@supacloud/cli 0.31.0 → 0.33.0

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 (3) hide show
  1. package/README.md +29 -0
  2. package/dist/index.js +287 -33
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -440,6 +440,35 @@ Use `--data_mode full_clone` only for an explicitly approved non-sensitive or
440
440
  masked debugging dataset. Whole-database replacement is an administrator-only
441
441
  break-glass API mode and is intentionally not exposed by this project CLI.
442
442
 
443
+ ## SupaCloud Lite CLI adapter
444
+
445
+ Lite can be used from its standalone `supacloud-lite` CLI and from the main
446
+ `supacloud-cli` through the local-only `lite` module. The adapter never calls
447
+ the Management API, never invokes the official Supabase CLI, and never treats a
448
+ PGlite data directory as a Postgres DSN.
449
+
450
+ ```bash
451
+ supacloud-cli lite migrate --project_dir .
452
+ supacloud-cli lite status --project_dir .
453
+ supacloud-cli lite db_diff --project_dir . --file add_accounts
454
+ supacloud-cli lite db_pull --project_dir . --file remote_schema
455
+ supacloud-cli lite gen_types --project_dir . --output src/database.types.ts
456
+ supacloud-cli lite snapshot_create --project_dir . --output backups/lite.tar.gz
457
+ supacloud-cli lite doctor --project_dir . --json
458
+ supacloud-cli lite start --project_dir . --port 54321
459
+ ```
460
+
461
+ The adapter resolves the executable in this order:
462
+
463
+ 1. `SUPACLOUD_LITE_CLI_BIN`
464
+ 2. `<workdir>/node_modules/@supacloud/lite/dist/launcher.cjs`
465
+ 3. `supacloud-lite` on `PATH`
466
+
467
+ Install `@supacloud/lite` or provide an explicit binary before using the
468
+ adapter. Lite actions are local-only, so Management API context and project
469
+ refs are not required. The `supabase` module remains the official CLI adapter;
470
+ use it for upstream Supabase CLI actions and Management-backed remote pushes.
471
+
443
472
  ## Official Supabase CLI adapter
444
473
 
445
474
  The `supabase` command group is a thin, allowlisted adapter around the official
package/dist/index.js CHANGED
@@ -6471,6 +6471,24 @@ var ACTION_POLICY = {
6471
6471
  local: ["version", "migration_new", "db_diff", "db_reset", "db_pull", "db_dump", "migration_list", "gen_types"],
6472
6472
  write: ["push"]
6473
6473
  },
6474
+ lite: {
6475
+ local: [
6476
+ "version",
6477
+ "start",
6478
+ "migrate",
6479
+ "status",
6480
+ "keys",
6481
+ "gen_types",
6482
+ "db_reset",
6483
+ "db_diff",
6484
+ "db_pull",
6485
+ "snapshot_create",
6486
+ "snapshot_restore",
6487
+ "upgrade",
6488
+ "inspect",
6489
+ "doctor"
6490
+ ]
6491
+ },
6474
6492
  auth: {
6475
6493
  read: ["list_users", "get_user", "list_providers", "get_provider", "supported_providers", "get_settings", "get_config", "get_oauth_server"],
6476
6494
  write: ["generate_link", "configure_provider", "update_provider", "disable_provider", "wechat_mini", "wechat_open", "update_settings", "update_config", "migrate_oauth_server"]
@@ -12100,6 +12118,7 @@ Actions: routes, upsert_route, update_route, delete_route, config, get_certifica
12100
12118
  managed_upstream: optional(stringEnum(["edge-functions"]), "[upsert_route/update_route] 托管上游(同步 Edge Function)"),
12101
12119
  upstream_tls_insecure_skip_verify: optional(Type.Boolean(), "[upsert_route/update_route] 上游 TLS 跳过校验"),
12102
12120
  static_root: optional(Type.String(), "[upsert_route/update_route] 静态站点根目录"),
12121
+ spa: optional(Type.Boolean(), "[upsert_route/update_route] 是否启用 SPA 单页回退"),
12103
12122
  protocol: optional(stringEnum(["http", "https"]), "[upsert_route/update_route] 可选请求协议匹配"),
12104
12123
  redirect_to: optional(Type.String(), "[upsert_route/update_route] 带固定 host 的绝对 http(s) 目标,可在末尾使用 {http.request.uri}"),
12105
12124
  redirect_status: withDescription(redirectStatus, "[upsert_route/update_route] 重定向状态码,默认 308"),
@@ -12146,6 +12165,7 @@ Actions: routes, upsert_route, update_route, delete_route, config, get_certifica
12146
12165
  managed_upstream,
12147
12166
  upstream_tls_insecure_skip_verify,
12148
12167
  static_root,
12168
+ spa,
12149
12169
  protocol,
12150
12170
  redirect_to,
12151
12171
  redirect_status,
@@ -12195,6 +12215,8 @@ Actions: routes, upsert_route, update_route, delete_route, config, get_certifica
12195
12215
  body.upstream_tls_insecure_skip_verify = upstream_tls_insecure_skip_verify;
12196
12216
  if (static_root !== undefined)
12197
12217
  body.static_root = static_root;
12218
+ if (spa !== undefined)
12219
+ body.spa = spa;
12198
12220
  if (protocol !== undefined)
12199
12221
  body.protocol = protocol;
12200
12222
  if (redirect_to !== undefined)
@@ -12232,6 +12254,8 @@ Actions: routes, upsert_route, update_route, delete_route, config, get_certifica
12232
12254
  body.upstream_tls_insecure_skip_verify = upstream_tls_insecure_skip_verify;
12233
12255
  if (static_root !== undefined)
12234
12256
  body.static_root = static_root;
12257
+ if (spa !== undefined)
12258
+ body.spa = spa;
12235
12259
  if (protocol !== undefined)
12236
12260
  body.protocol = protocol;
12237
12261
  if (redirect_to !== undefined)
@@ -12888,10 +12912,236 @@ function registerSupabaseCliTools(server, options = {}) {
12888
12912
  }, (request) => executeSupabaseAction(request, runtime));
12889
12913
  }
12890
12914
 
12915
+ // src/shared/tools/lite-cli-tools.ts
12916
+ import { spawn as spawn2 } from "node:child_process";
12917
+ import { existsSync as existsSync6, statSync as statSync4 } from "node:fs";
12918
+ import { join as join4, resolve as resolve4 } from "node:path";
12919
+ function requireWorkdir(workdir, fallback) {
12920
+ const resolved = resolve4(workdir || fallback);
12921
+ if (!existsSync6(resolved) || !statSync4(resolved).isDirectory()) {
12922
+ throw new Error(`Lite workdir not found: ${resolved}`);
12923
+ }
12924
+ return resolved;
12925
+ }
12926
+ function optionalFlag(args, flag, value) {
12927
+ if (value !== undefined)
12928
+ args.push(flag, String(value));
12929
+ }
12930
+ function booleanFlag(args, flag, value) {
12931
+ if (value === true)
12932
+ args.push(flag);
12933
+ }
12934
+ function buildLiteArgs(request) {
12935
+ const args = [];
12936
+ if (request.action === "version")
12937
+ return ["--version"];
12938
+ switch (request.action) {
12939
+ case "start":
12940
+ case "migrate":
12941
+ case "status":
12942
+ case "keys":
12943
+ case "upgrade":
12944
+ case "inspect":
12945
+ case "doctor":
12946
+ args.push(request.action);
12947
+ break;
12948
+ case "gen_types":
12949
+ args.push("gen", "types");
12950
+ break;
12951
+ case "db_reset":
12952
+ args.push("db", "reset");
12953
+ break;
12954
+ case "db_diff":
12955
+ args.push("db", "diff");
12956
+ break;
12957
+ case "db_pull":
12958
+ args.push("db", "pull");
12959
+ if (request.file)
12960
+ args.push(request.file);
12961
+ break;
12962
+ case "snapshot_create":
12963
+ args.push("snapshot", "create");
12964
+ break;
12965
+ case "snapshot_restore":
12966
+ if (!request.snapshot_file)
12967
+ throw new Error("snapshot_restore requires --snapshot_file");
12968
+ args.push("snapshot", "restore", request.snapshot_file);
12969
+ break;
12970
+ default:
12971
+ throw new Error(`Unsupported Lite CLI action: ${String(request.action)}`);
12972
+ }
12973
+ optionalFlag(args, "--project-dir", request.project_dir);
12974
+ optionalFlag(args, "--state-dir", request.state_dir);
12975
+ optionalFlag(args, "--data-dir", request.data_dir);
12976
+ optionalFlag(args, "--storage-dir", request.storage_dir);
12977
+ optionalFlag(args, "--storage-backend", request.storage_backend);
12978
+ optionalFlag(args, "--s3-prefix", request.s3_prefix);
12979
+ optionalFlag(args, "--engine", request.engine);
12980
+ optionalFlag(args, "--host", request.host);
12981
+ optionalFlag(args, "--port", request.port);
12982
+ optionalFlag(args, "--api-url", request.api_url);
12983
+ optionalFlag(args, "--site-url", request.site_url);
12984
+ optionalFlag(args, "--replication-profile", request.replication_profile);
12985
+ optionalFlag(args, "--replication-host", request.replication_host);
12986
+ optionalFlag(args, "--replication-port", request.replication_port);
12987
+ optionalFlag(args, "--replication-allow-cidrs", request.replication_allow_cidrs);
12988
+ optionalFlag(args, "--powersync-tables", request.powersync_tables);
12989
+ optionalFlag(args, "--replication-tls-cert", request.replication_tls_cert);
12990
+ optionalFlag(args, "--replication-tls-key", request.replication_tls_key);
12991
+ optionalFlag(args, "--output", request.output);
12992
+ optionalFlag(args, "--file", request.action === "db_diff" ? request.file : undefined);
12993
+ booleanFlag(args, "--service-role", request.service_role);
12994
+ booleanFlag(args, "--force", request.force);
12995
+ booleanFlag(args, "--memory", request.memory);
12996
+ booleanFlag(args, "--json", request.json);
12997
+ return args;
12998
+ }
12999
+ function resolveLiteCommand(workdir, environment = process.env) {
13000
+ const explicitBinary = environment.SUPACLOUD_LITE_CLI_BIN?.trim();
13001
+ if (explicitBinary) {
13002
+ if (explicitBinary.includes("\x00"))
13003
+ throw new Error("Invalid SUPACLOUD_LITE_CLI_BIN");
13004
+ return [explicitBinary];
13005
+ }
13006
+ const localPackageEntry = join4(resolve4(workdir), "node_modules", "@supacloud", "lite", "dist", "launcher.cjs");
13007
+ if (existsSync6(localPackageEntry))
13008
+ return [process.execPath, localPackageEntry];
13009
+ return ["supacloud-lite"];
13010
+ }
13011
+ function spawnLiteCommand(command, workdir, environment, inheritOutput) {
13012
+ const [executable, ...commandArguments] = command;
13013
+ return new Promise((resolveExecution, rejectExecution) => {
13014
+ const child = spawn2(executable, commandArguments, {
13015
+ cwd: workdir,
13016
+ env: { ...environment, NO_COLOR: "1" },
13017
+ shell: false,
13018
+ stdio: inheritOutput ? ["inherit", "inherit", "inherit"] : ["ignore", "pipe", "pipe"],
13019
+ windowsHide: true
13020
+ });
13021
+ const forwardSignal = (signal) => child.kill(signal);
13022
+ process.once("SIGINT", forwardSignal);
13023
+ process.once("SIGTERM", forwardSignal);
13024
+ const cleanup = () => {
13025
+ process.off("SIGINT", forwardSignal);
13026
+ process.off("SIGTERM", forwardSignal);
13027
+ };
13028
+ if (inheritOutput) {
13029
+ child.once("error", (error) => {
13030
+ cleanup();
13031
+ rejectExecution(error);
13032
+ });
13033
+ child.once("close", (exitCode) => {
13034
+ cleanup();
13035
+ resolveExecution({ exitCode: exitCode ?? 1, stdout: "", stderr: "" });
13036
+ });
13037
+ return;
13038
+ }
13039
+ if (!child.stdout || !child.stderr) {
13040
+ cleanup();
13041
+ rejectExecution(new Error("Lite CLI child process did not expose piped output"));
13042
+ return;
13043
+ }
13044
+ let standardOutput = "";
13045
+ let standardError = "";
13046
+ child.stdout.setEncoding("utf8");
13047
+ child.stderr.setEncoding("utf8");
13048
+ child.stdout.on("data", (chunk) => {
13049
+ standardOutput += chunk;
13050
+ });
13051
+ child.stderr.on("data", (chunk) => {
13052
+ standardError += chunk;
13053
+ });
13054
+ child.once("error", (error) => {
13055
+ cleanup();
13056
+ rejectExecution(error);
13057
+ });
13058
+ child.once("close", (exitCode) => {
13059
+ cleanup();
13060
+ resolveExecution({ exitCode: exitCode ?? 1, stdout: standardOutput, stderr: standardError });
13061
+ });
13062
+ });
13063
+ }
13064
+ async function executeLiteCli(request, environment, fallbackWorkdir) {
13065
+ const workdir = requireWorkdir(request.workdir, fallbackWorkdir);
13066
+ const command = [...resolveLiteCommand(workdir, environment), ...buildLiteArgs({ ...request, workdir })];
13067
+ try {
13068
+ return await spawnLiteCommand(command, workdir, environment, request.action === "start");
13069
+ } catch (error) {
13070
+ const failureMessage = error instanceof Error ? error.message : String(error);
13071
+ throw new Error([
13072
+ "SupaCloud Lite CLI could not be started.",
13073
+ "Install @supacloud/lite, put supacloud-lite on PATH, or set SUPACLOUD_LITE_CLI_BIN.",
13074
+ failureMessage
13075
+ ].join(" "));
13076
+ }
13077
+ }
13078
+ function formatExecutionText2(action, execution) {
13079
+ const combinedOutput = [execution.stdout.trim(), execution.stderr.trim()].filter(Boolean).join(`
13080
+ `);
13081
+ const heading = execution.exitCode === 0 ? `✅ SupaCloud Lite ${action} completed` : `❌ SupaCloud Lite ${action} failed (exit ${execution.exitCode})`;
13082
+ return combinedOutput ? `${heading}
13083
+ ${combinedOutput}` : heading;
13084
+ }
13085
+ function registerLiteCliTools(server, options = {}) {
13086
+ const environment = options.environment || process.env;
13087
+ const fallbackWorkdir = options.currentWorkingDirectory || process.cwd();
13088
+ const execute = options.executeLiteCli || ((request) => executeLiteCli(request, environment, fallbackWorkdir));
13089
+ server.tool("lite", "Controlled adapter for the local SupaCloud Lite CLI. Lite actions are local-only and never use the Management API or official Supabase CLI.", {
13090
+ action: withDescription(stringEnum([
13091
+ "version",
13092
+ "start",
13093
+ "migrate",
13094
+ "status",
13095
+ "keys",
13096
+ "gen_types",
13097
+ "db_reset",
13098
+ "db_diff",
13099
+ "db_pull",
13100
+ "snapshot_create",
13101
+ "snapshot_restore",
13102
+ "upgrade",
13103
+ "inspect",
13104
+ "doctor"
13105
+ ]), "Lite CLI action"),
13106
+ workdir: optional(Type.String(), "[*] Process working directory (default: current directory)"),
13107
+ project_dir: optional(Type.String(), "[*] Project containing supabase/"),
13108
+ state_dir: optional(Type.String(), "[*] Lite state root"),
13109
+ data_dir: optional(Type.String(), "[*] PGlite/native data directory"),
13110
+ storage_dir: optional(Type.String(), "[*] Object storage directory"),
13111
+ storage_backend: optional(stringEnum(["fs", "memory", "s3"]), "[*] Storage backend"),
13112
+ s3_prefix: optional(Type.String(), "[*] S3 object key prefix"),
13113
+ engine: optional(stringEnum(["pglite", "native"]), "[*] Database engine"),
13114
+ host: optional(Type.String(), "[start] Listen host"),
13115
+ port: optional(Type.Number(), "[start] Listen port"),
13116
+ api_url: optional(Type.String(), "[start] Public API URL"),
13117
+ site_url: optional(Type.String(), "[start] Auth site URL"),
13118
+ replication_profile: optional(stringEnum(["powersync"]), "[start/doctor] Replication profile"),
13119
+ replication_host: optional(Type.String(), "[start] Replication listener host"),
13120
+ replication_port: optional(Type.Number(), "[start] Replication listener port"),
13121
+ replication_allow_cidrs: optional(Type.String(), "[start] Replication client CIDRs"),
13122
+ powersync_tables: optional(Type.String(), "[start] PowerSync publication tables"),
13123
+ replication_tls_cert: optional(Type.String(), "[start] Replication TLS certificate"),
13124
+ replication_tls_key: optional(Type.String(), "[start] Replication TLS private key"),
13125
+ output: optional(Type.String(), "[gen_types/snapshot_create/upgrade] Output path"),
13126
+ file: optional(Type.String(), "[db_diff/db_pull] Migration suffix or name"),
13127
+ snapshot_file: optional(Type.String(), "[snapshot_restore] Snapshot archive"),
13128
+ service_role: optional(Type.Boolean(), "[keys] Also print the service_role key"),
13129
+ force: optional(Type.Boolean(), "[snapshot_restore] Replace non-empty restore targets"),
13130
+ memory: optional(Type.Boolean(), "[*] Use an in-memory PGlite database"),
13131
+ json: optional(Type.Boolean(), "[doctor] Emit machine-readable output")
13132
+ }, async (request) => {
13133
+ const execution = await execute(request);
13134
+ return {
13135
+ isError: execution.exitCode !== 0,
13136
+ content: [{ type: "text", text: formatExecutionText2(request.action, execution) }]
13137
+ };
13138
+ });
13139
+ }
13140
+
12891
13141
  // src/shared/tools/ai-tools.ts
12892
13142
  import {
12893
13143
  cpSync,
12894
- existsSync as existsSync6,
13144
+ existsSync as existsSync7,
12895
13145
  lstatSync as lstatSync2,
12896
13146
  mkdirSync as mkdirSync2,
12897
13147
  mkdtempSync as mkdtempSync2,
@@ -12901,13 +13151,13 @@ import {
12901
13151
  rmSync as rmSync2
12902
13152
  } from "node:fs";
12903
13153
  import { homedir as homedir2 } from "node:os";
12904
- import { dirname as dirname2, join as join4, relative as relative2, resolve as resolve4, sep as sep2 } from "node:path";
13154
+ import { dirname as dirname2, join as join5, relative as relative2, resolve as resolve5, sep as sep2 } from "node:path";
12905
13155
  import { fileURLToPath } from "node:url";
12906
13156
  var SKILL_NAME = "supacloud-cli";
12907
13157
  function regularFiles(rootDirectory, currentDirectory = rootDirectory) {
12908
13158
  const files = [];
12909
13159
  for (const directoryEntry of readdirSync3(currentDirectory, { withFileTypes: true })) {
12910
- const entryPath = join4(currentDirectory, directoryEntry.name);
13160
+ const entryPath = join5(currentDirectory, directoryEntry.name);
12911
13161
  if (directoryEntry.isSymbolicLink())
12912
13162
  throw new Error(`Skill directories cannot contain symlinks: ${entryPath}`);
12913
13163
  if (directoryEntry.isDirectory())
@@ -12918,13 +13168,13 @@ function regularFiles(rootDirectory, currentDirectory = rootDirectory) {
12918
13168
  return files.sort();
12919
13169
  }
12920
13170
  function directoriesMatch(sourceDirectory, destinationDirectory) {
12921
- if (!existsSync6(destinationDirectory) || !lstatSync2(destinationDirectory).isDirectory())
13171
+ if (!existsSync7(destinationDirectory) || !lstatSync2(destinationDirectory).isDirectory())
12922
13172
  return false;
12923
13173
  const sourceFiles = regularFiles(sourceDirectory);
12924
13174
  const destinationFiles = regularFiles(destinationDirectory);
12925
13175
  if (sourceFiles.join("\x00") !== destinationFiles.join("\x00"))
12926
13176
  return false;
12927
- return sourceFiles.every((file) => readFileSync5(join4(sourceDirectory, file)).equals(readFileSync5(join4(destinationDirectory, file))));
13177
+ return sourceFiles.every((file) => readFileSync5(join5(sourceDirectory, file)).equals(readFileSync5(join5(destinationDirectory, file))));
12928
13178
  }
12929
13179
  function backupTimestamp(now) {
12930
13180
  return now.toISOString().replace(/[-:.]/g, "");
@@ -12933,7 +13183,7 @@ function availableBackupDirectory(destinationDirectory, now) {
12933
13183
  const baseDirectory = `${destinationDirectory}.backup-${backupTimestamp(now)}`;
12934
13184
  let candidate = baseDirectory;
12935
13185
  let suffix = 2;
12936
- while (existsSync6(candidate)) {
13186
+ while (existsSync7(candidate)) {
12937
13187
  candidate = `${baseDirectory}-${suffix}`;
12938
13188
  suffix += 1;
12939
13189
  }
@@ -12941,8 +13191,8 @@ function availableBackupDirectory(destinationDirectory, now) {
12941
13191
  }
12942
13192
  function stagedSkill(sourceDirectory, targetRoot) {
12943
13193
  mkdirSync2(targetRoot, { recursive: true });
12944
- const stagingRoot = mkdtempSync2(join4(targetRoot, ".supacloud-cli-install-"));
12945
- const stagingSkill = join4(stagingRoot, SKILL_NAME);
13194
+ const stagingRoot = mkdtempSync2(join5(targetRoot, ".supacloud-cli-install-"));
13195
+ const stagingSkill = join5(stagingRoot, SKILL_NAME);
12946
13196
  try {
12947
13197
  cpSync(sourceDirectory, stagingSkill, { recursive: true, errorOnExist: true });
12948
13198
  } catch (error) {
@@ -12974,13 +13224,13 @@ function replaceSkill(sourceDirectory, targetRoot, destinationDirectory, backupD
12974
13224
  }
12975
13225
  }
12976
13226
  function skillSummary(request, action, files, backupDirectory) {
12977
- const sourceDirectory = resolve4(request.sourceDirectory);
12978
- const targetRoot = resolve4(request.targetRoot);
13227
+ const sourceDirectory = resolve5(request.sourceDirectory);
13228
+ const targetRoot = resolve5(request.targetRoot);
12979
13229
  return {
12980
13230
  name: SKILL_NAME,
12981
13231
  sourceDirectory,
12982
13232
  targetRoot,
12983
- destinationDirectory: join4(targetRoot, SKILL_NAME),
13233
+ destinationDirectory: join5(targetRoot, SKILL_NAME),
12984
13234
  action,
12985
13235
  mode: request.mode,
12986
13236
  changed: action !== "none",
@@ -12989,14 +13239,14 @@ function skillSummary(request, action, files, backupDirectory) {
12989
13239
  };
12990
13240
  }
12991
13241
  function installSkill(request) {
12992
- const sourceDirectory = resolve4(request.sourceDirectory);
12993
- const targetRoot = resolve4(request.targetRoot);
12994
- const destinationDirectory = join4(targetRoot, SKILL_NAME);
12995
- if (!existsSync6(join4(sourceDirectory, "SKILL.md"))) {
13242
+ const sourceDirectory = resolve5(request.sourceDirectory);
13243
+ const targetRoot = resolve5(request.targetRoot);
13244
+ const destinationDirectory = join5(targetRoot, SKILL_NAME);
13245
+ if (!existsSync7(join5(sourceDirectory, "SKILL.md"))) {
12996
13246
  throw new Error(`Bundled SupaCloud CLI skill not found: ${sourceDirectory}`);
12997
13247
  }
12998
13248
  const files = regularFiles(sourceDirectory);
12999
- if (!existsSync6(destinationDirectory))
13249
+ if (!existsSync7(destinationDirectory))
13000
13250
  return installNewSkill(request, files);
13001
13251
  if (directoriesMatch(sourceDirectory, destinationDirectory)) {
13002
13252
  return skillSummary(request, "none", files, null);
@@ -13007,17 +13257,17 @@ function installSkill(request) {
13007
13257
  return installReplacementSkill(request, files);
13008
13258
  }
13009
13259
  function installNewSkill(request, files) {
13010
- const sourceDirectory = resolve4(request.sourceDirectory);
13011
- const targetRoot = resolve4(request.targetRoot);
13260
+ const sourceDirectory = resolve5(request.sourceDirectory);
13261
+ const targetRoot = resolve5(request.targetRoot);
13012
13262
  if (request.mode === "write") {
13013
- createSkill(sourceDirectory, targetRoot, join4(targetRoot, SKILL_NAME));
13263
+ createSkill(sourceDirectory, targetRoot, join5(targetRoot, SKILL_NAME));
13014
13264
  }
13015
13265
  return skillSummary(request, "create", files, null);
13016
13266
  }
13017
13267
  function installReplacementSkill(request, files) {
13018
- const sourceDirectory = resolve4(request.sourceDirectory);
13019
- const targetRoot = resolve4(request.targetRoot);
13020
- const destinationDirectory = join4(targetRoot, SKILL_NAME);
13268
+ const sourceDirectory = resolve5(request.sourceDirectory);
13269
+ const targetRoot = resolve5(request.targetRoot);
13270
+ const destinationDirectory = join5(targetRoot, SKILL_NAME);
13021
13271
  const backupDirectory = availableBackupDirectory(destinationDirectory, request.now);
13022
13272
  if (request.mode === "write") {
13023
13273
  replaceSkill(sourceDirectory, targetRoot, destinationDirectory, backupDirectory);
@@ -13026,15 +13276,15 @@ function installReplacementSkill(request, files) {
13026
13276
  }
13027
13277
  function resolveDefaultCodexSkillRoot(environment = process.env, homeDirectory = homedir2()) {
13028
13278
  const codexHome = environment.CODEX_HOME?.trim();
13029
- return join4(resolve4(codexHome || join4(homeDirectory, ".codex")), "skills");
13279
+ return join5(resolve5(codexHome || join5(homeDirectory, ".codex")), "skills");
13030
13280
  }
13031
13281
  function resolveBundledSkillDirectory(moduleUrl = import.meta.url) {
13032
13282
  const moduleDirectory = dirname2(fileURLToPath(moduleUrl));
13033
13283
  const candidates = [
13034
- resolve4(moduleDirectory, "../../../skills", SKILL_NAME),
13035
- resolve4(moduleDirectory, "../skills", SKILL_NAME)
13284
+ resolve5(moduleDirectory, "../../../skills", SKILL_NAME),
13285
+ resolve5(moduleDirectory, "../skills", SKILL_NAME)
13036
13286
  ];
13037
- const skillDirectory = candidates.find((candidate) => existsSync6(join4(candidate, "SKILL.md")));
13287
+ const skillDirectory = candidates.find((candidate) => existsSync7(join5(candidate, "SKILL.md")));
13038
13288
  if (!skillDirectory)
13039
13289
  throw new Error("Bundled SupaCloud CLI skill is missing from this installation");
13040
13290
  return skillDirectory;
@@ -13056,7 +13306,7 @@ function registerAiTools(server) {
13056
13306
  name: SKILL_NAME,
13057
13307
  sourceDirectory,
13058
13308
  defaultTargetRoot,
13059
- defaultDestination: join4(defaultTargetRoot, SKILL_NAME)
13309
+ defaultDestination: join5(defaultTargetRoot, SKILL_NAME)
13060
13310
  });
13061
13311
  }
13062
13312
  return textResponse(installSkill({
@@ -13071,8 +13321,8 @@ function registerAiTools(server) {
13071
13321
 
13072
13322
  // src/shared/tools/scheduled-function-tools.ts
13073
13323
  import { randomUUID } from "node:crypto";
13074
- import { readFileSync as readFileSync6, statSync as statSync4 } from "node:fs";
13075
- import { resolve as resolve5 } from "node:path";
13324
+ import { readFileSync as readFileSync6, statSync as statSync5 } from "node:fs";
13325
+ import { resolve as resolve6 } from "node:path";
13076
13326
  import { isDeepStrictEqual } from "node:util";
13077
13327
  var HEADER_NAME_PATTERN = /^[!#$%&'*+.^_`|~0-9A-Za-z-]{1,128}$/;
13078
13328
  var ENVIRONMENT_NAME_PATTERN2 = /^[A-Za-z_][A-Za-z0-9_]{0,255}$/;
@@ -13156,8 +13406,8 @@ function validScheduledFunctionCron(expression) {
13156
13406
  function readScheduleBodyFile(bodyPathInput) {
13157
13407
  if (!bodyPathInput.trim())
13158
13408
  throw new Error("'body_file' must be a path");
13159
- const bodyPath = resolve5(bodyPathInput);
13160
- const bodyStat = statSync4(bodyPath);
13409
+ const bodyPath = resolve6(bodyPathInput);
13410
+ const bodyStat = statSync5(bodyPath);
13161
13411
  if (!bodyStat.isFile() || bodyStat.size > MAX_BODY_FILE_BYTES) {
13162
13412
  throw new Error("Scheduled Function body file must be a regular file no larger than 1 MiB");
13163
13413
  }
@@ -14115,7 +14365,7 @@ function registerReleaseTools(server, http, options = {}) {
14115
14365
  // package.json
14116
14366
  var package_default = {
14117
14367
  name: "@supacloud/cli",
14118
- version: "0.31.0",
14368
+ version: "0.33.0",
14119
14369
  description: "Project-scoped CLI for SupaCloud users",
14120
14370
  type: "module",
14121
14371
  main: "./dist/index.js",
@@ -14380,6 +14630,9 @@ EXAMPLES
14380
14630
  ${preferredCommand} supabase db_diff --schema public --name add_accounts
14381
14631
  ${preferredCommand} supabase push --ref abc123 --dir supabase/migrations --dry_run
14382
14632
  ${preferredCommand} supabase db_dump --db_url "postgresql://..." --file backups/schema.sql
14633
+ ${preferredCommand} lite migrate --project_dir .
14634
+ ${preferredCommand} lite start --project_dir . --port 54321
14635
+ ${preferredCommand} lite doctor --project_dir . --json
14383
14636
  ${preferredCommand} branch create --name feature-auth --data_mode schema_only
14384
14637
  ${preferredCommand} branch promotion_plan --branch_ref preview123
14385
14638
  ${preferredCommand} branch promote --branch_ref preview123 --plan_checksum <sha256>
@@ -14432,6 +14685,7 @@ function createCliTools(context, confirmProduction) {
14432
14685
  projectRef: context.projectRef || undefined,
14433
14686
  readOnly: context.readOnly
14434
14687
  })));
14688
+ Object.assign(tools, captureTools((server) => registerLiteCliTools(server)));
14435
14689
  Object.assign(tools, captureTools((server) => registerAiTools(server)));
14436
14690
  const registerContextAwareHelp = () => {
14437
14691
  tools.project = {
@@ -14593,7 +14847,7 @@ async function main() {
14593
14847
  return;
14594
14848
  }
14595
14849
  const cliTools = createCliTools(context, globalOptions.confirmProduction);
14596
- if (args.length === 1 && !["ai", "supabase"].includes(args[0]) && cliTools[args[0]]) {
14850
+ if (args.length === 1 && !["ai", "supabase", "lite"].includes(args[0]) && cliTools[args[0]]) {
14597
14851
  const result = await cliTools[args[0]].callback({});
14598
14852
  if (result?.content && Array.isArray(result.content)) {
14599
14853
  for (const chunk of result.content) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@supacloud/cli",
3
- "version": "0.31.0",
3
+ "version": "0.33.0",
4
4
  "description": "Project-scoped CLI for SupaCloud users",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",