Merge branch 'feature/drizzle-rls-real-auth'
# Conflicts: # CLAUDE.md # package.json # src/app/api/auth/[...nextauth]/route.ts # src/app/login/LoginClient.tsx # src/auth.config.ts # src/components/admin/AdminSidebar.tsx # src/lib/admin-permissions-types.ts # src/lib/admin-permissions.ts # src/lib/auth.ts # src/middleware.ts
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* DESTRUCTIVE: drops and recreates the `route_commerce` database, then
|
||||
* applies all migrations and seeds.
|
||||
*
|
||||
* Usage:
|
||||
* npm run db:reset
|
||||
*
|
||||
* Use only in dev. Requires sudo-less access to a postgres superuser.
|
||||
*/
|
||||
require("dotenv").config({ path: ".env.local" });
|
||||
const { execSync } = require("node:child_process");
|
||||
const url = process.env.DATABASE_URL;
|
||||
if (!url) {
|
||||
console.error("❌ DATABASE_URL is not set");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const m = url.match(/postgres(?:ql)?:\/\/([^:]+):[^@]+@([^:]+):(\d+)\/(.+)/);
|
||||
if (!m) {
|
||||
console.error("❌ Could not parse DATABASE_URL");
|
||||
process.exit(1);
|
||||
}
|
||||
const [, user, host, port, db] = m;
|
||||
const adminUrl = url.replace(/\/[^/]+$/, "/postgres");
|
||||
|
||||
console.log(`⚠️ DROPPING and recreating ${db} on ${host}:${port} as ${user}`);
|
||||
try {
|
||||
execSync(
|
||||
`psql "${adminUrl}" -c "DROP DATABASE IF EXISTS ${db};" -c "CREATE DATABASE ${db} OWNER ${user};"`,
|
||||
{ stdio: "inherit" },
|
||||
);
|
||||
console.log("✓ Database recreated");
|
||||
} catch (err) {
|
||||
console.error("❌ Failed to drop/create database. Try with sudo:");
|
||||
console.error(
|
||||
` sudo -u postgres psql -c "DROP DATABASE IF EXISTS ${db};" -c "CREATE DATABASE ${db} OWNER ${user};"`,
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
execSync("npm run db:migrate", { stdio: "inherit" });
|
||||
execSync("npm run db:seed", { stdio: "inherit" });
|
||||
console.log("✅ Database reset, migrated, and seeded");
|
||||
@@ -0,0 +1,91 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Apply Postgres migrations from `db/migrations/*.sql` in lexical order.
|
||||
* Wraps the whole thing in a transaction; tracks applied files in
|
||||
* `_migrations` so re-runs are safe.
|
||||
*
|
||||
* Usage:
|
||||
* npm run db:migrate
|
||||
*
|
||||
* Replaces the old `supabase/push-migrations.js` — that script was
|
||||
* hardcoded to a Supabase URL. This one reads `DATABASE_URL` directly.
|
||||
*/
|
||||
require("dotenv").config({ path: ".env.local" });
|
||||
|
||||
const fs = require("node:fs");
|
||||
const path = require("node:path");
|
||||
const { Client } = require("pg");
|
||||
|
||||
const MIGRATIONS_DIR = path.join(__dirname, "..", "db", "migrations");
|
||||
|
||||
async function main() {
|
||||
const url = process.env.DATABASE_ADMIN_URL ?? process.env.DATABASE_URL;
|
||||
if (!url) {
|
||||
console.error("❌ DATABASE_URL (or DATABASE_ADMIN_URL) is not set in .env.local");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const client = new Client({ connectionString: url });
|
||||
await client.connect();
|
||||
|
||||
try {
|
||||
await client.query(`
|
||||
CREATE TABLE IF NOT EXISTS _migrations (
|
||||
filename TEXT PRIMARY KEY,
|
||||
applied_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
)
|
||||
`);
|
||||
|
||||
const files = fs
|
||||
.readdirSync(MIGRATIONS_DIR)
|
||||
.filter((f) => f.endsWith(".sql"))
|
||||
.sort();
|
||||
|
||||
if (files.length === 0) {
|
||||
console.log("No migration files found in db/migrations/");
|
||||
return;
|
||||
}
|
||||
|
||||
const { rows: applied } = await client.query(
|
||||
`SELECT filename FROM _migrations`,
|
||||
);
|
||||
const appliedSet = new Set(applied.map((r) => r.filename));
|
||||
|
||||
let appliedNow = 0;
|
||||
for (const file of files) {
|
||||
if (appliedSet.has(file)) {
|
||||
console.log(`✓ ${file} (already applied)`);
|
||||
continue;
|
||||
}
|
||||
const sql = fs.readFileSync(path.join(MIGRATIONS_DIR, file), "utf8");
|
||||
console.log(`→ Applying ${file}...`);
|
||||
try {
|
||||
await client.query("BEGIN");
|
||||
await client.query(sql);
|
||||
await client.query(`INSERT INTO _migrations (filename) VALUES ($1)`, [
|
||||
file,
|
||||
]);
|
||||
await client.query("COMMIT");
|
||||
appliedNow += 1;
|
||||
console.log(`✓ ${file}`);
|
||||
} catch (err) {
|
||||
await client.query("ROLLBACK");
|
||||
console.error(`✗ ${file} failed:`, err.message);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
console.log(
|
||||
`\n✅ Done. ${appliedNow} new migration(s) applied. ${
|
||||
files.length - appliedNow
|
||||
} already current.`,
|
||||
);
|
||||
} finally {
|
||||
await client.end();
|
||||
}
|
||||
}
|
||||
|
||||
main().catch((err) => {
|
||||
console.error(err);
|
||||
process.exit(1);
|
||||
});
|
||||
Reference in New Issue
Block a user