Splits seed bootstrap (ports/roles/profile) into a shared module so
two seed entry points can share it:
- pnpm db:seed realistic NocoDB-shaped fixture (existing)
- pnpm db:seed:synthetic 12 clients, one per pipeline stage + archive
variants (rich metadata for restore wizard)
scripts/db-reset.ts truncates all data tables (preserves migrations);
guarded by --confirm and a localhost host check. Companion npm scripts:
- pnpm db:reset
- pnpm db:reseed:realistic
- pnpm db:reseed:synthetic
scripts/dev-open-browser.ts launches a headed Chromium with no viewport
override (uses the host monitor's natural size), pre-fills the login
form for the requested role.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
81 lines
2.7 KiB
TypeScript
81 lines
2.7 KiB
TypeScript
/**
|
|
* Launch a headed Chromium with NO viewport override so it adopts the
|
|
* host monitor's natural size — useful when you want to drive the CRM
|
|
* manually and have full-screen real estate.
|
|
*
|
|
* Pre-fills the login form for the synthetic admin (admin@portnimara.test
|
|
* / SuperAdmin12345!) but does not submit; press Enter when ready.
|
|
*
|
|
* The script keeps running until the browser window is closed by the
|
|
* user or until you Ctrl-C.
|
|
*
|
|
* pnpm tsx scripts/dev-open-browser.ts # super_admin
|
|
* pnpm tsx scripts/dev-open-browser.ts sales_agent
|
|
* pnpm tsx scripts/dev-open-browser.ts viewer
|
|
* pnpm tsx scripts/dev-open-browser.ts --no-prefill
|
|
*/
|
|
|
|
import 'dotenv/config';
|
|
import { chromium } from 'playwright';
|
|
|
|
const USERS: Record<string, { email: string; password: string }> = {
|
|
super_admin: { email: 'admin@portnimara.test', password: 'SuperAdmin12345!' },
|
|
sales_agent: { email: 'agent@portnimara.test', password: 'SalesAgent12345!' },
|
|
viewer: { email: 'viewer@portnimara.test', password: 'ViewerUser12345!' },
|
|
};
|
|
|
|
const BASE_URL = process.env.DEV_BASE_URL ?? 'http://localhost:3000';
|
|
|
|
async function main() {
|
|
const args = process.argv.slice(2);
|
|
const noPrefill = args.includes('--no-prefill');
|
|
const role =
|
|
args.find((a) => !a.startsWith('--')) && USERS[args.find((a) => !a.startsWith('--'))!]
|
|
? args.find((a) => !a.startsWith('--'))!
|
|
: 'super_admin';
|
|
const user = USERS[role]!;
|
|
|
|
console.log(`Launching headed Chromium → ${BASE_URL}`);
|
|
console.log(` role: ${role} (${user.email})`);
|
|
|
|
const browser = await chromium.launch({
|
|
headless: false,
|
|
args: ['--start-maximized'],
|
|
});
|
|
|
|
// viewport: null lets the page fill the OS window. Combined with
|
|
// --start-maximized this matches the host monitor's natural size.
|
|
const context = await browser.newContext({ viewport: null });
|
|
const page = await context.newPage();
|
|
|
|
await page.goto(`${BASE_URL}/login`);
|
|
|
|
if (!noPrefill) {
|
|
try {
|
|
await page.waitForSelector('#email', { timeout: 5000 });
|
|
await page.fill('#email', user.email);
|
|
await page.fill('#password', user.password);
|
|
console.log(' Login form pre-filled — press Enter in the browser to submit.');
|
|
} catch {
|
|
console.log(' Could not find login form (page may have redirected).');
|
|
}
|
|
}
|
|
|
|
console.log('');
|
|
console.log("Browser is open. Close it when you're done; the script will exit.");
|
|
console.log('Or Ctrl-C here to force-quit.');
|
|
|
|
// Keep the process alive until the browser window is closed.
|
|
await new Promise<void>((resolve) => {
|
|
browser.on('disconnected', () => resolve());
|
|
});
|
|
|
|
await browser.close().catch(() => undefined);
|
|
process.exit(0);
|
|
}
|
|
|
|
main().catch((err) => {
|
|
console.error('Open-browser failed:', err);
|
|
process.exit(1);
|
|
});
|