@vibecodemax/cli 0.1.11 → 0.1.12

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.
Files changed (2) hide show
  1. package/dist/cli.js +112 -0
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -473,6 +473,92 @@ function runSupabaseCommand(args, dependencyManager) {
473
473
  fail("SUPABASE_CLI_ERROR", [result.stderr, result.stdout].find(isNonEmptyString) || `Supabase CLI ${args.join(" ")} failed.`, 1, { exitCode: result.status ?? 1 });
474
474
  }
475
475
  }
476
+ function runSupabaseCommandCapture(args, dependencyManager) {
477
+ const runner = getSupabaseRunnerCommand(dependencyManager);
478
+ const result = spawnSync(runner.command, [...runner.args, ...args], {
479
+ cwd: process.cwd(),
480
+ encoding: "utf8",
481
+ });
482
+ if (result.status !== 0) {
483
+ fail("SUPABASE_CLI_ERROR", [result.stderr, result.stdout].find(isNonEmptyString) || `Supabase CLI ${args.join(" ")} failed.`, 1, { exitCode: result.status ?? 1 });
484
+ }
485
+ return result.stdout || "";
486
+ }
487
+ function extractMigrationVersion(value) {
488
+ if (!isNonEmptyString(value))
489
+ return "";
490
+ const match = value.trim().match(/^(\d{14})/);
491
+ return match ? match[1] : "";
492
+ }
493
+ function listLocalMigrationVersions(cwd = process.cwd()) {
494
+ const migrationsDir = path.join(cwd, "supabase", "migrations");
495
+ let entries = [];
496
+ try {
497
+ entries = fs.readdirSync(migrationsDir);
498
+ }
499
+ catch {
500
+ return [];
501
+ }
502
+ return [...new Set(entries.map((entry) => extractMigrationVersion(entry)).filter(Boolean))].sort();
503
+ }
504
+ function collectVersionsFromRows(rows, keyCandidates) {
505
+ const values = new Set();
506
+ for (const row of rows) {
507
+ if (!row || typeof row !== "object")
508
+ continue;
509
+ const record = row;
510
+ for (const key of keyCandidates) {
511
+ const version = extractMigrationVersion(record[key]);
512
+ if (version) {
513
+ values.add(version);
514
+ }
515
+ }
516
+ }
517
+ return Array.from(values).sort();
518
+ }
519
+ function parseMigrationListOutput(raw) {
520
+ const trimmed = raw.trim();
521
+ if (!trimmed) {
522
+ return { localVersions: [], remoteVersions: [] };
523
+ }
524
+ try {
525
+ const parsed = JSON.parse(trimmed);
526
+ const rows = Array.isArray(parsed)
527
+ ? parsed
528
+ : Array.isArray(parsed?.migrations)
529
+ ? (parsed.migrations)
530
+ : Array.isArray(parsed?.data)
531
+ ? (parsed.data)
532
+ : null;
533
+ if (!rows) {
534
+ fail("INVALID_MIGRATION_LIST_OUTPUT", "Supabase migration list JSON output did not contain a rows array.");
535
+ }
536
+ const localVersions = collectVersionsFromRows(rows, [
537
+ "local",
538
+ "local_version",
539
+ "localVersion",
540
+ "localMigration",
541
+ "local_migration",
542
+ ]);
543
+ const remoteVersions = collectVersionsFromRows(rows, [
544
+ "remote",
545
+ "remote_version",
546
+ "remoteVersion",
547
+ "remoteMigration",
548
+ "remote_migration",
549
+ ]);
550
+ if (localVersions.length === 0 && remoteVersions.length === 0) {
551
+ fail("INVALID_MIGRATION_LIST_OUTPUT", "Supabase migration list JSON output did not include recognizable local or remote migration version fields.");
552
+ }
553
+ return { localVersions, remoteVersions };
554
+ }
555
+ catch (error) {
556
+ if (error instanceof SyntaxError) {
557
+ fail("INVALID_MIGRATION_LIST_OUTPUT", "Supabase migration list output was not valid JSON. Upgrade the local Supabase CLI if it does not support --output json for migration list.");
558
+ }
559
+ throw error;
560
+ }
561
+ }
476
562
  async function supabaseManagementApiRequest(params) {
477
563
  const response = await fetch(`${MANAGEMENT_API_BASE}${params.endpoint}`, {
478
564
  method: params.method,
@@ -752,6 +838,29 @@ async function linkBaseSupabaseProject(flags) {
752
838
  bootstrapKeysWritten: writes.bootstrapKeysWritten,
753
839
  });
754
840
  }
841
+ function preflightBaseMigrationState(flags) {
842
+ const dependencyManager = normalizeDependencyManagerFlag(flags);
843
+ const localVersions = listLocalMigrationVersions();
844
+ const raw = runSupabaseCommandCapture(["migration", "list", "--linked", "--output", "json"], dependencyManager);
845
+ const parsed = parseMigrationListOutput(raw);
846
+ const localSet = new Set(localVersions);
847
+ const remoteSet = new Set(parsed.remoteVersions);
848
+ const localOnlyVersions = localVersions.filter((version) => !remoteSet.has(version));
849
+ const remoteOnlyVersions = parsed.remoteVersions.filter((version) => !localSet.has(version));
850
+ const blocked = remoteOnlyVersions.length > 0;
851
+ printJson({
852
+ ok: true,
853
+ command: "base preflight-migration-state",
854
+ localVersions,
855
+ remoteVersions: parsed.remoteVersions,
856
+ localOnlyVersions,
857
+ remoteOnlyVersions,
858
+ blocked,
859
+ requiresUserDecision: blocked,
860
+ decisionOptions: blocked ? ["reset", "repair", "relink"] : ["continue"],
861
+ status: blocked ? "diverged" : "aligned_or_recoverable",
862
+ });
863
+ }
755
864
  async function supabaseAdminRequest(params) {
756
865
  const response = await fetch(`${params.supabaseUrl}${params.endpoint}`, {
757
866
  method: params.method,
@@ -1952,6 +2061,7 @@ async function main() {
1952
2061
  "base check-supabase-access-token",
1953
2062
  "base create-supabase-project",
1954
2063
  "base link-supabase-project",
2064
+ "base preflight-migration-state",
1955
2065
  "admin ensure-admin",
1956
2066
  "storage check-supabase-context",
1957
2067
  "storage setup-supabase",
@@ -1987,6 +2097,8 @@ async function main() {
1987
2097
  return createBaseSupabaseProject(flags);
1988
2098
  if (command === "base" && subcommand === "link-supabase-project")
1989
2099
  return linkBaseSupabaseProject(flags);
2100
+ if (command === "base" && subcommand === "preflight-migration-state")
2101
+ return preflightBaseMigrationState(flags);
1990
2102
  if (command === "admin" && subcommand === "ensure-admin")
1991
2103
  return ensureAdmin(flags);
1992
2104
  if (command === "storage" && subcommand === "check-supabase-context")
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vibecodemax/cli",
3
- "version": "0.1.11",
3
+ "version": "0.1.12",
4
4
  "description": "VibeCodeMax CLI — local provider setup for bootstrap and project configuration",
5
5
  "type": "module",
6
6
  "bin": {