@vibecodemax/cli 0.1.5 → 0.1.6

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 +44 -30
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -1,6 +1,5 @@
1
1
  #!/usr/bin/env node
2
2
  import * as fs from "node:fs";
3
- import * as os from "node:os";
4
3
  import * as path from "node:path";
5
4
  import { spawnSync } from "node:child_process";
6
5
  import { checkS3Context, setupS3Storage, smokeTestS3 } from "./storageS3.js";
@@ -41,6 +40,19 @@ function fail(code, message, exitCode = 1, extra = {}) {
41
40
  printJson({ ok: false, code, message, ...extra });
42
41
  process.exit(exitCode);
43
42
  }
43
+ /** Extract a human-readable error message from a Supabase/provider JSON response. */
44
+ function extractErrorMessage(json) {
45
+ if (!json || typeof json !== "object")
46
+ return null;
47
+ const obj = json;
48
+ if (isNonEmptyString(obj.error))
49
+ return obj.error;
50
+ if (isNonEmptyString(obj.message))
51
+ return obj.message;
52
+ if (isNonEmptyString(obj.msg))
53
+ return obj.msg;
54
+ return null;
55
+ }
44
56
  function parseArgs(argv) {
45
57
  const [command, ...rest] = argv;
46
58
  let subcommand;
@@ -630,6 +642,20 @@ function runShellCommand(command, cwd) {
630
642
  }
631
643
  return typeof result.stdout === "string" ? result.stdout.trim() : "";
632
644
  }
645
+ function runLinkedSupabaseCommand(command, cwd, failureCode, fallbackMessage) {
646
+ const result = spawnSync(process.env.SHELL || "/bin/zsh", ["-lc", command], {
647
+ cwd,
648
+ env: process.env,
649
+ encoding: "utf8",
650
+ });
651
+ if (result.status !== 0) {
652
+ const message = [result.stderr, result.stdout]
653
+ .map((value) => (typeof value === "string" ? value.trim() : ""))
654
+ .find(Boolean) || fallbackMessage;
655
+ fail(failureCode, message);
656
+ }
657
+ return typeof result.stdout === "string" ? result.stdout.trim() : "";
658
+ }
633
659
  function normalizeStorageMimeCategories(rawValue) {
634
660
  const requested = rawValue
635
661
  .split(",")
@@ -708,13 +734,7 @@ async function storageRequest(params) {
708
734
  json = null;
709
735
  }
710
736
  if (!response.ok) {
711
- const message = isNonEmptyString(json?.error)
712
- ? json.error
713
- : isNonEmptyString(json?.message)
714
- ? json.message
715
- : isNonEmptyString(json?.msg)
716
- ? json.msg
717
- : `Supabase returned ${response.status}`;
737
+ const message = extractErrorMessage(json) || `Supabase returned ${response.status}`;
718
738
  fail("SUPABASE_STORAGE_ERROR", message, 1, { status: response.status });
719
739
  }
720
740
  return json;
@@ -764,14 +784,14 @@ async function readStorageBucket(supabaseUrl, serviceRoleKey, bucketId) {
764
784
  }
765
785
  if (response.status === 404)
766
786
  return null;
787
+ // Supabase may return 400 (not 404) for non-existent buckets in some API versions
788
+ if (response.status === 400) {
789
+ const extracted = extractErrorMessage(json);
790
+ if (extracted && /bucket\s*not\s*found/i.test(extracted))
791
+ return null;
792
+ }
767
793
  if (!response.ok) {
768
- const message = isNonEmptyString(json?.error)
769
- ? json.error
770
- : isNonEmptyString(json?.message)
771
- ? json.message
772
- : isNonEmptyString(json?.msg)
773
- ? json.msg
774
- : `Supabase returned ${response.status}`;
794
+ const message = extractErrorMessage(json) || `Supabase returned ${response.status}`;
775
795
  fail("SUPABASE_STORAGE_ERROR", message, 1, { status: response.status });
776
796
  }
777
797
  return json && typeof json === "object" ? json : {};
@@ -822,13 +842,6 @@ async function ensureStorageBucket(supabaseUrl, serviceRoleKey, bucketId, isPubl
822
842
  verified: true,
823
843
  };
824
844
  }
825
- function verifyRequiredStoragePolicies(dumpContent) {
826
- const normalized = dumpContent.toLowerCase();
827
- const missing = STORAGE_REQUIRED_POLICY_NAMES.filter((policyName) => !normalized.includes(`create policy \"${policyName}\"`));
828
- if (missing.length > 0) {
829
- fail("STORAGE_POLICY_VERIFY_FAILED", `Missing required storage policies after local Supabase CLI apply: ${missing.join(", ")}.`);
830
- }
831
- }
832
845
  function buildStorageHealthcheckObjectPath(runId) {
833
846
  return `${STORAGE_HEALTHCHECK_PREFIX}/${runId}/upload.txt`;
834
847
  }
@@ -869,20 +882,14 @@ async function setupSupabaseStorage(flags) {
869
882
  const supabaseRunner = getSupabaseRunner(dependencyManager);
870
883
  const mimeCategories = resolveStorageMimeCategories(flags);
871
884
  const allowedMimeTypes = expandStorageMimeCategories(mimeCategories);
885
+ const migrations = discoverStorageMigrationFiles(cwd);
886
+ runLinkedSupabaseCommand(`${supabaseRunner} db push --linked`, cwd, "STORAGE_POLICY_MIGRATION_APPLY_FAILED", "Failed to apply storage migrations to the linked Supabase project.");
872
887
  const publicBucket = await ensureStorageBucket(supabaseUrl, serviceRoleKey, STORAGE_PUBLIC_BUCKET, true, allowedMimeTypes);
873
888
  const privateBucket = await ensureStorageBucket(supabaseUrl, serviceRoleKey, STORAGE_PRIVATE_BUCKET, false, allowedMimeTypes);
874
889
  mergeEnvFile(envLocalPath, {
875
890
  SUPABASE_PUBLIC_BUCKET: STORAGE_PUBLIC_BUCKET,
876
891
  SUPABASE_PRIVATE_BUCKET: STORAGE_PRIVATE_BUCKET,
877
892
  });
878
- const migrations = discoverStorageMigrationFiles(cwd);
879
- runShellCommand(`${supabaseRunner} db push --linked`, cwd);
880
- const dumpDir = fs.mkdtempSync(path.join(os.tmpdir(), "vibecodemax-storage-dump-"));
881
- const dumpPath = path.join(dumpDir, "storage.sql");
882
- runShellCommand(`${supabaseRunner} db dump --linked --schema storage -f ${shellQuote(dumpPath)} >/dev/null`, cwd);
883
- const dumpContent = readFileIfExists(dumpPath);
884
- verifyRequiredStoragePolicies(dumpContent);
885
- fs.rmSync(dumpDir, { recursive: true, force: true });
886
893
  printJson({
887
894
  ok: true,
888
895
  command: "storage setup-supabase",
@@ -898,6 +905,7 @@ async function setupSupabaseStorage(flags) {
898
905
  policyMigrationsDiscovered: true,
899
906
  policyMigrationsApplied: true,
900
907
  policiesVerified: true,
908
+ policyVerificationMethod: "linked_db_push",
901
909
  envWritten: ["SUPABASE_PUBLIC_BUCKET", "SUPABASE_PRIVATE_BUCKET"],
902
910
  });
903
911
  }
@@ -967,6 +975,12 @@ async function main() {
967
975
  });
968
976
  return;
969
977
  }
978
+ // Handle --help for any resolved command before dispatching (avoids live API calls)
979
+ if (flags.help || flags.h) {
980
+ const resolvedCommand = subcommand ? `${command} ${subcommand}` : command;
981
+ printJson({ ok: true, command: resolvedCommand, help: true, message: `Usage: npx @vibecodemax/cli ${resolvedCommand} [options]` });
982
+ return;
983
+ }
970
984
  if (command === "read-setup-state")
971
985
  return readSetupState();
972
986
  if (command === "admin" && subcommand === "ensure-admin")
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vibecodemax/cli",
3
- "version": "0.1.5",
3
+ "version": "0.1.6",
4
4
  "description": "VibeCodeMax CLI — local provider setup for bootstrap and project configuration",
5
5
  "type": "module",
6
6
  "bin": {