212 lines
12 KiB
TypeScript
212 lines
12 KiB
TypeScript
/**
|
||
* Fix script: Re-insert historical migration records and apply new migration
|
||
* using a direct pg connection (no Payload init to avoid dev-mode push loops).
|
||
*
|
||
* Run with: pnpm tsx --env-file=.env scripts/fix-migrations.ts
|
||
*/
|
||
import { createRequire } from 'module'
|
||
const require = createRequire(import.meta.url)
|
||
|
||
const { Pool } = require(
|
||
'd:/Project/gbmake/gb-payload/node_modules/.pnpm/pg@8.16.3/node_modules/pg'
|
||
)
|
||
|
||
const pool = new Pool({
|
||
connectionString: process.env.DATABASE_URL ?? 'postgres://gb-payload:123123@localhost/gb-payload',
|
||
})
|
||
|
||
async function run(sql: string, params: any[] = []) {
|
||
const result = await pool.query(sql, params)
|
||
return result.rows
|
||
}
|
||
|
||
// ── Check current migration state ────────────────────────────────────────────
|
||
console.log('📋 Checking payload_migrations table...')
|
||
const existing = await run(`SELECT name FROM payload_migrations ORDER BY id`)
|
||
const existingNames = new Set(existing.map((r: any) => r.name))
|
||
console.log('Currently recorded:', existingNames.size > 0 ? [...existingNames] : '(none)')
|
||
|
||
// ── Mark all historical migrations as done ────────────────────────────────────
|
||
const historyMigrations = [
|
||
'20260208_171142',
|
||
'20260212_193303',
|
||
'20260212_202303',
|
||
'20260222_170233',
|
||
'hero_slider_simplify',
|
||
'product_recommendations_simplify',
|
||
]
|
||
|
||
for (const name of historyMigrations) {
|
||
if (!existingNames.has(name)) {
|
||
await run(
|
||
`INSERT INTO payload_migrations (name, batch, updated_at, created_at) VALUES ($1, 1, now(), now())`,
|
||
[name]
|
||
)
|
||
console.log(`✅ Marked done: ${name}`)
|
||
} else {
|
||
console.log(`⏭️ Already recorded: ${name}`)
|
||
}
|
||
}
|
||
|
||
// ── Skip if new migration already applied ─────────────────────────────────────
|
||
if (existingNames.has('20260223_disassembly_refactor')) {
|
||
console.log('\n⏭️ Migration 20260223_disassembly_refactor already applied.')
|
||
await pool.end()
|
||
process.exit(0)
|
||
}
|
||
|
||
// ── Show what disassembly tables exist ───────────────────────────────────────
|
||
const disasmTables = await run(
|
||
`SELECT tablename FROM pg_tables WHERE schemaname='public' AND tablename LIKE 'disassembly%' ORDER BY tablename`
|
||
)
|
||
console.log('\nCurrent disassembly tables:', disasmTables.map((r: any) => r.tablename))
|
||
|
||
console.log('\n🔧 Applying: 20260223_disassembly_refactor ...')
|
||
|
||
try {
|
||
// 1. disassembly_components
|
||
await run(`CREATE TABLE IF NOT EXISTS disassembly_components (
|
||
id serial PRIMARY KEY NOT NULL,
|
||
label varchar NOT NULL,
|
||
start_coordinate_x numeric DEFAULT 0 NOT NULL,
|
||
start_coordinate_y numeric DEFAULT 0 NOT NULL,
|
||
start_radius numeric DEFAULT 20 NOT NULL,
|
||
updated_at timestamp(3) with time zone DEFAULT now() NOT NULL,
|
||
created_at timestamp(3) with time zone DEFAULT now() NOT NULL
|
||
)`)
|
||
await run(`CREATE INDEX IF NOT EXISTS disassembly_components_updated_at_idx ON disassembly_components USING btree (updated_at)`)
|
||
await run(`CREATE INDEX IF NOT EXISTS disassembly_components_created_at_idx ON disassembly_components USING btree (created_at)`)
|
||
console.log(' ✅ disassembly_components')
|
||
|
||
// 2. disassembly_linked_products
|
||
await run(`CREATE TABLE IF NOT EXISTS disassembly_linked_products (
|
||
id serial PRIMARY KEY NOT NULL,
|
||
coordinate_x numeric DEFAULT 0 NOT NULL,
|
||
coordinate_y numeric DEFAULT 0 NOT NULL,
|
||
product_name varchar,
|
||
updated_at timestamp(3) with time zone DEFAULT now() NOT NULL,
|
||
created_at timestamp(3) with time zone DEFAULT now() NOT NULL
|
||
)`)
|
||
await run(`CREATE INDEX IF NOT EXISTS disassembly_linked_products_updated_at_idx ON disassembly_linked_products USING btree (updated_at)`)
|
||
await run(`CREATE INDEX IF NOT EXISTS disassembly_linked_products_created_at_idx ON disassembly_linked_products USING btree (created_at)`)
|
||
console.log(' ✅ disassembly_linked_products')
|
||
|
||
// 3. disassembly_components_rels
|
||
await run(`CREATE TABLE IF NOT EXISTS disassembly_components_rels (
|
||
id serial PRIMARY KEY NOT NULL,
|
||
"order" integer,
|
||
parent_id integer NOT NULL,
|
||
path varchar NOT NULL,
|
||
disassembly_linked_products_id integer
|
||
)`)
|
||
await run(`DO $$ BEGIN
|
||
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'disassembly_components_rels_parent_fk') THEN
|
||
ALTER TABLE disassembly_components_rels ADD CONSTRAINT disassembly_components_rels_parent_fk
|
||
FOREIGN KEY (parent_id) REFERENCES disassembly_components(id) ON DELETE cascade;
|
||
END IF;
|
||
END $$`)
|
||
await run(`DO $$ BEGIN
|
||
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'disassembly_components_rels_disassembly_linked_products_fk') THEN
|
||
ALTER TABLE disassembly_components_rels ADD CONSTRAINT disassembly_components_rels_disassembly_linked_products_fk
|
||
FOREIGN KEY (disassembly_linked_products_id) REFERENCES disassembly_linked_products(id) ON DELETE cascade;
|
||
END IF;
|
||
END $$`)
|
||
await run(`CREATE INDEX IF NOT EXISTS disassembly_components_rels_order_idx ON disassembly_components_rels USING btree ("order")`)
|
||
await run(`CREATE INDEX IF NOT EXISTS disassembly_components_rels_parent_idx ON disassembly_components_rels USING btree (parent_id)`)
|
||
await run(`CREATE INDEX IF NOT EXISTS disassembly_components_rels_path_idx ON disassembly_components_rels USING btree (path)`)
|
||
await run(`CREATE INDEX IF NOT EXISTS disassembly_components_rels_disassembly_linked_products_id_idx ON disassembly_components_rels USING btree (disassembly_linked_products_id)`)
|
||
console.log(' ✅ disassembly_components_rels')
|
||
|
||
// 4. disassembly_linked_products_rels
|
||
await run(`CREATE TABLE IF NOT EXISTS disassembly_linked_products_rels (
|
||
id serial PRIMARY KEY NOT NULL,
|
||
"order" integer,
|
||
parent_id integer NOT NULL,
|
||
path varchar NOT NULL,
|
||
products_id integer,
|
||
preorder_products_id integer
|
||
)`)
|
||
await run(`DO $$ BEGIN
|
||
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'disassembly_linked_products_rels_parent_fk') THEN
|
||
ALTER TABLE disassembly_linked_products_rels ADD CONSTRAINT disassembly_linked_products_rels_parent_fk
|
||
FOREIGN KEY (parent_id) REFERENCES disassembly_linked_products(id) ON DELETE cascade;
|
||
END IF;
|
||
END $$`)
|
||
await run(`DO $$ BEGIN
|
||
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'disassembly_linked_products_rels_products_fk') THEN
|
||
ALTER TABLE disassembly_linked_products_rels ADD CONSTRAINT disassembly_linked_products_rels_products_fk
|
||
FOREIGN KEY (products_id) REFERENCES products(id) ON DELETE cascade;
|
||
END IF;
|
||
END $$`)
|
||
await run(`DO $$ BEGIN
|
||
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'disassembly_linked_products_rels_preorder_products_fk') THEN
|
||
ALTER TABLE disassembly_linked_products_rels ADD CONSTRAINT disassembly_linked_products_rels_preorder_products_fk
|
||
FOREIGN KEY (preorder_products_id) REFERENCES preorder_products(id) ON DELETE cascade;
|
||
END IF;
|
||
END $$`)
|
||
await run(`CREATE INDEX IF NOT EXISTS disassembly_linked_products_rels_order_idx ON disassembly_linked_products_rels USING btree ("order")`)
|
||
await run(`CREATE INDEX IF NOT EXISTS disassembly_linked_products_rels_parent_idx ON disassembly_linked_products_rels USING btree (parent_id)`)
|
||
await run(`CREATE INDEX IF NOT EXISTS disassembly_linked_products_rels_path_idx ON disassembly_linked_products_rels USING btree (path)`)
|
||
await run(`CREATE INDEX IF NOT EXISTS disassembly_linked_products_rels_products_id_idx ON disassembly_linked_products_rels USING btree (products_id)`)
|
||
await run(`CREATE INDEX IF NOT EXISTS disassembly_linked_products_rels_preorder_products_id_idx ON disassembly_linked_products_rels USING btree (preorder_products_id)`)
|
||
console.log(' ✅ disassembly_linked_products_rels')
|
||
|
||
// 5. Update disassembly_pages_rels
|
||
await run(`ALTER TABLE disassembly_pages_rels DROP CONSTRAINT IF EXISTS disassembly_pages_rels_products_fk`)
|
||
await run(`ALTER TABLE disassembly_pages_rels DROP CONSTRAINT IF EXISTS disassembly_pages_rels_preorder_products_fk`)
|
||
await run(`DROP INDEX IF EXISTS disassembly_pages_rels_products_id_idx`)
|
||
await run(`DROP INDEX IF EXISTS disassembly_pages_rels_preorder_products_id_idx`)
|
||
const pc = await run(`SELECT 1 FROM information_schema.columns WHERE table_name='disassembly_pages_rels' AND column_name='products_id'`)
|
||
if (pc.length > 0) await run(`ALTER TABLE disassembly_pages_rels DROP COLUMN products_id`)
|
||
const prc = await run(`SELECT 1 FROM information_schema.columns WHERE table_name='disassembly_pages_rels' AND column_name='preorder_products_id'`)
|
||
if (prc.length > 0) await run(`ALTER TABLE disassembly_pages_rels DROP COLUMN preorder_products_id`)
|
||
await run(`ALTER TABLE disassembly_pages_rels ADD COLUMN IF NOT EXISTS disassembly_components_id integer`)
|
||
await run(`DO $$ BEGIN
|
||
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'disassembly_pages_rels_disassembly_components_fk') THEN
|
||
ALTER TABLE disassembly_pages_rels ADD CONSTRAINT disassembly_pages_rels_disassembly_components_fk
|
||
FOREIGN KEY (disassembly_components_id) REFERENCES disassembly_components(id) ON DELETE cascade;
|
||
END IF;
|
||
END $$`)
|
||
await run(`CREATE INDEX IF NOT EXISTS disassembly_pages_rels_disassembly_components_id_idx ON disassembly_pages_rels USING btree (disassembly_components_id)`)
|
||
console.log(' ✅ disassembly_pages_rels updated')
|
||
|
||
// 6. Update payload_locked_documents_rels
|
||
await run(`ALTER TABLE payload_locked_documents_rels ADD COLUMN IF NOT EXISTS disassembly_components_id integer`)
|
||
await run(`ALTER TABLE payload_locked_documents_rels ADD COLUMN IF NOT EXISTS disassembly_linked_products_id integer`)
|
||
await run(`DO $$ BEGIN
|
||
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'payload_locked_documents_rels_disassembly_components_fk') THEN
|
||
ALTER TABLE payload_locked_documents_rels ADD CONSTRAINT payload_locked_documents_rels_disassembly_components_fk
|
||
FOREIGN KEY (disassembly_components_id) REFERENCES disassembly_components(id) ON DELETE cascade;
|
||
END IF;
|
||
END $$`)
|
||
await run(`DO $$ BEGIN
|
||
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'payload_locked_documents_rels_disassembly_linked_products_fk') THEN
|
||
ALTER TABLE payload_locked_documents_rels ADD CONSTRAINT payload_locked_documents_rels_disassembly_linked_products_fk
|
||
FOREIGN KEY (disassembly_linked_products_id) REFERENCES disassembly_linked_products(id) ON DELETE cascade;
|
||
END IF;
|
||
END $$`)
|
||
await run(`CREATE INDEX IF NOT EXISTS payload_locked_documents_rels_disassembly_components_id_idx ON payload_locked_documents_rels USING btree (disassembly_components_id)`)
|
||
await run(`CREATE INDEX IF NOT EXISTS payload_locked_documents_rels_disassembly_linked_products_id_idx ON payload_locked_documents_rels USING btree (disassembly_linked_products_id)`)
|
||
console.log(' ✅ payload_locked_documents_rels updated')
|
||
|
||
// 7. Drop old array tables
|
||
await run(`DROP TABLE IF EXISTS disassembly_pages_components_linked_products CASCADE`)
|
||
await run(`DROP TABLE IF EXISTS disassembly_pages_components CASCADE`)
|
||
console.log(' ✅ Old array tables dropped')
|
||
|
||
// 8. Record migration
|
||
await run(
|
||
`INSERT INTO payload_migrations (name, batch, updated_at, created_at) VALUES ($1, 2, now(), now())`,
|
||
['20260223_disassembly_refactor']
|
||
)
|
||
console.log('\n🎉 Migration 20260223_disassembly_refactor applied successfully!')
|
||
|
||
} catch (err: any) {
|
||
console.error('\n❌ Error:', err?.message ?? err)
|
||
await pool.end()
|
||
process.exit(1)
|
||
}
|
||
|
||
await pool.end()
|
||
process.exit(0)
|