@beignet/cli 0.0.24 → 0.0.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/index.ts CHANGED
@@ -107,6 +107,27 @@ type DbFlags = {
107
107
  dryRun?: boolean;
108
108
  };
109
109
 
110
+ type DatabaseSchemaDialect = "sqlite" | "postgres" | "mysql";
111
+ type DatabaseSchemaTable = "audit" | "idempotency" | "outbox";
112
+
113
+ const databaseSchemaDialectChoices = [
114
+ "sqlite",
115
+ "postgres",
116
+ "mysql",
117
+ ] as const satisfies readonly DatabaseSchemaDialect[];
118
+
119
+ const databaseSchemaTableChoices = [
120
+ "audit",
121
+ "idempotency",
122
+ "outbox",
123
+ ] as const satisfies readonly DatabaseSchemaTable[];
124
+
125
+ type DbSchemaGenerateFlags = DbFlags & {
126
+ dialect?: DatabaseSchemaDialect;
127
+ tables?: readonly DatabaseSchemaTable[];
128
+ output?: string;
129
+ };
130
+
110
131
  type TaskRunFlags = {
111
132
  json?: boolean;
112
133
  input?: string;
@@ -142,6 +163,11 @@ type DoctorFlags = {
142
163
  format?: OutputFormat;
143
164
  };
144
165
 
166
+ type ProviderAuditFlags = {
167
+ json?: boolean;
168
+ cwd?: string;
169
+ };
170
+
145
171
  const parseString = (input: string): string => input;
146
172
  const parsePositiveInteger = (input: string): number => {
147
173
  const value = Number(input);
@@ -209,11 +235,38 @@ const lintFlagParameters = {
209
235
  format: formatFlag,
210
236
  } satisfies FlagParametersForType<LintFlags, CliContext>;
211
237
 
238
+ const providerAuditFlagParameters = {
239
+ json: jsonFlag,
240
+ cwd: cwdFlag,
241
+ } satisfies FlagParametersForType<ProviderAuditFlags, CliContext>;
242
+
212
243
  const dbFlagParameters = {
213
244
  json: jsonFlag,
214
245
  dryRun: dryRunFlag,
215
246
  } satisfies FlagParametersForType<DbFlags, CliContext>;
216
247
 
248
+ const dbSchemaGenerateFlagParameters = {
249
+ ...dbFlagParameters,
250
+ dialect: {
251
+ kind: "enum",
252
+ values: databaseSchemaDialectChoices,
253
+ optional: true,
254
+ brief:
255
+ "Drizzle dialect to generate for. Inferred from server/providers.ts when omitted.",
256
+ },
257
+ tables: {
258
+ kind: "enum",
259
+ values: databaseSchemaTableChoices,
260
+ optional: true,
261
+ variadic: ",",
262
+ brief:
263
+ "Provider tables to generate as a comma-separated list. Defaults to audit,idempotency,outbox.",
264
+ },
265
+ output: parsedStringFlag(
266
+ "Generated schema file. Defaults to infra/db/schema/beignet.ts.",
267
+ ),
268
+ } satisfies FlagParametersForType<DbSchemaGenerateFlags, CliContext>;
269
+
217
270
  const taskRunFlagParameters = {
218
271
  json: jsonFlag,
219
272
  input: parsedStringFlag("JSON input passed to the task schema."),
@@ -557,6 +610,44 @@ const mcpCommand = buildCommand<McpFlags, [], CliContext>({
557
610
  },
558
611
  });
559
612
 
613
+ const providerAuditCommand = buildCommand<ProviderAuditFlags, [], CliContext>({
614
+ docs: {
615
+ brief: "Audit installed Beignet provider setup.",
616
+ fullDescription:
617
+ "Reports installed provider packages, metadata validity, registration, provider env, required tables, app ports, and variants. This command is report-only; doctor remains the enforcement surface.",
618
+ },
619
+ parameters: {
620
+ flags: providerAuditFlagParameters,
621
+ },
622
+ loader: async () => {
623
+ const { auditProviders, formatProviderAudit } = await import(
624
+ "./provider-audit.js"
625
+ );
626
+
627
+ return async function runProviderAudit(
628
+ this: CliContext,
629
+ flags: ProviderAuditFlags,
630
+ ) {
631
+ const result = await auditProviders({ cwd: flags.cwd });
632
+ writeOutput(
633
+ this,
634
+ flags.json
635
+ ? JSON.stringify(result, null, 2)
636
+ : formatProviderAudit(result),
637
+ );
638
+ };
639
+ },
640
+ });
641
+
642
+ const providerRoutes = buildRouteMap({
643
+ docs: {
644
+ brief: "Inspect Beignet provider setup.",
645
+ },
646
+ routes: {
647
+ audit: providerAuditCommand,
648
+ },
649
+ });
650
+
560
651
  type DatabaseCommandName = "generate" | "migrate" | "reset" | "seed";
561
652
 
562
653
  function databaseCommand(command: DatabaseCommandName) {
@@ -591,6 +682,52 @@ function databaseCommand(command: DatabaseCommandName) {
591
682
  });
592
683
  }
593
684
 
685
+ const dbSchemaGenerateCommand = buildCommand<
686
+ DbSchemaGenerateFlags,
687
+ [],
688
+ CliContext
689
+ >({
690
+ docs: {
691
+ brief: "Generate provider-owned Drizzle schema exports.",
692
+ fullDescription:
693
+ "Writes an app-owned schema file that re-exports Beignet provider tables, then updates the schema index. Run beignet db generate afterward to let the app's Drizzle Kit script create migrations.",
694
+ },
695
+ parameters: {
696
+ flags: dbSchemaGenerateFlagParameters,
697
+ },
698
+ loader: async () => {
699
+ const { generateDatabaseSchema } = await import("./db.js");
700
+
701
+ return async function runDbSchemaGenerate(
702
+ this: CliContext,
703
+ flags: DbSchemaGenerateFlags,
704
+ ) {
705
+ const result = await generateDatabaseSchema({
706
+ dialect: flags.dialect,
707
+ tables: flags.tables,
708
+ output: flags.output,
709
+ dryRun: Boolean(flags.dryRun),
710
+ });
711
+
712
+ writeOutput(
713
+ this,
714
+ flags.json
715
+ ? JSON.stringify(result, null, 2)
716
+ : databaseSchemaGenerateNextSteps(result),
717
+ );
718
+ };
719
+ },
720
+ });
721
+
722
+ const dbSchemaRoutes = buildRouteMap({
723
+ docs: {
724
+ brief: "Generate Beignet database schema helpers.",
725
+ },
726
+ routes: {
727
+ generate: dbSchemaGenerateCommand,
728
+ },
729
+ });
730
+
594
731
  const dbRoutes = buildRouteMap({
595
732
  docs: {
596
733
  brief: "Run Beignet database lifecycle commands.",
@@ -599,6 +736,7 @@ const dbRoutes = buildRouteMap({
599
736
  generate: databaseCommand("generate"),
600
737
  migrate: databaseCommand("migrate"),
601
738
  reset: databaseCommand("reset"),
739
+ schema: dbSchemaRoutes,
602
740
  seed: databaseCommand("seed"),
603
741
  },
604
742
  });
@@ -1214,6 +1352,7 @@ Run npm create beignet@latest (or bun create beignet) to scaffold a new app.`,
1214
1352
  make: makeRoutes,
1215
1353
  mcp: mcpCommand,
1216
1354
  outbox: outboxRoutes,
1355
+ providers: providerRoutes,
1217
1356
  routes: routesCommand,
1218
1357
  schedule: scheduleRoutes,
1219
1358
  task: taskRoutes,
@@ -1278,6 +1417,18 @@ type DatabaseCommandNextStepsResult = {
1278
1417
  dryRun: boolean;
1279
1418
  };
1280
1419
 
1420
+ type DatabaseSchemaGenerateNextStepsResult = {
1421
+ cwd: string;
1422
+ dialect: DatabaseSchemaDialect;
1423
+ tables: DatabaseSchemaTable[];
1424
+ output: string;
1425
+ indexFile: string;
1426
+ createdFiles: string[];
1427
+ updatedFiles: string[];
1428
+ skippedFiles: string[];
1429
+ dryRun: boolean;
1430
+ };
1431
+
1281
1432
  type AppTaskRunNextStepsResult = {
1282
1433
  name: string;
1283
1434
  durationMs: number;
@@ -1432,7 +1583,12 @@ function isEnvRequiredProviderIntegration(
1432
1583
  );
1433
1584
  }
1434
1585
 
1435
- function changedFileLines(result: MakeNextStepsResult): {
1586
+ function changedFileLines(
1587
+ result: Pick<
1588
+ MakeNextStepsResult,
1589
+ "createdFiles" | "updatedFiles" | "skippedFiles"
1590
+ >,
1591
+ ): {
1436
1592
  changedFiles: string;
1437
1593
  skippedFiles: string;
1438
1594
  } {
@@ -1482,6 +1638,29 @@ Command:
1482
1638
  ${command}`;
1483
1639
  }
1484
1640
 
1641
+ function databaseSchemaGenerateNextSteps(
1642
+ result: DatabaseSchemaGenerateNextStepsResult,
1643
+ ): string {
1644
+ const { changedFiles, skippedFiles } = changedFileLines({
1645
+ createdFiles: result.createdFiles,
1646
+ updatedFiles: result.updatedFiles,
1647
+ skippedFiles: result.skippedFiles,
1648
+ });
1649
+ const prefix = result.dryRun ? "Would generate" : "Generated";
1650
+ const tables = result.tables.join(", ");
1651
+
1652
+ return `${prefix} Beignet ${result.dialect} database schema (${tables}) in ${result.cwd}
1653
+
1654
+ Changed files:
1655
+ ${changedFiles || " none"}
1656
+ ${skippedFiles ? `\nSkipped identical files:\n${skippedFiles}` : ""}
1657
+
1658
+ Next steps:
1659
+ Run beignet db generate to produce app-owned Drizzle migrations.
1660
+ Run beignet db migrate to apply the migration.
1661
+ Run beignet doctor --strict to check provider setup.`;
1662
+ }
1663
+
1485
1664
  function makeFeatureNextSteps(result: MakeNextStepsResult): string {
1486
1665
  return makeNextSteps(result, "feature slice", [
1487
1666
  "Use make feature for product capabilities and workflows. Use make resource when the concept is mostly CRUD-shaped.",