import { discoverPlugins } from '../src/servers/plugins/discover'; import { generatePluginSchemas } from '../src/servers/plugins/schema'; // Write `plugin-schemas.gen.ts` from whatever plugins are on disk. Runs as the first half of `db:push`. // // ── The bug this closes ── // // `officer_db/src/schema.ts` ends with `export * from './plugin-schemas.gen'` — UNCONDITIONAL, because // drizzle-kit needs one file listing every table. That generated file is gitignored (it describes this // machine, not the project), and until 2026-08-15 its only writer was `installPlugin`. // // So on a fresh clone the file did not exist, and `bun db:push` died with MODULE_NOT_FOUND before // creating a single table. That is exactly what `scripts/setup/officer-setup.sh` section 8 runs, so // setup failed at the schema step on any clean machine — and the only thing that would have written the // file was installing a plugin, which needs a working database. A deadlock, shipped. // // It is wired into the `db:push` SCRIPT rather than added as a setup step on purpose. Setup is not the // only caller: `pushSchema()` shells out to the same command, a developer types it by hand, and // `git clean -xfd` removes the file at any time. A step someone has to remember is one they only forget // once — the barrel now cannot be stale when push reads it, because push regenerates it. // // Empty is a correct answer, and the common one: a machine with no plugins gets a barrel with no // exports, which is what `schema.ts` needs in order to import it at all. const { plugins, broken } = await discoverPlugins(); // Reported, never thrown. A plugin with an unreadable manifest must not stop the platform's own tables // from being created — the same rule discovery follows everywhere else. for (const { appName, error } of broken) { console.warn(`[plugin-schemas] skipping ${appName}: ${error}`); } const withSchema = plugins.filter((p) => p.schema); generatePluginSchemas(plugins); console.log( withSchema.length ? `[plugin-schemas] ${withSchema.length} plugin schema(s): ${withSchema.map((p) => p.appName).join(', ')}` : '[plugin-schemas] no plugin schemas on disk — wrote an empty barrel', );