104 lines
3.3 KiB
TypeScript
104 lines
3.3 KiB
TypeScript
// Bun script — runs directly: bun run scripts/seed-projects.ts
|
|
// Idempotent: skips existing projects/pending-income by name
|
|
|
|
const BASE_URL = process.env.QUINN_MY_BASE_URL ?? 'http://localhost:3024';
|
|
const TOKEN = process.env.QUINN_MY_SERVICE_TOKEN ?? 'dev-service-token';
|
|
|
|
const headers = {
|
|
'Content-Type': 'application/json',
|
|
Authorization: `Bearer ${TOKEN}`,
|
|
};
|
|
|
|
function log(msg: string): void {
|
|
process.stdout.write(`${msg}\n`);
|
|
}
|
|
|
|
async function apiFetch(path: string, init?: RequestInit): Promise<unknown> {
|
|
const res = await fetch(`${BASE_URL}${path}`, { headers, ...init });
|
|
if (!res.ok) {
|
|
const body = await res.text().catch(() => '');
|
|
throw new Error(`${init?.method ?? 'GET'} ${path} → ${res.status}: ${body}`);
|
|
}
|
|
return res.json();
|
|
}
|
|
|
|
async function main() {
|
|
// ── Projects ──────────────────────────────────────────────────────────────
|
|
const projects = (await apiFetch('/api/projects')) as Array<{ name: string }>;
|
|
const existingNames = new Set(projects.map((p) => p.name));
|
|
|
|
const projectSeeds = [
|
|
{
|
|
name: 'CVG + LA Tour',
|
|
kind: 'tour',
|
|
status: 'planned',
|
|
startedAt: '2026-04-26',
|
|
endedAt: '2026-05-21',
|
|
budgetCap: 4900,
|
|
},
|
|
{
|
|
name: 'Fire Wings Tattoo',
|
|
kind: 'body-mod',
|
|
status: 'planned',
|
|
startedAt: '2026-05-10',
|
|
endedAt: null,
|
|
budgetCap: 3000,
|
|
},
|
|
{
|
|
name: 'LA Content Shoot',
|
|
kind: 'shoot',
|
|
status: 'planned',
|
|
startedAt: '2026-05-05',
|
|
endedAt: '2026-05-09',
|
|
budgetCap: 1700,
|
|
},
|
|
] as const;
|
|
|
|
for (const seed of projectSeeds) {
|
|
if (existingNames.has(seed.name)) {
|
|
log(`[skip] project "${seed.name}" already exists`);
|
|
continue;
|
|
}
|
|
await apiFetch('/api/projects', {
|
|
method: 'POST',
|
|
body: JSON.stringify(seed),
|
|
});
|
|
log(`[created] project "${seed.name}"`);
|
|
}
|
|
|
|
// ── Pending income ─────────────────────────────────────────────────────────
|
|
const pendingIncome = (await apiFetch('/api/pending-income')) as Array<{ source: string }>;
|
|
const existingSources = new Set(pendingIncome.map((r) => r.source));
|
|
|
|
const simsSource = 'Subs + simps';
|
|
if (existingSources.has(simsSource)) {
|
|
log(`[skip] pending-income "${simsSource}" already exists`);
|
|
} else {
|
|
await apiFetch('/api/pending-income', {
|
|
method: 'POST',
|
|
body: JSON.stringify({
|
|
source: simsSource,
|
|
amount: 5000,
|
|
expectedBy: '2026-04-25',
|
|
note: 'Weekly subs + two regulars',
|
|
status: 'pending',
|
|
}),
|
|
});
|
|
log(`[created] pending-income "${simsSource}"`);
|
|
}
|
|
|
|
// ── Savings position ───────────────────────────────────────────────────────
|
|
await apiFetch('/api/financials/savings', {
|
|
method: 'PUT',
|
|
body: JSON.stringify({ startingBalance: 4000 }),
|
|
});
|
|
log('[set] savings startingBalance = 4000');
|
|
|
|
log('Done.');
|
|
process.exit(0);
|
|
}
|
|
|
|
main().catch((err: unknown) => {
|
|
process.stderr.write(`[error] ${String(err)}\n`);
|
|
process.exit(1);
|
|
});
|