Files
av-planner/scripts/generate-seed.mjs
T
aarbitandClaude Sonnet 5 93cb4a9617 Seed the public catalog from domain/library.ts
- Catalog table ids (device_categories, port_types, cable_types,
  device_templates) switch from uuid to text so the existing stable,
  human-readable ids (pt-hdmi, dt-display, ...) survive the move
  instead of every diagram's references silently orphaning.
- supabase/seed.sql is generated (scripts/generate-seed.mjs), not
  hand-written, so the seed data can't drift from the actual source of
  truth in domain/library.ts. Re-run the script after editing the
  built-in library.
- Also committing ideas.md/organized-ideas.md, which have been driving
  every backend decision this whole project but were never actually
  checked in.

RLS test suite re-run clean (23/23) after both the schema change and
the seed.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017DUU6CnxECCDeqDNYJgr5x
2026-09-07 23:02:12 -05:00

63 lines
2.8 KiB
JavaScript

// Generates supabase/seed.sql from src/domain/library.ts, so the public
// catalog seed data is derived directly from the source of truth instead of
// hand-transcribed (and risking drift/typos). Run via: node scripts/generate-seed.mjs
import { BUILT_IN_CABLE_TYPES, BUILT_IN_DEVICE_CATEGORIES, BUILT_IN_DEVICE_TEMPLATES, BUILT_IN_PORT_TYPES } from '../src/domain/library.ts'
import { writeFileSync } from 'node:fs'
import { randomUUID } from 'node:crypto'
function sqlString(value) {
if (value === undefined || value === null) return 'null'
return `'${String(value).replace(/'/g, "''")}'`
}
function sqlTextArray(values) {
if (!values || values.length === 0) return "'{}'"
return `'{${values.map((v) => `"${v.replace(/"/g, '\\"')}"`).join(',')}}'`
}
const lines = []
lines.push('-- Generated by scripts/generate-seed.mjs from src/domain/library.ts. Do not hand-edit —')
lines.push('-- re-run the script after changing the built-in library instead.')
lines.push('-- Seeds the public catalog: is_public = true, owner_id = null (system-owned).')
lines.push('')
lines.push('-- Device categories')
for (const c of BUILT_IN_DEVICE_CATEGORIES) {
lines.push(
`insert into public.device_categories (id, name, is_public) values (${sqlString(c.id)}, ${sqlString(c.name)}, true);`,
)
}
lines.push('')
lines.push('-- Port types')
for (const pt of BUILT_IN_PORT_TYPES) {
lines.push(
`insert into public.port_types (id, name, category, family, compatible_family_ids, max_connections, is_public) values (${sqlString(pt.id)}, ${sqlString(pt.name)}, ${sqlString(pt.category)}, ${sqlString(pt.family)}, ${sqlTextArray(pt.compatibleFamilyIds)}, ${pt.maxConnections ?? 'null'}, true);`,
)
}
lines.push('')
lines.push('-- Cable types')
for (const ct of BUILT_IN_CABLE_TYPES) {
lines.push(
`insert into public.cable_types (id, name, family, family2, unit, is_public) values (${sqlString(ct.id)}, ${sqlString(ct.name)}, ${sqlString(ct.family)}, ${sqlString(ct.family2)}, ${sqlString(ct.unit)}, true);`,
)
}
lines.push('')
lines.push('-- Device templates + their ports')
for (const dt of BUILT_IN_DEVICE_TEMPLATES) {
lines.push(
`insert into public.device_templates (id, name, category_id, is_public) values (${sqlString(dt.id)}, ${sqlString(dt.name)}, ${sqlString(dt.category)}, true);`,
)
for (const [index, port] of dt.ports.entries()) {
lines.push(
`insert into public.device_template_ports (id, device_template_id, name, direction, port_type_id, sort_order) values (${sqlString(randomUUID())}, ${sqlString(dt.id)}, ${sqlString(port.name)}, ${sqlString(port.direction)}, ${sqlString(port.portTypeId)}, ${index});`,
)
}
}
lines.push('')
writeFileSync(new URL('../supabase/seed.sql', import.meta.url), lines.join('\n') + '\n')
console.log(`Wrote supabase/seed.sql (${lines.length} lines)`)