Files
biblical-guide.com/scripts/clone_vector_table.ts
andupetcu 196ca00194 Fix authentication state persistence and admin role display
- Implement complete authentication system with JWT token validation
- Add auth provider with persistent login state across page refreshes
- Create multilingual login/register forms with Material-UI components
- Fix token validation using raw SQL queries to bypass Prisma sync issues
- Add comprehensive error handling for expired/invalid tokens
- Create profile and settings pages with full i18n support
- Add proper user role management (admin/user) with database sync
- Implement secure middleware with CSRF protection and auth checks
- Add debug endpoints for troubleshooting authentication issues
- Fix Zustand store persistence for authentication state

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-21 01:06:30 +03:00

75 lines
2.8 KiB
TypeScript

import 'dotenv/config'
import { Pool } from 'pg'
async function main() {
const pool = new Pool({ connectionString: process.env.DATABASE_URL })
const schema = (process.env.VECTOR_SCHEMA || 'ai_bible').replace(/[^a-zA-Z0-9_]/g, '')
const source = `${schema}.bv_ro_fidela`
const target = `${schema}.bv_ro_cornilescu`
const client = await pool.connect()
try {
console.log('Cloning vector table from', source, 'to', target)
await client.query('BEGIN')
await client.query(`CREATE EXTENSION IF NOT EXISTS vector;`)
await client.query(`CREATE SCHEMA IF NOT EXISTS "${schema}";`)
// Create target table if not exists with same structure
await client.query(`
DO $$
BEGIN
IF NOT EXISTS (
SELECT 1 FROM information_schema.tables
WHERE table_schema = '${schema}' AND table_name = 'bv_ro_cornilescu') THEN
EXECUTE format('CREATE TABLE %I.%I (LIKE %I.%I INCLUDING ALL)', '${schema}', 'bv_ro_cornilescu', '${schema}', 'bv_ro_fidela');
END IF;
END$$;`)
// Insert rows if target empty
const cnt = await client.query(`SELECT count(*)::int AS c FROM ${target}`)
if ((cnt.rows?.[0]?.c ?? 0) === 0) {
console.log('Copying rows...')
await client.query(`
INSERT INTO ${target} (testament, book, chapter, verse, text_raw, text_norm, tsv, embedding, created_at, updated_at)
SELECT testament, book, chapter, verse, text_raw, text_norm, tsv, embedding, created_at, updated_at
FROM ${source}
ON CONFLICT DO NOTHING
`)
} else {
console.log('Target already has rows, skipping copy')
}
// Create indexes if not exist
await client.query(`
CREATE UNIQUE INDEX IF NOT EXISTS ux_ref_bv_ro_cornilescu ON ${target} (book, chapter, verse);
CREATE INDEX IF NOT EXISTS idx_tsv_bv_ro_cornilescu ON ${target} USING GIN (tsv);
CREATE INDEX IF NOT EXISTS idx_book_ch_bv_ro_cornilescu ON ${target} (book, chapter);
CREATE INDEX IF NOT EXISTS idx_testament_bv_ro_cornilescu ON ${target} (testament);
`)
await client.query('COMMIT')
console.log('Rows copied and indexes created. Running post-copy maintenance...')
// Run maintenance commands outside of transaction
await client.query(`VACUUM ANALYZE ${target};`)
try {
await client.query(`
CREATE INDEX IF NOT EXISTS idx_vec_ivfflat_bv_ro_cornilescu
ON ${target} USING ivfflat (embedding vector_cosine_ops)
WITH (lists = 100);
`)
} catch (e) {
console.warn('IVFFLAT index creation hit memory limits; skipping for now. You can create it later with higher maintenance_work_mem.')
}
console.log('Clone completed.')
} catch (e) {
await client.query('ROLLBACK')
console.error('Clone error:', e)
process.exit(1)
} finally {
client.release()
await pool.end()
}
}
main()