percher 0.5.6 → 0.5.8

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.
@@ -5069,11 +5069,11 @@ var require_tslib = __commonJS((exports, module) => {
5069
5069
  };
5070
5070
  __awaiter = function(thisArg, _arguments, P, generator) {
5071
5071
  function adopt(value) {
5072
- return value instanceof P ? value : new P(function(resolve7) {
5073
- resolve7(value);
5072
+ return value instanceof P ? value : new P(function(resolve6) {
5073
+ resolve6(value);
5074
5074
  });
5075
5075
  }
5076
- return new (P || (P = Promise))(function(resolve7, reject) {
5076
+ return new (P || (P = Promise))(function(resolve6, reject) {
5077
5077
  function fulfilled(value) {
5078
5078
  try {
5079
5079
  step(generator.next(value));
@@ -5089,7 +5089,7 @@ var require_tslib = __commonJS((exports, module) => {
5089
5089
  }
5090
5090
  }
5091
5091
  function step(result) {
5092
- result.done ? resolve7(result.value) : adopt(result.value).then(fulfilled, rejected);
5092
+ result.done ? resolve6(result.value) : adopt(result.value).then(fulfilled, rejected);
5093
5093
  }
5094
5094
  step((generator = generator.apply(thisArg, _arguments || [])).next());
5095
5095
  });
@@ -5318,14 +5318,14 @@ var require_tslib = __commonJS((exports, module) => {
5318
5318
  }, i);
5319
5319
  function verb(n) {
5320
5320
  i[n] = o[n] && function(v) {
5321
- return new Promise(function(resolve7, reject) {
5322
- v = o[n](v), settle(resolve7, reject, v.done, v.value);
5321
+ return new Promise(function(resolve6, reject) {
5322
+ v = o[n](v), settle(resolve6, reject, v.done, v.value);
5323
5323
  });
5324
5324
  };
5325
5325
  }
5326
- function settle(resolve7, reject, d, v) {
5326
+ function settle(resolve6, reject, d, v) {
5327
5327
  Promise.resolve(v).then(function(v2) {
5328
- resolve7({ value: v2, done: d });
5328
+ resolve6({ value: v2, done: d });
5329
5329
  }, reject);
5330
5330
  }
5331
5331
  };
@@ -8824,7 +8824,7 @@ var require_util = __commonJS((exports) => {
8824
8824
  }
8825
8825
  path = url2.path;
8826
8826
  }
8827
- var isAbsolute3 = exports.isAbsolute(path);
8827
+ var isAbsolute2 = exports.isAbsolute(path);
8828
8828
  var parts = path.split(/\/+/);
8829
8829
  for (var part, up = 0, i = parts.length - 1;i >= 0; i--) {
8830
8830
  part = parts[i];
@@ -8844,7 +8844,7 @@ var require_util = __commonJS((exports) => {
8844
8844
  }
8845
8845
  path = parts.join("/");
8846
8846
  if (path === "") {
8847
- path = isAbsolute3 ? "/" : ".";
8847
+ path = isAbsolute2 ? "/" : ".";
8848
8848
  }
8849
8849
  if (url2) {
8850
8850
  url2.path = path;
@@ -8853,7 +8853,7 @@ var require_util = __commonJS((exports) => {
8853
8853
  return path;
8854
8854
  }
8855
8855
  exports.normalize = normalize2;
8856
- function join18(aRoot, aPath) {
8856
+ function join17(aRoot, aPath) {
8857
8857
  if (aRoot === "") {
8858
8858
  aRoot = ".";
8859
8859
  }
@@ -8885,11 +8885,11 @@ var require_util = __commonJS((exports) => {
8885
8885
  }
8886
8886
  return joined;
8887
8887
  }
8888
- exports.join = join18;
8888
+ exports.join = join17;
8889
8889
  exports.isAbsolute = function(aPath) {
8890
8890
  return aPath.charAt(0) === "/" || urlRegexp.test(aPath);
8891
8891
  };
8892
- function relative4(aRoot, aPath) {
8892
+ function relative3(aRoot, aPath) {
8893
8893
  if (aRoot === "") {
8894
8894
  aRoot = ".";
8895
8895
  }
@@ -8908,7 +8908,7 @@ var require_util = __commonJS((exports) => {
8908
8908
  }
8909
8909
  return Array(level + 1).join("../") + aPath.substr(aRoot.length + 1);
8910
8910
  }
8911
- exports.relative = relative4;
8911
+ exports.relative = relative3;
8912
8912
  var supportsNullProto = function() {
8913
8913
  var obj = Object.create(null);
8914
8914
  return !("__proto__" in obj);
@@ -9058,7 +9058,7 @@ var require_util = __commonJS((exports) => {
9058
9058
  parsed.path = parsed.path.substring(0, index + 1);
9059
9059
  }
9060
9060
  }
9061
- sourceURL = join18(urlGenerate(parsed), sourceURL);
9061
+ sourceURL = join17(urlGenerate(parsed), sourceURL);
9062
9062
  }
9063
9063
  return normalize2(sourceURL);
9064
9064
  }
@@ -85237,6 +85237,462 @@ var require_core3 = __commonJS((exports, module) => {
85237
85237
  module.exports = enrichCore(core2, getParser());
85238
85238
  });
85239
85239
 
85240
+ // ../../node_modules/.bun/isexe@2.0.0/node_modules/isexe/windows.js
85241
+ var require_windows = __commonJS((exports, module) => {
85242
+ module.exports = isexe;
85243
+ isexe.sync = sync;
85244
+ var fs = __require("fs");
85245
+ function checkPathExt(path, options) {
85246
+ var pathext = options.pathExt !== undefined ? options.pathExt : process.env.PATHEXT;
85247
+ if (!pathext) {
85248
+ return true;
85249
+ }
85250
+ pathext = pathext.split(";");
85251
+ if (pathext.indexOf("") !== -1) {
85252
+ return true;
85253
+ }
85254
+ for (var i = 0;i < pathext.length; i++) {
85255
+ var p = pathext[i].toLowerCase();
85256
+ if (p && path.substr(-p.length).toLowerCase() === p) {
85257
+ return true;
85258
+ }
85259
+ }
85260
+ return false;
85261
+ }
85262
+ function checkStat(stat, path, options) {
85263
+ if (!stat.isSymbolicLink() && !stat.isFile()) {
85264
+ return false;
85265
+ }
85266
+ return checkPathExt(path, options);
85267
+ }
85268
+ function isexe(path, options, cb) {
85269
+ fs.stat(path, function(er, stat) {
85270
+ cb(er, er ? false : checkStat(stat, path, options));
85271
+ });
85272
+ }
85273
+ function sync(path, options) {
85274
+ return checkStat(fs.statSync(path), path, options);
85275
+ }
85276
+ });
85277
+
85278
+ // ../../node_modules/.bun/isexe@2.0.0/node_modules/isexe/mode.js
85279
+ var require_mode = __commonJS((exports, module) => {
85280
+ module.exports = isexe;
85281
+ isexe.sync = sync;
85282
+ var fs = __require("fs");
85283
+ function isexe(path, options, cb) {
85284
+ fs.stat(path, function(er, stat) {
85285
+ cb(er, er ? false : checkStat(stat, options));
85286
+ });
85287
+ }
85288
+ function sync(path, options) {
85289
+ return checkStat(fs.statSync(path), options);
85290
+ }
85291
+ function checkStat(stat, options) {
85292
+ return stat.isFile() && checkMode(stat, options);
85293
+ }
85294
+ function checkMode(stat, options) {
85295
+ var mod = stat.mode;
85296
+ var uid = stat.uid;
85297
+ var gid = stat.gid;
85298
+ var myUid = options.uid !== undefined ? options.uid : process.getuid && process.getuid();
85299
+ var myGid = options.gid !== undefined ? options.gid : process.getgid && process.getgid();
85300
+ var u = parseInt("100", 8);
85301
+ var g = parseInt("010", 8);
85302
+ var o = parseInt("001", 8);
85303
+ var ug = u | g;
85304
+ var ret = mod & o || mod & g && gid === myGid || mod & u && uid === myUid || mod & ug && myUid === 0;
85305
+ return ret;
85306
+ }
85307
+ });
85308
+
85309
+ // ../../node_modules/.bun/isexe@2.0.0/node_modules/isexe/index.js
85310
+ var require_isexe = __commonJS((exports, module) => {
85311
+ var fs = __require("fs");
85312
+ var core2;
85313
+ if (process.platform === "win32" || global.TESTING_WINDOWS) {
85314
+ core2 = require_windows();
85315
+ } else {
85316
+ core2 = require_mode();
85317
+ }
85318
+ module.exports = isexe;
85319
+ isexe.sync = sync;
85320
+ function isexe(path, options, cb) {
85321
+ if (typeof options === "function") {
85322
+ cb = options;
85323
+ options = {};
85324
+ }
85325
+ if (!cb) {
85326
+ if (typeof Promise !== "function") {
85327
+ throw new TypeError("callback not provided");
85328
+ }
85329
+ return new Promise(function(resolve6, reject) {
85330
+ isexe(path, options || {}, function(er, is) {
85331
+ if (er) {
85332
+ reject(er);
85333
+ } else {
85334
+ resolve6(is);
85335
+ }
85336
+ });
85337
+ });
85338
+ }
85339
+ core2(path, options || {}, function(er, is) {
85340
+ if (er) {
85341
+ if (er.code === "EACCES" || options && options.ignoreErrors) {
85342
+ er = null;
85343
+ is = false;
85344
+ }
85345
+ }
85346
+ cb(er, is);
85347
+ });
85348
+ }
85349
+ function sync(path, options) {
85350
+ try {
85351
+ return core2.sync(path, options || {});
85352
+ } catch (er) {
85353
+ if (options && options.ignoreErrors || er.code === "EACCES") {
85354
+ return false;
85355
+ } else {
85356
+ throw er;
85357
+ }
85358
+ }
85359
+ }
85360
+ });
85361
+
85362
+ // ../../node_modules/.bun/which@2.0.2/node_modules/which/which.js
85363
+ var require_which = __commonJS((exports, module) => {
85364
+ var isWindows = process.platform === "win32" || process.env.OSTYPE === "cygwin" || process.env.OSTYPE === "msys";
85365
+ var path = __require("path");
85366
+ var COLON = isWindows ? ";" : ":";
85367
+ var isexe = require_isexe();
85368
+ var getNotFoundError = (cmd) => Object.assign(new Error(`not found: ${cmd}`), { code: "ENOENT" });
85369
+ var getPathInfo = (cmd, opt) => {
85370
+ const colon = opt.colon || COLON;
85371
+ const pathEnv = cmd.match(/\//) || isWindows && cmd.match(/\\/) ? [""] : [
85372
+ ...isWindows ? [process.cwd()] : [],
85373
+ ...(opt.path || process.env.PATH || "").split(colon)
85374
+ ];
85375
+ const pathExtExe = isWindows ? opt.pathExt || process.env.PATHEXT || ".EXE;.CMD;.BAT;.COM" : "";
85376
+ const pathExt = isWindows ? pathExtExe.split(colon) : [""];
85377
+ if (isWindows) {
85378
+ if (cmd.indexOf(".") !== -1 && pathExt[0] !== "")
85379
+ pathExt.unshift("");
85380
+ }
85381
+ return {
85382
+ pathEnv,
85383
+ pathExt,
85384
+ pathExtExe
85385
+ };
85386
+ };
85387
+ var which = (cmd, opt, cb) => {
85388
+ if (typeof opt === "function") {
85389
+ cb = opt;
85390
+ opt = {};
85391
+ }
85392
+ if (!opt)
85393
+ opt = {};
85394
+ const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt);
85395
+ const found = [];
85396
+ const step = (i) => new Promise((resolve6, reject) => {
85397
+ if (i === pathEnv.length)
85398
+ return opt.all && found.length ? resolve6(found) : reject(getNotFoundError(cmd));
85399
+ const ppRaw = pathEnv[i];
85400
+ const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw;
85401
+ const pCmd = path.join(pathPart, cmd);
85402
+ const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd;
85403
+ resolve6(subStep(p, i, 0));
85404
+ });
85405
+ const subStep = (p, i, ii) => new Promise((resolve6, reject) => {
85406
+ if (ii === pathExt.length)
85407
+ return resolve6(step(i + 1));
85408
+ const ext = pathExt[ii];
85409
+ isexe(p + ext, { pathExt: pathExtExe }, (er, is) => {
85410
+ if (!er && is) {
85411
+ if (opt.all)
85412
+ found.push(p + ext);
85413
+ else
85414
+ return resolve6(p + ext);
85415
+ }
85416
+ return resolve6(subStep(p, i, ii + 1));
85417
+ });
85418
+ });
85419
+ return cb ? step(0).then((res) => cb(null, res), cb) : step(0);
85420
+ };
85421
+ var whichSync = (cmd, opt) => {
85422
+ opt = opt || {};
85423
+ const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt);
85424
+ const found = [];
85425
+ for (let i = 0;i < pathEnv.length; i++) {
85426
+ const ppRaw = pathEnv[i];
85427
+ const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw;
85428
+ const pCmd = path.join(pathPart, cmd);
85429
+ const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd;
85430
+ for (let j = 0;j < pathExt.length; j++) {
85431
+ const cur = p + pathExt[j];
85432
+ try {
85433
+ const is = isexe.sync(cur, { pathExt: pathExtExe });
85434
+ if (is) {
85435
+ if (opt.all)
85436
+ found.push(cur);
85437
+ else
85438
+ return cur;
85439
+ }
85440
+ } catch (ex) {}
85441
+ }
85442
+ }
85443
+ if (opt.all && found.length)
85444
+ return found;
85445
+ if (opt.nothrow)
85446
+ return null;
85447
+ throw getNotFoundError(cmd);
85448
+ };
85449
+ module.exports = which;
85450
+ which.sync = whichSync;
85451
+ });
85452
+
85453
+ // ../../node_modules/.bun/path-key@3.1.1/node_modules/path-key/index.js
85454
+ var require_path_key = __commonJS((exports, module) => {
85455
+ var pathKey = (options = {}) => {
85456
+ const environment = options.env || process.env;
85457
+ const platform = options.platform || process.platform;
85458
+ if (platform !== "win32") {
85459
+ return "PATH";
85460
+ }
85461
+ return Object.keys(environment).reverse().find((key) => key.toUpperCase() === "PATH") || "Path";
85462
+ };
85463
+ module.exports = pathKey;
85464
+ module.exports.default = pathKey;
85465
+ });
85466
+
85467
+ // ../../node_modules/.bun/cross-spawn@7.0.6/node_modules/cross-spawn/lib/util/resolveCommand.js
85468
+ var require_resolveCommand = __commonJS((exports, module) => {
85469
+ var path = __require("path");
85470
+ var which = require_which();
85471
+ var getPathKey = require_path_key();
85472
+ function resolveCommandAttempt(parsed, withoutPathExt) {
85473
+ const env = parsed.options.env || process.env;
85474
+ const cwd = process.cwd();
85475
+ const hasCustomCwd = parsed.options.cwd != null;
85476
+ const shouldSwitchCwd = hasCustomCwd && process.chdir !== undefined && !process.chdir.disabled;
85477
+ if (shouldSwitchCwd) {
85478
+ try {
85479
+ process.chdir(parsed.options.cwd);
85480
+ } catch (err) {}
85481
+ }
85482
+ let resolved;
85483
+ try {
85484
+ resolved = which.sync(parsed.command, {
85485
+ path: env[getPathKey({ env })],
85486
+ pathExt: withoutPathExt ? path.delimiter : undefined
85487
+ });
85488
+ } catch (e) {} finally {
85489
+ if (shouldSwitchCwd) {
85490
+ process.chdir(cwd);
85491
+ }
85492
+ }
85493
+ if (resolved) {
85494
+ resolved = path.resolve(hasCustomCwd ? parsed.options.cwd : "", resolved);
85495
+ }
85496
+ return resolved;
85497
+ }
85498
+ function resolveCommand(parsed) {
85499
+ return resolveCommandAttempt(parsed) || resolveCommandAttempt(parsed, true);
85500
+ }
85501
+ module.exports = resolveCommand;
85502
+ });
85503
+
85504
+ // ../../node_modules/.bun/cross-spawn@7.0.6/node_modules/cross-spawn/lib/util/escape.js
85505
+ var require_escape = __commonJS((exports, module) => {
85506
+ var metaCharsRegExp = /([()\][%!^"`<>&|;, *?])/g;
85507
+ function escapeCommand(arg) {
85508
+ arg = arg.replace(metaCharsRegExp, "^$1");
85509
+ return arg;
85510
+ }
85511
+ function escapeArgument(arg, doubleEscapeMetaChars) {
85512
+ arg = `${arg}`;
85513
+ arg = arg.replace(/(?=(\\+?)?)\1"/g, "$1$1\\\"");
85514
+ arg = arg.replace(/(?=(\\+?)?)\1$/, "$1$1");
85515
+ arg = `"${arg}"`;
85516
+ arg = arg.replace(metaCharsRegExp, "^$1");
85517
+ if (doubleEscapeMetaChars) {
85518
+ arg = arg.replace(metaCharsRegExp, "^$1");
85519
+ }
85520
+ return arg;
85521
+ }
85522
+ exports.command = escapeCommand;
85523
+ exports.argument = escapeArgument;
85524
+ });
85525
+
85526
+ // ../../node_modules/.bun/shebang-regex@3.0.0/node_modules/shebang-regex/index.js
85527
+ var require_shebang_regex = __commonJS((exports, module) => {
85528
+ module.exports = /^#!(.*)/;
85529
+ });
85530
+
85531
+ // ../../node_modules/.bun/shebang-command@2.0.0/node_modules/shebang-command/index.js
85532
+ var require_shebang_command = __commonJS((exports, module) => {
85533
+ var shebangRegex = require_shebang_regex();
85534
+ module.exports = (string4 = "") => {
85535
+ const match = string4.match(shebangRegex);
85536
+ if (!match) {
85537
+ return null;
85538
+ }
85539
+ const [path, argument] = match[0].replace(/#! ?/, "").split(" ");
85540
+ const binary = path.split("/").pop();
85541
+ if (binary === "env") {
85542
+ return argument;
85543
+ }
85544
+ return argument ? `${binary} ${argument}` : binary;
85545
+ };
85546
+ });
85547
+
85548
+ // ../../node_modules/.bun/cross-spawn@7.0.6/node_modules/cross-spawn/lib/util/readShebang.js
85549
+ var require_readShebang = __commonJS((exports, module) => {
85550
+ var fs = __require("fs");
85551
+ var shebangCommand = require_shebang_command();
85552
+ function readShebang(command) {
85553
+ const size = 150;
85554
+ const buffer = Buffer.alloc(size);
85555
+ let fd;
85556
+ try {
85557
+ fd = fs.openSync(command, "r");
85558
+ fs.readSync(fd, buffer, 0, size, 0);
85559
+ fs.closeSync(fd);
85560
+ } catch (e) {}
85561
+ return shebangCommand(buffer.toString());
85562
+ }
85563
+ module.exports = readShebang;
85564
+ });
85565
+
85566
+ // ../../node_modules/.bun/cross-spawn@7.0.6/node_modules/cross-spawn/lib/parse.js
85567
+ var require_parse2 = __commonJS((exports, module) => {
85568
+ var path = __require("path");
85569
+ var resolveCommand = require_resolveCommand();
85570
+ var escape = require_escape();
85571
+ var readShebang = require_readShebang();
85572
+ var isWin = process.platform === "win32";
85573
+ var isExecutableRegExp = /\.(?:com|exe)$/i;
85574
+ var isCmdShimRegExp = /node_modules[\\/].bin[\\/][^\\/]+\.cmd$/i;
85575
+ function detectShebang(parsed) {
85576
+ parsed.file = resolveCommand(parsed);
85577
+ const shebang = parsed.file && readShebang(parsed.file);
85578
+ if (shebang) {
85579
+ parsed.args.unshift(parsed.file);
85580
+ parsed.command = shebang;
85581
+ return resolveCommand(parsed);
85582
+ }
85583
+ return parsed.file;
85584
+ }
85585
+ function parseNonShell(parsed) {
85586
+ if (!isWin) {
85587
+ return parsed;
85588
+ }
85589
+ const commandFile = detectShebang(parsed);
85590
+ const needsShell = !isExecutableRegExp.test(commandFile);
85591
+ if (parsed.options.forceShell || needsShell) {
85592
+ const needsDoubleEscapeMetaChars = isCmdShimRegExp.test(commandFile);
85593
+ parsed.command = path.normalize(parsed.command);
85594
+ parsed.command = escape.command(parsed.command);
85595
+ parsed.args = parsed.args.map((arg) => escape.argument(arg, needsDoubleEscapeMetaChars));
85596
+ const shellCommand = [parsed.command].concat(parsed.args).join(" ");
85597
+ parsed.args = ["/d", "/s", "/c", `"${shellCommand}"`];
85598
+ parsed.command = process.env.comspec || "cmd.exe";
85599
+ parsed.options.windowsVerbatimArguments = true;
85600
+ }
85601
+ return parsed;
85602
+ }
85603
+ function parse6(command, args, options) {
85604
+ if (args && !Array.isArray(args)) {
85605
+ options = args;
85606
+ args = null;
85607
+ }
85608
+ args = args ? args.slice(0) : [];
85609
+ options = Object.assign({}, options);
85610
+ const parsed = {
85611
+ command,
85612
+ args,
85613
+ options,
85614
+ file: undefined,
85615
+ original: {
85616
+ command,
85617
+ args
85618
+ }
85619
+ };
85620
+ return options.shell ? parsed : parseNonShell(parsed);
85621
+ }
85622
+ module.exports = parse6;
85623
+ });
85624
+
85625
+ // ../../node_modules/.bun/cross-spawn@7.0.6/node_modules/cross-spawn/lib/enoent.js
85626
+ var require_enoent = __commonJS((exports, module) => {
85627
+ var isWin = process.platform === "win32";
85628
+ function notFoundError(original, syscall) {
85629
+ return Object.assign(new Error(`${syscall} ${original.command} ENOENT`), {
85630
+ code: "ENOENT",
85631
+ errno: "ENOENT",
85632
+ syscall: `${syscall} ${original.command}`,
85633
+ path: original.command,
85634
+ spawnargs: original.args
85635
+ });
85636
+ }
85637
+ function hookChildProcess(cp, parsed) {
85638
+ if (!isWin) {
85639
+ return;
85640
+ }
85641
+ const originalEmit = cp.emit;
85642
+ cp.emit = function(name, arg1) {
85643
+ if (name === "exit") {
85644
+ const err = verifyENOENT(arg1, parsed);
85645
+ if (err) {
85646
+ return originalEmit.call(cp, "error", err);
85647
+ }
85648
+ }
85649
+ return originalEmit.apply(cp, arguments);
85650
+ };
85651
+ }
85652
+ function verifyENOENT(status, parsed) {
85653
+ if (isWin && status === 1 && !parsed.file) {
85654
+ return notFoundError(parsed.original, "spawn");
85655
+ }
85656
+ return null;
85657
+ }
85658
+ function verifyENOENTSync(status, parsed) {
85659
+ if (isWin && status === 1 && !parsed.file) {
85660
+ return notFoundError(parsed.original, "spawnSync");
85661
+ }
85662
+ return null;
85663
+ }
85664
+ module.exports = {
85665
+ hookChildProcess,
85666
+ verifyENOENT,
85667
+ verifyENOENTSync,
85668
+ notFoundError
85669
+ };
85670
+ });
85671
+
85672
+ // ../../node_modules/.bun/cross-spawn@7.0.6/node_modules/cross-spawn/index.js
85673
+ var require_cross_spawn = __commonJS((exports, module) => {
85674
+ var cp = __require("child_process");
85675
+ var parse6 = require_parse2();
85676
+ var enoent = require_enoent();
85677
+ function spawn(command, args, options) {
85678
+ const parsed = parse6(command, args, options);
85679
+ const spawned = cp.spawn(parsed.command, parsed.args, parsed.options);
85680
+ enoent.hookChildProcess(spawned, parsed);
85681
+ return spawned;
85682
+ }
85683
+ function spawnSync(command, args, options) {
85684
+ const parsed = parse6(command, args, options);
85685
+ const result = cp.spawnSync(parsed.command, parsed.args, parsed.options);
85686
+ result.error = result.error || enoent.verifyENOENTSync(result.status, parsed);
85687
+ return result;
85688
+ }
85689
+ module.exports = spawn;
85690
+ module.exports.spawn = spawn;
85691
+ module.exports.sync = spawnSync;
85692
+ module.exports._parse = parse6;
85693
+ module.exports._enoent = enoent;
85694
+ });
85695
+
85240
85696
  // ../../node_modules/.bun/qrcode@1.5.4/node_modules/qrcode/lib/can-promise.js
85241
85697
  var require_can_promise = __commonJS((exports, module) => {
85242
85698
  module.exports = function() {
@@ -86112,7 +86568,7 @@ var require_regex = __commonJS((exports) => {
86112
86568
  });
86113
86569
 
86114
86570
  // ../../node_modules/.bun/qrcode@1.5.4/node_modules/qrcode/lib/core/mode.js
86115
- var require_mode = __commonJS((exports) => {
86571
+ var require_mode2 = __commonJS((exports) => {
86116
86572
  var VersionCheck = require_version_check();
86117
86573
  var Regex = require_regex();
86118
86574
  exports.NUMERIC = {
@@ -86203,7 +86659,7 @@ var require_version = __commonJS((exports) => {
86203
86659
  var Utils = require_utils();
86204
86660
  var ECCode = require_error_correction_code();
86205
86661
  var ECLevel = require_error_correction_level();
86206
- var Mode = require_mode();
86662
+ var Mode = require_mode2();
86207
86663
  var VersionCheck = require_version_check();
86208
86664
  var G18 = 1 << 12 | 1 << 11 | 1 << 10 | 1 << 9 | 1 << 8 | 1 << 5 | 1 << 2 | 1 << 0;
86209
86665
  var G18_BCH = Utils.getBCHDigit(G18);
@@ -86311,7 +86767,7 @@ var require_format_info = __commonJS((exports) => {
86311
86767
 
86312
86768
  // ../../node_modules/.bun/qrcode@1.5.4/node_modules/qrcode/lib/core/numeric-data.js
86313
86769
  var require_numeric_data = __commonJS((exports, module) => {
86314
- var Mode = require_mode();
86770
+ var Mode = require_mode2();
86315
86771
  function NumericData(data2) {
86316
86772
  this.mode = Mode.NUMERIC;
86317
86773
  this.data = data2.toString();
@@ -86344,7 +86800,7 @@ var require_numeric_data = __commonJS((exports, module) => {
86344
86800
 
86345
86801
  // ../../node_modules/.bun/qrcode@1.5.4/node_modules/qrcode/lib/core/alphanumeric-data.js
86346
86802
  var require_alphanumeric_data = __commonJS((exports, module) => {
86347
- var Mode = require_mode();
86803
+ var Mode = require_mode2();
86348
86804
  var ALPHA_NUM_CHARS = [
86349
86805
  "0",
86350
86806
  "1",
@@ -86421,7 +86877,7 @@ var require_alphanumeric_data = __commonJS((exports, module) => {
86421
86877
 
86422
86878
  // ../../node_modules/.bun/qrcode@1.5.4/node_modules/qrcode/lib/core/byte-data.js
86423
86879
  var require_byte_data = __commonJS((exports, module) => {
86424
- var Mode = require_mode();
86880
+ var Mode = require_mode2();
86425
86881
  function ByteData(data2) {
86426
86882
  this.mode = Mode.BYTE;
86427
86883
  if (typeof data2 === "string") {
@@ -86449,7 +86905,7 @@ var require_byte_data = __commonJS((exports, module) => {
86449
86905
 
86450
86906
  // ../../node_modules/.bun/qrcode@1.5.4/node_modules/qrcode/lib/core/kanji-data.js
86451
86907
  var require_kanji_data = __commonJS((exports, module) => {
86452
- var Mode = require_mode();
86908
+ var Mode = require_mode2();
86453
86909
  var Utils = require_utils();
86454
86910
  function KanjiData(data2) {
86455
86911
  this.mode = Mode.KANJI;
@@ -86570,7 +87026,7 @@ var require_dijkstra = __commonJS((exports, module) => {
86570
87026
 
86571
87027
  // ../../node_modules/.bun/qrcode@1.5.4/node_modules/qrcode/lib/core/segments.js
86572
87028
  var require_segments = __commonJS((exports) => {
86573
- var Mode = require_mode();
87029
+ var Mode = require_mode2();
86574
87030
  var NumericData = require_numeric_data();
86575
87031
  var AlphanumericData = require_alphanumeric_data();
86576
87032
  var ByteData = require_byte_data();
@@ -86765,7 +87221,7 @@ var require_qrcode = __commonJS((exports) => {
86765
87221
  var ReedSolomonEncoder = require_reed_solomon_encoder();
86766
87222
  var Version = require_version();
86767
87223
  var FormatInfo = require_format_info();
86768
- var Mode = require_mode();
87224
+ var Mode = require_mode2();
86769
87225
  var Segments = require_segments();
86770
87226
  function setupFinderPattern(matrix, version2) {
86771
87227
  const size = matrix.size;
@@ -89384,10 +89840,10 @@ var require_browser = __commonJS((exports) => {
89384
89840
  text = canvas;
89385
89841
  canvas = undefined;
89386
89842
  }
89387
- return new Promise(function(resolve7, reject) {
89843
+ return new Promise(function(resolve10, reject) {
89388
89844
  try {
89389
89845
  const data2 = QRCode.create(text, opts);
89390
- resolve7(renderFunc(data2, canvas, opts));
89846
+ resolve10(renderFunc(data2, canvas, opts));
89391
89847
  } catch (e) {
89392
89848
  reject(e);
89393
89849
  }
@@ -89466,11 +89922,11 @@ var require_server = __commonJS((exports) => {
89466
89922
  }
89467
89923
  function render(renderFunc, text, params) {
89468
89924
  if (!params.cb) {
89469
- return new Promise(function(resolve7, reject) {
89925
+ return new Promise(function(resolve10, reject) {
89470
89926
  try {
89471
89927
  const data2 = QRCode.create(text, params.opts);
89472
89928
  return renderFunc(data2, params.opts, function(err, data3) {
89473
- return err ? reject(err) : resolve7(data3);
89929
+ return err ? reject(err) : resolve10(data3);
89474
89930
  });
89475
89931
  } catch (e) {
89476
89932
  reject(e);
@@ -89543,462 +89999,6 @@ var init_qr = __esm(() => {
89543
89999
  import_qrcode = __toESM(require_server(), 1);
89544
90000
  });
89545
90001
 
89546
- // ../../node_modules/.bun/isexe@2.0.0/node_modules/isexe/windows.js
89547
- var require_windows = __commonJS((exports, module) => {
89548
- module.exports = isexe;
89549
- isexe.sync = sync;
89550
- var fs = __require("fs");
89551
- function checkPathExt(path, options) {
89552
- var pathext = options.pathExt !== undefined ? options.pathExt : process.env.PATHEXT;
89553
- if (!pathext) {
89554
- return true;
89555
- }
89556
- pathext = pathext.split(";");
89557
- if (pathext.indexOf("") !== -1) {
89558
- return true;
89559
- }
89560
- for (var i = 0;i < pathext.length; i++) {
89561
- var p = pathext[i].toLowerCase();
89562
- if (p && path.substr(-p.length).toLowerCase() === p) {
89563
- return true;
89564
- }
89565
- }
89566
- return false;
89567
- }
89568
- function checkStat(stat, path, options) {
89569
- if (!stat.isSymbolicLink() && !stat.isFile()) {
89570
- return false;
89571
- }
89572
- return checkPathExt(path, options);
89573
- }
89574
- function isexe(path, options, cb) {
89575
- fs.stat(path, function(er, stat) {
89576
- cb(er, er ? false : checkStat(stat, path, options));
89577
- });
89578
- }
89579
- function sync(path, options) {
89580
- return checkStat(fs.statSync(path), path, options);
89581
- }
89582
- });
89583
-
89584
- // ../../node_modules/.bun/isexe@2.0.0/node_modules/isexe/mode.js
89585
- var require_mode2 = __commonJS((exports, module) => {
89586
- module.exports = isexe;
89587
- isexe.sync = sync;
89588
- var fs = __require("fs");
89589
- function isexe(path, options, cb) {
89590
- fs.stat(path, function(er, stat) {
89591
- cb(er, er ? false : checkStat(stat, options));
89592
- });
89593
- }
89594
- function sync(path, options) {
89595
- return checkStat(fs.statSync(path), options);
89596
- }
89597
- function checkStat(stat, options) {
89598
- return stat.isFile() && checkMode(stat, options);
89599
- }
89600
- function checkMode(stat, options) {
89601
- var mod = stat.mode;
89602
- var uid = stat.uid;
89603
- var gid = stat.gid;
89604
- var myUid = options.uid !== undefined ? options.uid : process.getuid && process.getuid();
89605
- var myGid = options.gid !== undefined ? options.gid : process.getgid && process.getgid();
89606
- var u = parseInt("100", 8);
89607
- var g = parseInt("010", 8);
89608
- var o = parseInt("001", 8);
89609
- var ug = u | g;
89610
- var ret = mod & o || mod & g && gid === myGid || mod & u && uid === myUid || mod & ug && myUid === 0;
89611
- return ret;
89612
- }
89613
- });
89614
-
89615
- // ../../node_modules/.bun/isexe@2.0.0/node_modules/isexe/index.js
89616
- var require_isexe = __commonJS((exports, module) => {
89617
- var fs = __require("fs");
89618
- var core2;
89619
- if (process.platform === "win32" || global.TESTING_WINDOWS) {
89620
- core2 = require_windows();
89621
- } else {
89622
- core2 = require_mode2();
89623
- }
89624
- module.exports = isexe;
89625
- isexe.sync = sync;
89626
- function isexe(path, options, cb) {
89627
- if (typeof options === "function") {
89628
- cb = options;
89629
- options = {};
89630
- }
89631
- if (!cb) {
89632
- if (typeof Promise !== "function") {
89633
- throw new TypeError("callback not provided");
89634
- }
89635
- return new Promise(function(resolve7, reject) {
89636
- isexe(path, options || {}, function(er, is) {
89637
- if (er) {
89638
- reject(er);
89639
- } else {
89640
- resolve7(is);
89641
- }
89642
- });
89643
- });
89644
- }
89645
- core2(path, options || {}, function(er, is) {
89646
- if (er) {
89647
- if (er.code === "EACCES" || options && options.ignoreErrors) {
89648
- er = null;
89649
- is = false;
89650
- }
89651
- }
89652
- cb(er, is);
89653
- });
89654
- }
89655
- function sync(path, options) {
89656
- try {
89657
- return core2.sync(path, options || {});
89658
- } catch (er) {
89659
- if (options && options.ignoreErrors || er.code === "EACCES") {
89660
- return false;
89661
- } else {
89662
- throw er;
89663
- }
89664
- }
89665
- }
89666
- });
89667
-
89668
- // ../../node_modules/.bun/which@2.0.2/node_modules/which/which.js
89669
- var require_which = __commonJS((exports, module) => {
89670
- var isWindows = process.platform === "win32" || process.env.OSTYPE === "cygwin" || process.env.OSTYPE === "msys";
89671
- var path = __require("path");
89672
- var COLON = isWindows ? ";" : ":";
89673
- var isexe = require_isexe();
89674
- var getNotFoundError = (cmd) => Object.assign(new Error(`not found: ${cmd}`), { code: "ENOENT" });
89675
- var getPathInfo = (cmd, opt) => {
89676
- const colon = opt.colon || COLON;
89677
- const pathEnv = cmd.match(/\//) || isWindows && cmd.match(/\\/) ? [""] : [
89678
- ...isWindows ? [process.cwd()] : [],
89679
- ...(opt.path || process.env.PATH || "").split(colon)
89680
- ];
89681
- const pathExtExe = isWindows ? opt.pathExt || process.env.PATHEXT || ".EXE;.CMD;.BAT;.COM" : "";
89682
- const pathExt = isWindows ? pathExtExe.split(colon) : [""];
89683
- if (isWindows) {
89684
- if (cmd.indexOf(".") !== -1 && pathExt[0] !== "")
89685
- pathExt.unshift("");
89686
- }
89687
- return {
89688
- pathEnv,
89689
- pathExt,
89690
- pathExtExe
89691
- };
89692
- };
89693
- var which = (cmd, opt, cb) => {
89694
- if (typeof opt === "function") {
89695
- cb = opt;
89696
- opt = {};
89697
- }
89698
- if (!opt)
89699
- opt = {};
89700
- const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt);
89701
- const found = [];
89702
- const step = (i) => new Promise((resolve7, reject) => {
89703
- if (i === pathEnv.length)
89704
- return opt.all && found.length ? resolve7(found) : reject(getNotFoundError(cmd));
89705
- const ppRaw = pathEnv[i];
89706
- const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw;
89707
- const pCmd = path.join(pathPart, cmd);
89708
- const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd;
89709
- resolve7(subStep(p, i, 0));
89710
- });
89711
- const subStep = (p, i, ii) => new Promise((resolve7, reject) => {
89712
- if (ii === pathExt.length)
89713
- return resolve7(step(i + 1));
89714
- const ext = pathExt[ii];
89715
- isexe(p + ext, { pathExt: pathExtExe }, (er, is) => {
89716
- if (!er && is) {
89717
- if (opt.all)
89718
- found.push(p + ext);
89719
- else
89720
- return resolve7(p + ext);
89721
- }
89722
- return resolve7(subStep(p, i, ii + 1));
89723
- });
89724
- });
89725
- return cb ? step(0).then((res) => cb(null, res), cb) : step(0);
89726
- };
89727
- var whichSync = (cmd, opt) => {
89728
- opt = opt || {};
89729
- const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt);
89730
- const found = [];
89731
- for (let i = 0;i < pathEnv.length; i++) {
89732
- const ppRaw = pathEnv[i];
89733
- const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw;
89734
- const pCmd = path.join(pathPart, cmd);
89735
- const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd;
89736
- for (let j = 0;j < pathExt.length; j++) {
89737
- const cur = p + pathExt[j];
89738
- try {
89739
- const is = isexe.sync(cur, { pathExt: pathExtExe });
89740
- if (is) {
89741
- if (opt.all)
89742
- found.push(cur);
89743
- else
89744
- return cur;
89745
- }
89746
- } catch (ex) {}
89747
- }
89748
- }
89749
- if (opt.all && found.length)
89750
- return found;
89751
- if (opt.nothrow)
89752
- return null;
89753
- throw getNotFoundError(cmd);
89754
- };
89755
- module.exports = which;
89756
- which.sync = whichSync;
89757
- });
89758
-
89759
- // ../../node_modules/.bun/path-key@3.1.1/node_modules/path-key/index.js
89760
- var require_path_key = __commonJS((exports, module) => {
89761
- var pathKey = (options = {}) => {
89762
- const environment = options.env || process.env;
89763
- const platform = options.platform || process.platform;
89764
- if (platform !== "win32") {
89765
- return "PATH";
89766
- }
89767
- return Object.keys(environment).reverse().find((key) => key.toUpperCase() === "PATH") || "Path";
89768
- };
89769
- module.exports = pathKey;
89770
- module.exports.default = pathKey;
89771
- });
89772
-
89773
- // ../../node_modules/.bun/cross-spawn@7.0.6/node_modules/cross-spawn/lib/util/resolveCommand.js
89774
- var require_resolveCommand = __commonJS((exports, module) => {
89775
- var path = __require("path");
89776
- var which = require_which();
89777
- var getPathKey = require_path_key();
89778
- function resolveCommandAttempt(parsed, withoutPathExt) {
89779
- const env = parsed.options.env || process.env;
89780
- const cwd = process.cwd();
89781
- const hasCustomCwd = parsed.options.cwd != null;
89782
- const shouldSwitchCwd = hasCustomCwd && process.chdir !== undefined && !process.chdir.disabled;
89783
- if (shouldSwitchCwd) {
89784
- try {
89785
- process.chdir(parsed.options.cwd);
89786
- } catch (err) {}
89787
- }
89788
- let resolved;
89789
- try {
89790
- resolved = which.sync(parsed.command, {
89791
- path: env[getPathKey({ env })],
89792
- pathExt: withoutPathExt ? path.delimiter : undefined
89793
- });
89794
- } catch (e) {} finally {
89795
- if (shouldSwitchCwd) {
89796
- process.chdir(cwd);
89797
- }
89798
- }
89799
- if (resolved) {
89800
- resolved = path.resolve(hasCustomCwd ? parsed.options.cwd : "", resolved);
89801
- }
89802
- return resolved;
89803
- }
89804
- function resolveCommand(parsed) {
89805
- return resolveCommandAttempt(parsed) || resolveCommandAttempt(parsed, true);
89806
- }
89807
- module.exports = resolveCommand;
89808
- });
89809
-
89810
- // ../../node_modules/.bun/cross-spawn@7.0.6/node_modules/cross-spawn/lib/util/escape.js
89811
- var require_escape = __commonJS((exports, module) => {
89812
- var metaCharsRegExp = /([()\][%!^"`<>&|;, *?])/g;
89813
- function escapeCommand(arg) {
89814
- arg = arg.replace(metaCharsRegExp, "^$1");
89815
- return arg;
89816
- }
89817
- function escapeArgument(arg, doubleEscapeMetaChars) {
89818
- arg = `${arg}`;
89819
- arg = arg.replace(/(?=(\\+?)?)\1"/g, "$1$1\\\"");
89820
- arg = arg.replace(/(?=(\\+?)?)\1$/, "$1$1");
89821
- arg = `"${arg}"`;
89822
- arg = arg.replace(metaCharsRegExp, "^$1");
89823
- if (doubleEscapeMetaChars) {
89824
- arg = arg.replace(metaCharsRegExp, "^$1");
89825
- }
89826
- return arg;
89827
- }
89828
- exports.command = escapeCommand;
89829
- exports.argument = escapeArgument;
89830
- });
89831
-
89832
- // ../../node_modules/.bun/shebang-regex@3.0.0/node_modules/shebang-regex/index.js
89833
- var require_shebang_regex = __commonJS((exports, module) => {
89834
- module.exports = /^#!(.*)/;
89835
- });
89836
-
89837
- // ../../node_modules/.bun/shebang-command@2.0.0/node_modules/shebang-command/index.js
89838
- var require_shebang_command = __commonJS((exports, module) => {
89839
- var shebangRegex = require_shebang_regex();
89840
- module.exports = (string4 = "") => {
89841
- const match = string4.match(shebangRegex);
89842
- if (!match) {
89843
- return null;
89844
- }
89845
- const [path, argument] = match[0].replace(/#! ?/, "").split(" ");
89846
- const binary = path.split("/").pop();
89847
- if (binary === "env") {
89848
- return argument;
89849
- }
89850
- return argument ? `${binary} ${argument}` : binary;
89851
- };
89852
- });
89853
-
89854
- // ../../node_modules/.bun/cross-spawn@7.0.6/node_modules/cross-spawn/lib/util/readShebang.js
89855
- var require_readShebang = __commonJS((exports, module) => {
89856
- var fs = __require("fs");
89857
- var shebangCommand = require_shebang_command();
89858
- function readShebang(command) {
89859
- const size = 150;
89860
- const buffer = Buffer.alloc(size);
89861
- let fd;
89862
- try {
89863
- fd = fs.openSync(command, "r");
89864
- fs.readSync(fd, buffer, 0, size, 0);
89865
- fs.closeSync(fd);
89866
- } catch (e) {}
89867
- return shebangCommand(buffer.toString());
89868
- }
89869
- module.exports = readShebang;
89870
- });
89871
-
89872
- // ../../node_modules/.bun/cross-spawn@7.0.6/node_modules/cross-spawn/lib/parse.js
89873
- var require_parse2 = __commonJS((exports, module) => {
89874
- var path = __require("path");
89875
- var resolveCommand = require_resolveCommand();
89876
- var escape = require_escape();
89877
- var readShebang = require_readShebang();
89878
- var isWin = process.platform === "win32";
89879
- var isExecutableRegExp = /\.(?:com|exe)$/i;
89880
- var isCmdShimRegExp = /node_modules[\\/].bin[\\/][^\\/]+\.cmd$/i;
89881
- function detectShebang(parsed) {
89882
- parsed.file = resolveCommand(parsed);
89883
- const shebang = parsed.file && readShebang(parsed.file);
89884
- if (shebang) {
89885
- parsed.args.unshift(parsed.file);
89886
- parsed.command = shebang;
89887
- return resolveCommand(parsed);
89888
- }
89889
- return parsed.file;
89890
- }
89891
- function parseNonShell(parsed) {
89892
- if (!isWin) {
89893
- return parsed;
89894
- }
89895
- const commandFile = detectShebang(parsed);
89896
- const needsShell = !isExecutableRegExp.test(commandFile);
89897
- if (parsed.options.forceShell || needsShell) {
89898
- const needsDoubleEscapeMetaChars = isCmdShimRegExp.test(commandFile);
89899
- parsed.command = path.normalize(parsed.command);
89900
- parsed.command = escape.command(parsed.command);
89901
- parsed.args = parsed.args.map((arg) => escape.argument(arg, needsDoubleEscapeMetaChars));
89902
- const shellCommand = [parsed.command].concat(parsed.args).join(" ");
89903
- parsed.args = ["/d", "/s", "/c", `"${shellCommand}"`];
89904
- parsed.command = process.env.comspec || "cmd.exe";
89905
- parsed.options.windowsVerbatimArguments = true;
89906
- }
89907
- return parsed;
89908
- }
89909
- function parse6(command, args, options) {
89910
- if (args && !Array.isArray(args)) {
89911
- options = args;
89912
- args = null;
89913
- }
89914
- args = args ? args.slice(0) : [];
89915
- options = Object.assign({}, options);
89916
- const parsed = {
89917
- command,
89918
- args,
89919
- options,
89920
- file: undefined,
89921
- original: {
89922
- command,
89923
- args
89924
- }
89925
- };
89926
- return options.shell ? parsed : parseNonShell(parsed);
89927
- }
89928
- module.exports = parse6;
89929
- });
89930
-
89931
- // ../../node_modules/.bun/cross-spawn@7.0.6/node_modules/cross-spawn/lib/enoent.js
89932
- var require_enoent = __commonJS((exports, module) => {
89933
- var isWin = process.platform === "win32";
89934
- function notFoundError(original, syscall) {
89935
- return Object.assign(new Error(`${syscall} ${original.command} ENOENT`), {
89936
- code: "ENOENT",
89937
- errno: "ENOENT",
89938
- syscall: `${syscall} ${original.command}`,
89939
- path: original.command,
89940
- spawnargs: original.args
89941
- });
89942
- }
89943
- function hookChildProcess(cp, parsed) {
89944
- if (!isWin) {
89945
- return;
89946
- }
89947
- const originalEmit = cp.emit;
89948
- cp.emit = function(name, arg1) {
89949
- if (name === "exit") {
89950
- const err = verifyENOENT(arg1, parsed);
89951
- if (err) {
89952
- return originalEmit.call(cp, "error", err);
89953
- }
89954
- }
89955
- return originalEmit.apply(cp, arguments);
89956
- };
89957
- }
89958
- function verifyENOENT(status, parsed) {
89959
- if (isWin && status === 1 && !parsed.file) {
89960
- return notFoundError(parsed.original, "spawn");
89961
- }
89962
- return null;
89963
- }
89964
- function verifyENOENTSync(status, parsed) {
89965
- if (isWin && status === 1 && !parsed.file) {
89966
- return notFoundError(parsed.original, "spawnSync");
89967
- }
89968
- return null;
89969
- }
89970
- module.exports = {
89971
- hookChildProcess,
89972
- verifyENOENT,
89973
- verifyENOENTSync,
89974
- notFoundError
89975
- };
89976
- });
89977
-
89978
- // ../../node_modules/.bun/cross-spawn@7.0.6/node_modules/cross-spawn/index.js
89979
- var require_cross_spawn = __commonJS((exports, module) => {
89980
- var cp = __require("child_process");
89981
- var parse6 = require_parse2();
89982
- var enoent = require_enoent();
89983
- function spawn(command, args, options) {
89984
- const parsed = parse6(command, args, options);
89985
- const spawned = cp.spawn(parsed.command, parsed.args, parsed.options);
89986
- enoent.hookChildProcess(spawned, parsed);
89987
- return spawned;
89988
- }
89989
- function spawnSync(command, args, options) {
89990
- const parsed = parse6(command, args, options);
89991
- const result = cp.spawnSync(parsed.command, parsed.args, parsed.options);
89992
- result.error = result.error || enoent.verifyENOENTSync(result.status, parsed);
89993
- return result;
89994
- }
89995
- module.exports = spawn;
89996
- module.exports.spawn = spawn;
89997
- module.exports.sync = spawnSync;
89998
- module.exports._parse = parse6;
89999
- module.exports._enoent = enoent;
90000
- });
90001
-
90002
90002
  // ../../node_modules/.bun/picocolors@1.1.1/node_modules/picocolors/picocolors.js
90003
90003
  var require_picocolors = __commonJS((exports, module) => {
90004
90004
  var p = process || {};
@@ -90181,7 +90181,7 @@ __export(exports_prompt_hidden, {
90181
90181
  });
90182
90182
  import { stdin, stdout } from "node:process";
90183
90183
  function promptHiddenWithStreams(question, input, output) {
90184
- return new Promise((resolve7, reject) => {
90184
+ return new Promise((resolve10, reject) => {
90185
90185
  output.write(`${question} `);
90186
90186
  let buf = "";
90187
90187
  let done = false;
@@ -90197,7 +90197,7 @@ function promptHiddenWithStreams(question, input, output) {
90197
90197
  input.removeListener("error", onError);
90198
90198
  output.write(`
90199
90199
  `);
90200
- resolve7(buf.replace(/\r$/, ""));
90200
+ resolve10(buf.replace(/\r$/, ""));
90201
90201
  return;
90202
90202
  }
90203
90203
  buf += ch;
@@ -90219,7 +90219,7 @@ function promptHiddenWithStreams(question, input, output) {
90219
90219
  input.removeListener("error", onError);
90220
90220
  output.write(`
90221
90221
  `);
90222
- resolve7(buf.replace(/\r$/, ""));
90222
+ resolve10(buf.replace(/\r$/, ""));
90223
90223
  };
90224
90224
  input.on("data", onData);
90225
90225
  input.on("error", onError);
@@ -90237,7 +90237,7 @@ async function promptHidden(question) {
90237
90237
  ttyStdin.resume();
90238
90238
  ttyStdin.setEncoding("utf8");
90239
90239
  try {
90240
- return await new Promise((resolve7, reject) => {
90240
+ return await new Promise((resolve10, reject) => {
90241
90241
  stdout.write(`${question} `);
90242
90242
  let buf = "";
90243
90243
  const onData = (key) => {
@@ -90247,7 +90247,7 @@ async function promptHidden(question) {
90247
90247
  ttyStdin.removeListener("data", onData);
90248
90248
  stdout.write(`
90249
90249
  `);
90250
- resolve7(buf);
90250
+ resolve10(buf);
90251
90251
  return;
90252
90252
  }
90253
90253
  if (ch === "\x03") {
@@ -105486,10 +105486,17 @@ function loadConfig() {
105486
105486
  const envToken = process.env.PERCHER_TOKEN;
105487
105487
  return {
105488
105488
  apiUrl: envUrl ?? file2.apiUrl ?? DEFAULT_API_URL,
105489
- token: envToken ?? file2.token ?? null,
105490
- anonClaim: file2.anonClaim ?? null
105489
+ token: envToken ?? file2.token ?? null
105491
105490
  };
105492
105491
  }
105492
+ function readAnonClaims() {
105493
+ const file2 = readFile2();
105494
+ const claims = { ...file2.anonClaims ?? {} };
105495
+ if (file2.anonClaim?.app && !claims[file2.anonClaim.app]) {
105496
+ claims[file2.anonClaim.app] = file2.anonClaim;
105497
+ }
105498
+ return claims;
105499
+ }
105493
105500
  function saveConfig(partial2) {
105494
105501
  const p = configPath();
105495
105502
  mkdirSync3(dirname3(p), { recursive: true });
@@ -105499,6 +105506,21 @@ function saveConfig(partial2) {
105499
105506
  writeFileSync3(tmp, JSON.stringify(merged, null, 2), "utf8");
105500
105507
  renameSync(tmp, p);
105501
105508
  }
105509
+ function getAnonClaim(app) {
105510
+ return readAnonClaims()[app] ?? null;
105511
+ }
105512
+ function setAnonClaim(state) {
105513
+ const claims = { ...readAnonClaims(), [state.app]: state };
105514
+ saveConfig({ anonClaims: claims, anonClaim: null });
105515
+ }
105516
+ function clearAnonClaim(app) {
105517
+ const claims = { ...readAnonClaims() };
105518
+ delete claims[app];
105519
+ saveConfig({ anonClaims: claims, anonClaim: null });
105520
+ }
105521
+ function listAnonClaimApps() {
105522
+ return Object.keys(readAnonClaims());
105523
+ }
105502
105524
 
105503
105525
  // ../client/dist/errors.js
105504
105526
  class PercherApiError extends Error {
@@ -106534,13 +106556,14 @@ var claimInputSchema = exports_external.object({
106534
106556
  claimToken: exports_external.string().optional().describe("The one-time claim token returned by the anonymous publish (pcl_…)")
106535
106557
  });
106536
106558
  async function claim(ctx, input = {}) {
106537
- const state = loadConfig().anonClaim;
106538
- const app = input.app ?? state?.app ?? readPercherTomlAppName(ctx.cwd) ?? undefined;
106539
- const claimToken = input.claimToken ?? state?.claimToken;
106559
+ const tomlApp = readPercherTomlAppName(ctx.cwd) ?? undefined;
106560
+ const remembered = listAnonClaimApps();
106561
+ const app = input.app ?? tomlApp ?? (remembered.length === 1 ? remembered[0] : undefined);
106562
+ const claimToken = input.claimToken ?? (app ? getAnonClaim(app)?.claimToken ?? undefined : undefined);
106540
106563
  if (!app) {
106541
106564
  return {
106542
106565
  status: "needs_token",
106543
- summary: "No app to claim. Pass --app (or run from the project that published it) and the claim token."
106566
+ summary: remembered.length > 1 ? `Multiple anonymous apps are remembered (${remembered.join(", ")}). Pass --app to choose one.` : "No app to claim. Pass --app (or run from the project that published it) and the claim token."
106544
106567
  };
106545
106568
  }
106546
106569
  if (!claimToken) {
@@ -106550,8 +106573,7 @@ async function claim(ctx, input = {}) {
106550
106573
  };
106551
106574
  }
106552
106575
  const result = await ctx.client.apps.claim(app, { claimToken });
106553
- if (state)
106554
- saveConfig({ anonClaim: null });
106576
+ clearAnonClaim(app);
106555
106577
  return {
106556
106578
  status: "claimed",
106557
106579
  app: result.name,
@@ -110866,9 +110888,2260 @@ function collectWarnings2(collections, rlsPolicies, unsupported) {
110866
110888
  }
110867
110889
  return warnings;
110868
110890
  }
110891
+ // ../core/dist/commands/migrate-supabase-rewrite.js
110892
+ import { mkdir as mkdir3, writeFile as writeFile3 } from "node:fs/promises";
110893
+ import { dirname as dirname5, join as join19, relative as relative5, resolve as resolve8, sep as sep4 } from "node:path";
110894
+
110895
+ // ../core/dist/commands/migrate-supabase-recipes.js
110896
+ var AUTH_RECIPES = {
110897
+ "auth.getSession": {
110898
+ title: "getSession → pb.authStore",
110899
+ recipe: "PocketBase keeps the session in `pb.authStore` (local, synchronous — no await). Replace `const { data: { session } } = await supabase.auth.getSession()` with `pb.authStore.isValid` (logged in?), `pb.authStore.record` (the user record), and `pb.authStore.token` (the JWT)."
110900
+ },
110901
+ "auth.getClaims": {
110902
+ title: "getClaims → pb.authStore.record",
110903
+ recipe: "PocketBase has no separate claims endpoint. The authenticated user's fields live on `pb.authStore.record`; use `pb.authStore.isValid` for the logged-in check. Read them directly — no await, no token decode."
110904
+ },
110905
+ "auth.getUser": {
110906
+ title: "getUser → pb.authStore.record",
110907
+ recipe: "`pb.authStore.record` is the current user record (or null), read synchronously. Supabase's `getUser()` returns `Promise<{ data: { user } }>`, so drop the await and the `.data.user` unwrap."
110908
+ },
110909
+ "auth.signInWithOtp": {
110910
+ title: "signInWithOtp → requestOTP + authWithOTP",
110911
+ recipe: "PocketBase email-OTP is two steps: `const req = await pb.collection('users').requestOTP(email)` sends the code, then on a second screen `await pb.collection('users').authWithOTP(req.otpId, code)` verifies it. Supabase's single magic-link `signInWithOtp` maps to the first step — you'll add a code-entry screen for the second."
110912
+ },
110913
+ "auth.verifyOtp": {
110914
+ title: "verifyOtp → authWithOTP",
110915
+ recipe: "Pairs with requestOTP: `await pb.collection('users').authWithOTP(otpId, code)` (otpId comes from the requestOTP response, not from the email link). Supabase's `token_hash` / `type` model doesn't carry over — keep the otpId from step one in component state."
110916
+ },
110917
+ "auth.resetPasswordForEmail": {
110918
+ title: "resetPasswordForEmail → requestPasswordReset",
110919
+ recipe: "`await pb.collection('users').requestPasswordReset(email)` sends the reset email. The confirm step lives on your reset page: `await pb.collection('users').confirmPasswordReset(token, newPassword, newPasswordConfirm)` (token comes from the email link)."
110920
+ },
110921
+ "auth.updateUser": {
110922
+ title: "updateUser → collection('users').update",
110923
+ recipe: "PocketBase updates by record id: `await pb.collection('users').update(pb.authStore.record.id, { ... })`. There's no implicit current-user update — pass the id explicitly. Email/password changes use the dedicated `requestEmailChange` / `confirmEmailChange` flows."
110924
+ },
110925
+ "auth.refreshSession": {
110926
+ title: "refreshSession → authRefresh",
110927
+ recipe: "`await pb.collection('users').authRefresh()` re-validates the stored token and refreshes `pb.authStore`. There's no refresh-token rotation to manage — PocketBase reissues the JWT in place."
110928
+ },
110929
+ "auth.onAuthStateChange": {
110930
+ title: "onAuthStateChange → pb.authStore.onChange",
110931
+ recipe: "`const unsubscribe = pb.authStore.onChange((token, record) => { ... })`. The callback receives `(token, record)`, NOT Supabase's `(event, session)` — there's no event-type string, so branch on `pb.authStore.isValid` inside the callback. It returns an unsubscribe function; call it on teardown."
110932
+ }
110933
+ };
110934
+ function recipeFor(pattern) {
110935
+ return AUTH_RECIPES[pattern] ?? null;
110936
+ }
110937
+ var GENERAL_AUTH_RECIPES = [
110938
+ {
110939
+ title: "Route guards → pb.authStore.isValid",
110940
+ recipe: "Gate protected routes on `pb.authStore.isValid` instead of inspecting a session object, e.g. `if (!pb.authStore.isValid) redirect('/login')`. `pb.authStore` is restored from storage on load, so the check works on the first render."
110941
+ }
110942
+ ];
110943
+ function renderRecipesSection(patterns2) {
110944
+ const seen = new Set;
110945
+ const recipes = [];
110946
+ for (const pattern of patterns2) {
110947
+ const recipe = recipeFor(pattern);
110948
+ if (recipe && !seen.has(recipe.title)) {
110949
+ seen.add(recipe.title);
110950
+ recipes.push(recipe);
110951
+ }
110952
+ }
110953
+ if (recipes.length === 0)
110954
+ return [];
110955
+ const lines = [];
110956
+ lines.push("## Recipes — Supabase auth → PocketBase");
110957
+ lines.push("");
110958
+ lines.push("Concrete PocketBase equivalents for the auth calls above. These are NOT auto-applied — the Supabase call is left in place so the app keeps working until you migrate it deliberately. See https://pocketbase.io/docs/authentication/.");
110959
+ lines.push("");
110960
+ for (const recipe of [...recipes, ...GENERAL_AUTH_RECIPES]) {
110961
+ lines.push(`### ${recipe.title}`);
110962
+ lines.push("");
110963
+ lines.push(recipe.recipe);
110964
+ lines.push("");
110965
+ }
110966
+ return lines;
110967
+ }
110968
+
110969
+ // ../core/dist/commands/migrate-supabase-scaffold.js
110970
+ var import_jscodeshift = __toESM(require_core3(), 1);
110971
+ import { posix } from "node:path";
110972
+ var tsx = import_jscodeshift.default.withParser("tsx");
110973
+ var CLIENT_FACTORIES = new Set(["createClient", "createBrowserClient", "createServerClient"]);
110974
+ function scaffoldPocketBaseClient(input) {
110975
+ const pbName = input.pbIdentifier ?? "pb";
110976
+ const codeFiles = input.files.filter((f) => f.kind === "code");
110977
+ const flags = [];
110978
+ for (const file2 of codeFiles) {
110979
+ if (isSupabaseClientModule(file2.source)) {
110980
+ flags.push({
110981
+ file: file2.relativePath,
110982
+ kind: "manual_review",
110983
+ pattern: "supabase.client_module",
110984
+ note: "This module sets up the Supabase client. It's kept while any Supabase call remains; once everything is migrated to PocketBase, delete it and the imports that reference it."
110985
+ });
110986
+ }
110987
+ }
110988
+ const existing = codeFiles.find((f) => exportsBinding(f.rewritten, pbName));
110989
+ let targetRelNoExt;
110990
+ let clientModule = null;
110991
+ let skippedReason;
110992
+ if (existing) {
110993
+ targetRelNoExt = stripExt(existing.relativePath);
110994
+ skippedReason = "pb_client_exists";
110995
+ } else {
110996
+ const ext = pickExtension(codeFiles);
110997
+ const baseNoExt = pickModuleBase(codeFiles);
110998
+ const targetRel = `${baseNoExt}.${ext}`;
110999
+ if (input.files.some((f) => f.relativePath === targetRel)) {
111000
+ flags.push({
111001
+ file: targetRel,
111002
+ kind: "manual_review",
111003
+ pattern: "scaffold.path_taken",
111004
+ note: `Couldn't auto-create a PocketBase client — \`${targetRel}\` already exists. Create one that exports \`${pbName}\` and import it in the rewritten files.`
111005
+ });
111006
+ return {
111007
+ clientModule: null,
111008
+ importInsertions: new Map,
111009
+ flags,
111010
+ skippedReason: "target_path_taken"
111011
+ };
111012
+ }
111013
+ targetRelNoExt = baseNoExt;
111014
+ clientModule = { relativePath: targetRel, content: renderClientModule(pbName, codeFiles) };
111015
+ }
111016
+ const importInsertions = new Map;
111017
+ const changed = new Set(input.changedRelPaths);
111018
+ for (const file2 of codeFiles) {
111019
+ if (!changed.has(file2.relativePath))
111020
+ continue;
111021
+ if (file2.relativePath === clientModule?.relativePath)
111022
+ continue;
111023
+ if (!referencesUnboundIdentifier(file2.rewritten, pbName))
111024
+ continue;
111025
+ const importPath = computeImportPath(file2.relativePath, targetRelNoExt);
111026
+ const next = insertNamedImport(file2.rewritten, pbName, importPath);
111027
+ if (next !== null)
111028
+ importInsertions.set(file2.relativePath, next);
111029
+ }
111030
+ return { clientModule, importInsertions, flags, ...skippedReason ? { skippedReason } : {} };
111031
+ }
111032
+ function renderClientModule(pbName, codeFiles) {
111033
+ const usesViteEnv = codeFiles.some((f) => f.source.includes("import.meta.env"));
111034
+ const accessor = usesViteEnv ? "import.meta.env.VITE_POCKETBASE_URL" : "process.env.POCKETBASE_URL";
111035
+ return [
111036
+ 'import PocketBase from "pocketbase";',
111037
+ "",
111038
+ "// Percher injects the PocketBase URL at deploy time. This is a working",
111039
+ "// default — adjust the URL accessor to match your framework if needed.",
111040
+ `export const ${pbName} = new PocketBase(${accessor});`,
111041
+ ""
111042
+ ].join(`
111043
+ `);
111044
+ }
111045
+ function pickExtension(codeFiles) {
111046
+ return codeFiles.some((f) => f.relativePath.endsWith(".ts") || f.relativePath.endsWith(".tsx")) ? "ts" : "js";
111047
+ }
111048
+ function pickModuleBase(codeFiles) {
111049
+ const hasSrc = codeFiles.some((f) => f.relativePath.startsWith("src/"));
111050
+ return hasSrc ? "src/lib/pocketbase" : "lib/pocketbase";
111051
+ }
111052
+ function stripExt(relPath) {
111053
+ const dot = relPath.lastIndexOf(".");
111054
+ return dot > relPath.lastIndexOf("/") ? relPath.slice(0, dot) : relPath;
111055
+ }
111056
+ function computeImportPath(fromFileRel, targetRelNoExt) {
111057
+ let rel = posix.relative(posix.dirname(fromFileRel), targetRelNoExt);
111058
+ if (!rel.startsWith("."))
111059
+ rel = `./${rel}`;
111060
+ return rel;
111061
+ }
111062
+ function insertNamedImport(source, name, spec) {
111063
+ let root;
111064
+ try {
111065
+ root = tsx(source);
111066
+ } catch {
111067
+ return null;
111068
+ }
111069
+ const decl = import_jscodeshift.default.importDeclaration([import_jscodeshift.default.importSpecifier(import_jscodeshift.default.identifier(name))], import_jscodeshift.default.literal(spec));
111070
+ const program = root.get().node.program;
111071
+ program.body.unshift(decl);
111072
+ return root.toSource({ quote: "double" });
111073
+ }
111074
+ function referencesUnboundIdentifier(source, name) {
111075
+ let root;
111076
+ try {
111077
+ root = tsx(source);
111078
+ } catch {
111079
+ return false;
111080
+ }
111081
+ let declared = false;
111082
+ root.find(import_jscodeshift.default.ImportDeclaration).forEach((p) => {
111083
+ for (const spec of p.node.specifiers ?? []) {
111084
+ if (spec.local?.name === name)
111085
+ declared = true;
111086
+ }
111087
+ });
111088
+ root.find(import_jscodeshift.default.VariableDeclarator).forEach((p) => {
111089
+ if (p.node.id.type === "Identifier" && p.node.id.name === name) {
111090
+ declared = true;
111091
+ }
111092
+ });
111093
+ let used = false;
111094
+ root.find(import_jscodeshift.default.MemberExpression).forEach((p) => {
111095
+ const obj = p.node.object;
111096
+ if (obj.type === "Identifier" && obj.name === name)
111097
+ used = true;
111098
+ });
111099
+ return used && !declared;
111100
+ }
111101
+ function exportsBinding(source, name) {
111102
+ if (!source.includes(`export`) || !source.includes(name))
111103
+ return false;
111104
+ let root;
111105
+ try {
111106
+ root = tsx(source);
111107
+ } catch {
111108
+ return false;
111109
+ }
111110
+ let found = false;
111111
+ root.find(import_jscodeshift.default.ExportNamedDeclaration).forEach((p) => {
111112
+ const node = p.node;
111113
+ if (node.declaration?.type === "VariableDeclaration") {
111114
+ for (const d of node.declaration.declarations) {
111115
+ if (d.type === "VariableDeclarator" && d.id.type === "Identifier" && d.id.name === name) {
111116
+ found = true;
111117
+ }
111118
+ }
111119
+ }
111120
+ for (const spec of node.specifiers ?? []) {
111121
+ const exported = spec.exported;
111122
+ if (exported?.type === "Identifier" && exported.name === name) {
111123
+ found = true;
111124
+ }
111125
+ }
111126
+ });
111127
+ return found;
111128
+ }
111129
+ function isSupabaseClientModule(source) {
111130
+ if (!source.includes("@supabase/"))
111131
+ return false;
111132
+ let root;
111133
+ try {
111134
+ root = tsx(source);
111135
+ } catch {
111136
+ return false;
111137
+ }
111138
+ let importsSupabase = false;
111139
+ root.find(import_jscodeshift.default.ImportDeclaration).forEach((p) => {
111140
+ const src = p.node.source.value;
111141
+ if (typeof src === "string" && src.startsWith("@supabase/"))
111142
+ importsSupabase = true;
111143
+ });
111144
+ if (!importsSupabase)
111145
+ return false;
111146
+ let callsFactory = false;
111147
+ root.find(import_jscodeshift.default.CallExpression).forEach((p) => {
111148
+ const callee = p.node.callee;
111149
+ if (callee.type === "Identifier" && CLIENT_FACTORIES.has(callee.name)) {
111150
+ callsFactory = true;
111151
+ }
111152
+ });
111153
+ return callsFactory;
111154
+ }
111155
+
111156
+ // ../core/dist/commands/migrate-supabase-status.js
111157
+ var import_cross_spawn = __toESM(require_cross_spawn(), 1);
111158
+ import { readFile as readFile4 } from "node:fs/promises";
111159
+ import { join as join18, relative as relative4, resolve as resolve7 } from "node:path";
111160
+
111161
+ // ../core/dist/commands/migrate-supabase-sdk.js
111162
+ var import_jscodeshift2 = __toESM(require_core3(), 1);
111163
+ var tsx2 = import_jscodeshift2.default.withParser("tsx");
111164
+ function rewriteSupabaseSdk(input) {
111165
+ const pbName = input.pbIdentifier ?? "pb";
111166
+ const supabaseNames = new Set(input.supabaseIdentifiers ?? ["supabase"]);
111167
+ if (!sourceMentionsSupabase(input.source, supabaseNames)) {
111168
+ return { rewritten: input.source, flags: [], changed: false };
111169
+ }
111170
+ let root;
111171
+ try {
111172
+ root = tsx2(input.source);
111173
+ } catch (err) {
111174
+ return {
111175
+ rewritten: input.source,
111176
+ flags: [],
111177
+ changed: false,
111178
+ parseError: err instanceof Error ? err.message : String(err)
111179
+ };
111180
+ }
111181
+ const flags = [];
111182
+ const state = { mutated: false };
111183
+ rewriteAuthCalls(root, supabaseNames, pbName, flags, state);
111184
+ rewriteFromCalls(root, supabaseNames, pbName, flags, state);
111185
+ flagUnsupportedPatterns(root, supabaseNames, flags);
111186
+ if (!state.mutated) {
111187
+ return { rewritten: input.source, flags, changed: false };
111188
+ }
111189
+ return {
111190
+ rewritten: root.toSource({ quote: "double" }),
111191
+ flags,
111192
+ changed: true
111193
+ };
111194
+ }
111195
+ function consumesDataErrorEnvelope(path) {
111196
+ let outer = path.node;
111197
+ let outerParent = path.parent?.node;
111198
+ if (outerParent?.type === "AwaitExpression") {
111199
+ const aw = outerParent;
111200
+ if (aw.argument === path.node) {
111201
+ outer = outerParent;
111202
+ outerParent = path.parent.parent?.node;
111203
+ }
111204
+ }
111205
+ if (!outerParent)
111206
+ return false;
111207
+ if (outerParent.type === "MemberExpression") {
111208
+ const m = outerParent;
111209
+ if (m.object === outer && m.property.type === "Identifier") {
111210
+ const propName = m.property.name;
111211
+ if (propName === "data" || propName === "error")
111212
+ return true;
111213
+ }
111214
+ return false;
111215
+ }
111216
+ if (outerParent.type === "VariableDeclarator") {
111217
+ const v = outerParent;
111218
+ if (v.init === outer && v.id.type === "ObjectPattern") {
111219
+ return objectPatternHasDataOrError(v.id);
111220
+ }
111221
+ return false;
111222
+ }
111223
+ if (outerParent.type === "AssignmentExpression") {
111224
+ const a = outerParent;
111225
+ if (a.right === outer && a.left.type === "ObjectPattern") {
111226
+ return objectPatternHasDataOrError(a.left);
111227
+ }
111228
+ return false;
111229
+ }
111230
+ return false;
111231
+ }
111232
+ function objectPatternHasDataOrError(pattern) {
111233
+ for (const prop of pattern.properties) {
111234
+ if ((prop.type === "Property" || prop.type === "ObjectProperty") && "key" in prop && prop.key.type === "Identifier") {
111235
+ const name = prop.key.name;
111236
+ if (name === "data" || name === "error")
111237
+ return true;
111238
+ }
111239
+ }
111240
+ return false;
111241
+ }
111242
+ function flagEnvelopeManualReview(path, pattern, flags) {
111243
+ flags.push(makeFlag(path, "manual_review", `${pattern}.envelope`, `Call site consumes the Supabase \`{ data, error }\` envelope — PocketBase returns plain values. Skipping rewrite; unwrap the destructure (or .data/.error access) manually, then re-run the migrator.`));
111244
+ }
111245
+ function sourceMentionsSupabase(source, supabaseNames) {
111246
+ if (source.includes("@supabase/supabase-js"))
111247
+ return true;
111248
+ for (const name of supabaseNames) {
111249
+ if (source.includes(name))
111250
+ return true;
111251
+ }
111252
+ return false;
111253
+ }
111254
+ function rewriteAuthCalls(root, supabaseNames, pbName, flags, state) {
111255
+ root.find(import_jscodeshift2.default.CallExpression).filter((path) => isSupabaseAuthCall(path, supabaseNames)).forEach((path) => {
111256
+ const callee = path.node.callee;
111257
+ const method = callee.property.name;
111258
+ switch (method) {
111259
+ case "signInWithPassword":
111260
+ replaceAuthSignIn(path, pbName, flags, state);
111261
+ return;
111262
+ case "signUp":
111263
+ replaceAuthSignUp(path, pbName, flags, state);
111264
+ return;
111265
+ case "signOut":
111266
+ replaceAuthSignOut(path, pbName, flags, state);
111267
+ return;
111268
+ case "getUser":
111269
+ replaceAuthGetUser(path, pbName, flags, state);
111270
+ return;
111271
+ case "onAuthStateChange":
111272
+ replaceAuthOnChange(path, pbName, flags, state);
111273
+ return;
111274
+ default: {
111275
+ const recipe = recipeFor(`auth.${method}`);
111276
+ const note = recipe ? `supabase.auth.${method}(...) isn't auto-translated (the PB equivalent diverges) — it still calls Supabase. ${recipe.recipe}` : `supabase.auth.${method}(...) isn't auto-translated — it still calls Supabase. Map it to PocketBase's auth API by hand (https://pocketbase.io/docs/authentication/).`;
111277
+ flags.push(makeFlag(path, "unsupported", `auth.${method}`, note));
111278
+ return;
111279
+ }
111280
+ }
111281
+ });
111282
+ }
111283
+ function replaceAuthOnChange(path, pbName, flags, state) {
111284
+ const callback = path.node.arguments[0];
111285
+ if (!callback) {
111286
+ flags.push(makeFlag(path, "manual_review", "auth.onAuthStateChange", "onAuthStateChange called with no args — manual review."));
111287
+ return;
111288
+ }
111289
+ const replacement = import_jscodeshift2.default.callExpression(import_jscodeshift2.default.memberExpression(import_jscodeshift2.default.memberExpression(import_jscodeshift2.default.identifier(pbName), import_jscodeshift2.default.identifier("authStore")), import_jscodeshift2.default.identifier("onChange")), [callback]);
111290
+ applyRewrite(path, replacement, "manual_review", "auth.onAuthStateChange", "onAuthStateChange → pb.authStore.onChange — the callback signature changes: Supabase passes `(event, session)`, PB passes `(token, model)`. Rewrite the callback body.", flags, state);
111291
+ }
111292
+ function isSupabaseAuthCall(path, supabaseNames) {
111293
+ const callee = path.node.callee;
111294
+ if (callee.type !== "MemberExpression")
111295
+ return false;
111296
+ if (callee.property.type !== "Identifier")
111297
+ return false;
111298
+ const object2 = callee.object;
111299
+ if (object2.type !== "MemberExpression")
111300
+ return false;
111301
+ if (object2.property.type !== "Identifier" || object2.property.name !== "auth")
111302
+ return false;
111303
+ if (object2.object.type !== "Identifier")
111304
+ return false;
111305
+ return supabaseNames.has(object2.object.name);
111306
+ }
111307
+ function replaceAuthSignIn(path, pbName, flags, state) {
111308
+ const arg = path.node.arguments[0];
111309
+ if (arg?.type !== "ObjectExpression") {
111310
+ flags.push(makeFlag(path, "manual_review", "auth.signInWithPassword", "auth.signInWithPassword called with non-object argument — manual review needed."));
111311
+ return;
111312
+ }
111313
+ const emailExpr = findObjectProp(arg, "email");
111314
+ const passwordExpr = findObjectProp(arg, "password");
111315
+ if (!emailExpr || !passwordExpr) {
111316
+ flags.push(makeFlag(path, "manual_review", "auth.signInWithPassword", "auth.signInWithPassword object missing email or password — manual review needed."));
111317
+ return;
111318
+ }
111319
+ if (consumesDataErrorEnvelope(path)) {
111320
+ flagEnvelopeManualReview(path, "auth.signInWithPassword", flags);
111321
+ return;
111322
+ }
111323
+ const replacement = import_jscodeshift2.default.callExpression(import_jscodeshift2.default.memberExpression(import_jscodeshift2.default.callExpression(import_jscodeshift2.default.memberExpression(import_jscodeshift2.default.identifier(pbName), import_jscodeshift2.default.identifier("collection")), [import_jscodeshift2.default.literal("users")]), import_jscodeshift2.default.identifier("authWithPassword")), [emailExpr, passwordExpr]);
111324
+ applyRewrite(path, replacement, "rewritten", "auth.signInWithPassword", 'signInWithPassword → pb.collection("users").authWithPassword', flags, state);
111325
+ }
111326
+ function replaceAuthSignUp(path, pbName, flags, state) {
111327
+ const arg = path.node.arguments[0];
111328
+ if (arg?.type !== "ObjectExpression") {
111329
+ flags.push(makeFlag(path, "manual_review", "auth.signUp", "auth.signUp called with non-object argument — manual review needed."));
111330
+ return;
111331
+ }
111332
+ const emailExpr = findObjectProp(arg, "email");
111333
+ const passwordExpr = findObjectProp(arg, "password");
111334
+ if (!emailExpr || !passwordExpr) {
111335
+ flags.push(makeFlag(path, "manual_review", "auth.signUp", "auth.signUp object missing email or password — manual review needed."));
111336
+ return;
111337
+ }
111338
+ if (consumesDataErrorEnvelope(path)) {
111339
+ flagEnvelopeManualReview(path, "auth.signUp", flags);
111340
+ return;
111341
+ }
111342
+ const replacement = import_jscodeshift2.default.callExpression(import_jscodeshift2.default.memberExpression(import_jscodeshift2.default.callExpression(import_jscodeshift2.default.memberExpression(import_jscodeshift2.default.identifier(pbName), import_jscodeshift2.default.identifier("collection")), [import_jscodeshift2.default.literal("users")]), import_jscodeshift2.default.identifier("create")), [
111343
+ import_jscodeshift2.default.objectExpression([
111344
+ import_jscodeshift2.default.property("init", import_jscodeshift2.default.identifier("email"), emailExpr),
111345
+ import_jscodeshift2.default.property("init", import_jscodeshift2.default.identifier("password"), passwordExpr),
111346
+ import_jscodeshift2.default.property("init", import_jscodeshift2.default.identifier("passwordConfirm"), passwordExpr)
111347
+ ])
111348
+ ]);
111349
+ applyRewrite(path, replacement, "rewritten", "auth.signUp", 'signUp → pb.collection("users").create({...passwordConfirm})', flags, state);
111350
+ }
111351
+ function replaceAuthSignOut(path, pbName, flags, state) {
111352
+ if (consumesDataErrorEnvelope(path)) {
111353
+ flagEnvelopeManualReview(path, "auth.signOut", flags);
111354
+ return;
111355
+ }
111356
+ const replacement = import_jscodeshift2.default.callExpression(import_jscodeshift2.default.memberExpression(import_jscodeshift2.default.memberExpression(import_jscodeshift2.default.identifier(pbName), import_jscodeshift2.default.identifier("authStore")), import_jscodeshift2.default.identifier("clear")), []);
111357
+ applyRewrite(path, replacement, "rewritten", "auth.signOut", "signOut → pb.authStore.clear()", flags, state);
111358
+ }
111359
+ function replaceAuthGetUser(path, pbName, flags, state) {
111360
+ if (consumesDataErrorEnvelope(path)) {
111361
+ flagEnvelopeManualReview(path, "auth.getUser", flags);
111362
+ return;
111363
+ }
111364
+ const replacement = import_jscodeshift2.default.memberExpression(import_jscodeshift2.default.memberExpression(import_jscodeshift2.default.identifier(pbName), import_jscodeshift2.default.identifier("authStore")), import_jscodeshift2.default.identifier("model"));
111365
+ applyRewrite(path, replacement, "manual_review", "auth.getUser", "getUser → pb.authStore.model — note Supabase returned Promise<{ data: { user } }>, PB returns the record sync; remove awaits + .data.user access.", flags, state);
111366
+ }
111367
+ function rewriteFromCalls(root, supabaseNames, pbName, flags, state) {
111368
+ root.find(import_jscodeshift2.default.CallExpression).filter((path) => isSupabaseFromTerminal(path, supabaseNames)).forEach((path) => {
111369
+ rewriteFromChain(path, supabaseNames, pbName, flags, state);
111370
+ });
111371
+ }
111372
+ function isSupabaseFromTerminal(path, supabaseNames) {
111373
+ let fromCall = null;
111374
+ let cursor = path.node;
111375
+ while (cursor.type === "CallExpression") {
111376
+ const call = cursor;
111377
+ if (call.callee.type !== "MemberExpression")
111378
+ break;
111379
+ const callee = call.callee;
111380
+ if (callee.property.type === "Identifier" && callee.property.name === "from") {
111381
+ fromCall = call;
111382
+ break;
111383
+ }
111384
+ cursor = callee.object;
111385
+ }
111386
+ if (!fromCall)
111387
+ return false;
111388
+ const fromCallee = fromCall.callee;
111389
+ if (fromCallee.object.type !== "Identifier")
111390
+ return false;
111391
+ if (!supabaseNames.has(fromCallee.object.name))
111392
+ return false;
111393
+ const parent = path.parent?.node;
111394
+ if (parent?.type === "MemberExpression") {
111395
+ const parentMember = parent;
111396
+ if (parentMember.object === path.node)
111397
+ return false;
111398
+ }
111399
+ return true;
111400
+ }
111401
+ function rewriteFromChain(path, _supabaseNames, pbName, flags, state) {
111402
+ const decomposed = decomposeFromChain(path.node);
111403
+ if (!decomposed) {
111404
+ flags.push(makeFlag(path, "manual_review", "from.chain", "Couldn't decompose .from() chain shape — manual review."));
111405
+ return;
111406
+ }
111407
+ const { table, steps } = decomposed;
111408
+ const terminal = steps[0];
111409
+ if (!terminal) {
111410
+ return;
111411
+ }
111412
+ switch (terminal.method) {
111413
+ case "select":
111414
+ rewriteSelect(path, pbName, table, steps, flags, state);
111415
+ return;
111416
+ case "insert":
111417
+ rewriteInsert(path, pbName, table, terminal, flags, state);
111418
+ return;
111419
+ case "update":
111420
+ rewriteUpdate(path, pbName, table, steps, flags, state);
111421
+ return;
111422
+ case "delete":
111423
+ rewriteDelete(path, pbName, table, steps, flags, state);
111424
+ return;
111425
+ case "upsert":
111426
+ flags.push(makeFlag(path, "unsupported", "from.upsert", `from(${JSON.stringify(table)}).upsert(...) — PB has no upsert primitive. Rewrite as getOne (catch 404) → update-or-create.`));
111427
+ return;
111428
+ default:
111429
+ flags.push(makeFlag(path, "manual_review", `from.${terminal.method}`, `from(${JSON.stringify(table)}).${terminal.method}(...) has no chunk-1 rewrite — manual review.`));
111430
+ }
111431
+ }
111432
+ function decomposeFromChain(outer) {
111433
+ const reversedSteps = [];
111434
+ let node = outer;
111435
+ while (node.type === "CallExpression") {
111436
+ const call = node;
111437
+ if (call.callee.type !== "MemberExpression")
111438
+ break;
111439
+ const callee = call.callee;
111440
+ const method = callee.property.type === "Identifier" ? callee.property.name : null;
111441
+ if (method === null)
111442
+ return null;
111443
+ if (method === "from") {
111444
+ const arg = call.arguments[0];
111445
+ if (!arg || arg.type !== "Literal" && arg.type !== "StringLiteral")
111446
+ return null;
111447
+ const table = arg.value;
111448
+ if (typeof table !== "string")
111449
+ return null;
111450
+ return { table, steps: reversedSteps.reverse() };
111451
+ }
111452
+ reversedSteps.push({ method, args: call.arguments });
111453
+ node = callee.object;
111454
+ }
111455
+ return null;
111456
+ }
111457
+ function rewriteSelect(path, pbName, table, steps, flags, state) {
111458
+ if (consumesDataErrorEnvelope(path)) {
111459
+ flagEnvelopeManualReview(path, "from.select", flags);
111460
+ return;
111461
+ }
111462
+ const select = steps[0];
111463
+ if (!select)
111464
+ return;
111465
+ const tail = steps.slice(1);
111466
+ const opts = {};
111467
+ let needsReview = false;
111468
+ const reviewNotes = [];
111469
+ let usePagination = false;
111470
+ let paginationPage = 1;
111471
+ let paginationPerPage = 0;
111472
+ const fieldsValue = extractSelectFields(select);
111473
+ if (fieldsValue !== null)
111474
+ opts.fields = import_jscodeshift2.default.literal(fieldsValue);
111475
+ for (const step of tail) {
111476
+ switch (step.method) {
111477
+ case "eq": {
111478
+ const result = buildEqFilter(step);
111479
+ if (!result) {
111480
+ needsReview = true;
111481
+ reviewNotes.push(`.eq() arguments not in the (column-literal, value) shape — manual review.`);
111482
+ continue;
111483
+ }
111484
+ opts.filter = result.identifierValue ? combineFilterDynamic(opts.filter, result.expression) : combineFilterStatic(opts.filter, result.expression);
111485
+ if (result.identifierValue) {
111486
+ needsReview = true;
111487
+ reviewNotes.push(`.eq(${JSON.stringify(result.column)}, <identifier>) — verify the value is escape-safe for PB filter strings (no double-quotes / backslashes).`);
111488
+ }
111489
+ break;
111490
+ }
111491
+ case "order": {
111492
+ const sortFrag = buildSortFragment(step);
111493
+ if (!sortFrag) {
111494
+ needsReview = true;
111495
+ reviewNotes.push(`.order() arguments not in the recognised shape — manual review.`);
111496
+ continue;
111497
+ }
111498
+ opts.sort = import_jscodeshift2.default.literal(opts.sort ? `${literalString(opts.sort)},${sortFrag}` : sortFrag);
111499
+ break;
111500
+ }
111501
+ case "limit": {
111502
+ const arg = step.args[0];
111503
+ const n = extractNumber(arg);
111504
+ if (n === null) {
111505
+ needsReview = true;
111506
+ reviewNotes.push(`.limit() argument isn't a literal number — manual review.`);
111507
+ continue;
111508
+ }
111509
+ if (n <= 0) {
111510
+ flags.push(makeFlag(path, "manual_review", "from.select.limit_invalid", `from(${JSON.stringify(table)}).select(...).limit(${n}) — non-positive limit doesn't translate to PB pagination. Manual review.`));
111511
+ return;
111512
+ }
111513
+ usePagination = true;
111514
+ paginationPerPage = Math.max(paginationPerPage, n);
111515
+ break;
111516
+ }
111517
+ case "range": {
111518
+ const startArg = step.args[0];
111519
+ const endArg = step.args[1];
111520
+ const startN = extractNumber(startArg);
111521
+ const endN = extractNumber(endArg);
111522
+ if (startN === null || endN === null) {
111523
+ needsReview = true;
111524
+ reviewNotes.push(`.range() arguments aren't literal numbers — manual review.`);
111525
+ continue;
111526
+ }
111527
+ const perPage = endN - startN + 1;
111528
+ if (perPage <= 0) {
111529
+ flags.push(makeFlag(path, "manual_review", "from.select.range_invalid", `from(${JSON.stringify(table)}).select(...).range(${startN}, ${endN}) — end < start; PB pagination has no equivalent. Manual review.`));
111530
+ return;
111531
+ }
111532
+ usePagination = true;
111533
+ paginationPerPage = Math.max(paginationPerPage, perPage);
111534
+ if (startN === 0) {
111535
+ paginationPage = 1;
111536
+ } else if (startN % perPage === 0) {
111537
+ paginationPage = Math.floor(startN / perPage) + 1;
111538
+ } else {
111539
+ needsReview = true;
111540
+ reviewNotes.push(`.range(${startN}, ${endN}) — start isn't on a page boundary; PB's page math doesn't translate cleanly. Manual review.`);
111541
+ }
111542
+ break;
111543
+ }
111544
+ case "single": {
111545
+ flags.push(makeFlag(path, "manual_review", "from.select.single", `from(${JSON.stringify(table)}).select(...).single() — PB's getFullList returns an array; getFirstListItem(filter) is the single-record equivalent but takes a filter string. Rewrite this chain by hand: pick getFirstListItem with the right filter OR [0]-index the array result.`));
111546
+ return;
111547
+ }
111548
+ default: {
111549
+ flags.push(makeFlag(path, "manual_review", `from.select.${step.method}`, `from(${JSON.stringify(table)}).select(...).${step.method}(...) has no chunk-2 rewrite — manual review.`));
111550
+ return;
111551
+ }
111552
+ }
111553
+ }
111554
+ let methodName;
111555
+ let methodArgs;
111556
+ if (usePagination) {
111557
+ methodName = "getList";
111558
+ const trailingOpts = buildOptionsObject(opts);
111559
+ methodArgs = [import_jscodeshift2.default.literal(paginationPage), import_jscodeshift2.default.literal(paginationPerPage)];
111560
+ if (trailingOpts)
111561
+ methodArgs.push(trailingOpts);
111562
+ } else {
111563
+ methodName = "getFullList";
111564
+ const optsObj = buildOptionsObject(opts);
111565
+ methodArgs = optsObj ? [optsObj] : [];
111566
+ }
111567
+ const replacement = import_jscodeshift2.default.callExpression(import_jscodeshift2.default.memberExpression(import_jscodeshift2.default.callExpression(import_jscodeshift2.default.memberExpression(import_jscodeshift2.default.identifier(pbName), import_jscodeshift2.default.identifier("collection")), [import_jscodeshift2.default.literal(table)]), import_jscodeshift2.default.identifier(methodName)), methodArgs);
111568
+ const kind = needsReview ? "manual_review" : "rewritten";
111569
+ const baseNote = `from(${JSON.stringify(table)}).select(...) → pb.collection(...).${methodName}(...)`;
111570
+ const note = needsReview ? `${baseNote} — ${reviewNotes.join(" · ")}` : baseNote;
111571
+ applyRewrite(path, replacement, kind, "from.select", note, flags, state);
111572
+ }
111573
+ function extractSelectFields(select) {
111574
+ const first = select.args[0];
111575
+ if (!first)
111576
+ return null;
111577
+ if ((first.type === "Literal" || first.type === "StringLiteral") && typeof first.value === "string") {
111578
+ const val = first.value;
111579
+ if (val === "*" || val.length === 0)
111580
+ return null;
111581
+ return val;
111582
+ }
111583
+ return null;
111584
+ }
111585
+ function buildEqFilter(step) {
111586
+ const colArg = step.args[0];
111587
+ const valArg = step.args[1];
111588
+ if (!colArg || !valArg)
111589
+ return null;
111590
+ if (!(colArg.type === "Literal" || colArg.type === "StringLiteral") || typeof colArg.value !== "string") {
111591
+ return null;
111592
+ }
111593
+ const column = colArg.value;
111594
+ if (valArg.type === "Literal" || valArg.type === "StringLiteral" || valArg.type === "NumericLiteral" || valArg.type === "BooleanLiteral") {
111595
+ const v = valArg.value;
111596
+ if (typeof v === "string") {
111597
+ return {
111598
+ expression: import_jscodeshift2.default.literal(`${column} = "${escapeFilterString(v)}"`),
111599
+ column,
111600
+ identifierValue: false
111601
+ };
111602
+ }
111603
+ if (typeof v === "number" || typeof v === "boolean") {
111604
+ return {
111605
+ expression: import_jscodeshift2.default.literal(`${column} = ${v}`),
111606
+ column,
111607
+ identifierValue: false
111608
+ };
111609
+ }
111610
+ return null;
111611
+ }
111612
+ const template = import_jscodeshift2.default.templateLiteral([
111613
+ import_jscodeshift2.default.templateElement({ raw: `${column} = "`, cooked: `${column} = "` }, false),
111614
+ import_jscodeshift2.default.templateElement({ raw: `"`, cooked: `"` }, true)
111615
+ ], [valArg]);
111616
+ return {
111617
+ expression: template,
111618
+ column,
111619
+ identifierValue: true
111620
+ };
111621
+ }
111622
+ function escapeFilterString(s) {
111623
+ return s.replace(/\\/g, "\\\\").replace(/"/g, "\\\"");
111624
+ }
111625
+ function combineFilterStatic(current, next) {
111626
+ if (!current)
111627
+ return next;
111628
+ const a = literalString(current);
111629
+ const b = literalString(next);
111630
+ if (a !== null && b !== null) {
111631
+ return import_jscodeshift2.default.literal(`(${a}) && (${b})`);
111632
+ }
111633
+ return combineFilterDynamic(current, next);
111634
+ }
111635
+ function combineFilterDynamic(current, next) {
111636
+ if (!current)
111637
+ return next;
111638
+ return import_jscodeshift2.default.templateLiteral([
111639
+ import_jscodeshift2.default.templateElement({ raw: "(", cooked: "(" }, false),
111640
+ import_jscodeshift2.default.templateElement({ raw: ") && (", cooked: ") && (" }, false),
111641
+ import_jscodeshift2.default.templateElement({ raw: ")", cooked: ")" }, true)
111642
+ ], [current, next]);
111643
+ }
111644
+ function literalString(node) {
111645
+ if (node?.type === "Literal" || node?.type === "StringLiteral") {
111646
+ const v = node.value;
111647
+ if (typeof v === "string")
111648
+ return v;
111649
+ }
111650
+ return null;
111651
+ }
111652
+ function buildSortFragment(step) {
111653
+ const colArg = step.args[0];
111654
+ if (!colArg)
111655
+ return null;
111656
+ if (!(colArg.type === "Literal" || colArg.type === "StringLiteral") || typeof colArg.value !== "string") {
111657
+ return null;
111658
+ }
111659
+ const column = colArg.value;
111660
+ let ascending = true;
111661
+ if (step.args.length >= 2) {
111662
+ const opts = step.args[1];
111663
+ if (opts?.type === "ObjectExpression") {
111664
+ const ascProp = findObjectProp(opts, "ascending");
111665
+ if (ascProp?.type === "Literal" || ascProp?.type === "BooleanLiteral") {
111666
+ ascending = ascProp.value === true;
111667
+ } else if (ascProp) {
111668
+ return null;
111669
+ }
111670
+ }
111671
+ }
111672
+ return ascending ? column : `-${column}`;
111673
+ }
111674
+ function extractNumber(node) {
111675
+ if (!node)
111676
+ return null;
111677
+ if (node.type === "Literal" || node.type === "NumericLiteral") {
111678
+ const v = node.value;
111679
+ if (typeof v === "number")
111680
+ return v;
111681
+ }
111682
+ if (node.type === "UnaryExpression") {
111683
+ const u = node;
111684
+ if (u.operator === "-") {
111685
+ const inner = extractNumber(u.argument);
111686
+ if (inner !== null)
111687
+ return -inner;
111688
+ }
111689
+ }
111690
+ return null;
111691
+ }
111692
+ function buildOptionsObject(opts) {
111693
+ const props = [];
111694
+ if (opts.fields !== undefined) {
111695
+ props.push(import_jscodeshift2.default.property("init", import_jscodeshift2.default.identifier("fields"), opts.fields));
111696
+ }
111697
+ if (opts.filter !== undefined) {
111698
+ props.push(import_jscodeshift2.default.property("init", import_jscodeshift2.default.identifier("filter"), opts.filter));
111699
+ }
111700
+ if (opts.sort !== undefined) {
111701
+ props.push(import_jscodeshift2.default.property("init", import_jscodeshift2.default.identifier("sort"), opts.sort));
111702
+ }
111703
+ if (props.length === 0)
111704
+ return null;
111705
+ return import_jscodeshift2.default.objectExpression(props);
111706
+ }
111707
+ function rewriteInsert(path, pbName, table, insert, flags, state) {
111708
+ if (consumesDataErrorEnvelope(path)) {
111709
+ flagEnvelopeManualReview(path, "from.insert", flags);
111710
+ return;
111711
+ }
111712
+ const arg = insert.args[0];
111713
+ if (!arg) {
111714
+ flags.push(makeFlag(path, "manual_review", "from.insert", "from(...).insert() called with no args — manual review."));
111715
+ return;
111716
+ }
111717
+ if (arg.type === "ArrayExpression") {
111718
+ flags.push(makeFlag(path, "manual_review", "from.insert.array", `from(${JSON.stringify(table)}).insert([...]) — PB's create takes one record at a time; wrap in a loop.`));
111719
+ return;
111720
+ }
111721
+ const replacement = import_jscodeshift2.default.callExpression(import_jscodeshift2.default.memberExpression(import_jscodeshift2.default.callExpression(import_jscodeshift2.default.memberExpression(import_jscodeshift2.default.identifier(pbName), import_jscodeshift2.default.identifier("collection")), [import_jscodeshift2.default.literal(table)]), import_jscodeshift2.default.identifier("create")), [arg]);
111722
+ applyRewrite(path, replacement, "rewritten", "from.insert", `from(${JSON.stringify(table)}).insert({...}) → pb.collection(...).create({...})`, flags, state);
111723
+ }
111724
+ function rewriteUpdate(path, pbName, table, steps, flags, state) {
111725
+ if (consumesDataErrorEnvelope(path)) {
111726
+ flagEnvelopeManualReview(path, "from.update", flags);
111727
+ return;
111728
+ }
111729
+ const update = steps[0];
111730
+ const eq = steps[1];
111731
+ if (steps.length !== 2 || !update || !eq || eq.method !== "eq") {
111732
+ flags.push(makeFlag(path, "manual_review", "from.update.shape", `from(${JSON.stringify(table)}).update(...) chain isn't the .update({...}).eq("id", v) shape — manual review.`));
111733
+ return;
111734
+ }
111735
+ const eqCol = eq.args[0];
111736
+ const eqVal = eq.args[1];
111737
+ if (!eqCol || !eqVal) {
111738
+ flags.push(makeFlag(path, "manual_review", "from.update.eq", "update().eq(...) call missing args — manual review."));
111739
+ return;
111740
+ }
111741
+ if (!((eqCol.type === "Literal" || eqCol.type === "StringLiteral") && eqCol.value === "id")) {
111742
+ flags.push(makeFlag(path, "manual_review", "from.update.eq_non_id", `from(${JSON.stringify(table)}).update().eq() filters on a non-id column — PB's update needs an id; chunk 2 will handle filter-based updates.`));
111743
+ return;
111744
+ }
111745
+ const updateArg = update.args[0];
111746
+ if (!updateArg) {
111747
+ flags.push(makeFlag(path, "manual_review", "from.update", "update() called with no args — manual review."));
111748
+ return;
111749
+ }
111750
+ const replacement = import_jscodeshift2.default.callExpression(import_jscodeshift2.default.memberExpression(import_jscodeshift2.default.callExpression(import_jscodeshift2.default.memberExpression(import_jscodeshift2.default.identifier(pbName), import_jscodeshift2.default.identifier("collection")), [import_jscodeshift2.default.literal(table)]), import_jscodeshift2.default.identifier("update")), [eqVal, updateArg]);
111751
+ applyRewrite(path, replacement, "rewritten", "from.update", `from(${JSON.stringify(table)}).update({...}).eq("id", v) → pb.collection(...).update(v, {...})`, flags, state);
111752
+ }
111753
+ function rewriteDelete(path, pbName, table, steps, flags, state) {
111754
+ if (consumesDataErrorEnvelope(path)) {
111755
+ flagEnvelopeManualReview(path, "from.delete", flags);
111756
+ return;
111757
+ }
111758
+ const eq = steps[1];
111759
+ if (steps.length !== 2 || !eq || eq.method !== "eq") {
111760
+ flags.push(makeFlag(path, "manual_review", "from.delete.shape", `from(${JSON.stringify(table)}).delete() chain isn't the .delete().eq("id", v) shape — manual review.`));
111761
+ return;
111762
+ }
111763
+ const eqCol = eq.args[0];
111764
+ const eqVal = eq.args[1];
111765
+ if (!eqCol || !eqVal) {
111766
+ flags.push(makeFlag(path, "manual_review", "from.delete.eq", "delete().eq(...) call missing args — manual review."));
111767
+ return;
111768
+ }
111769
+ if (!((eqCol.type === "Literal" || eqCol.type === "StringLiteral") && eqCol.value === "id")) {
111770
+ flags.push(makeFlag(path, "manual_review", "from.delete.eq_non_id", `from(${JSON.stringify(table)}).delete().eq() filters on a non-id column — PB's delete needs an id; chunk 2 will handle filter-based deletes.`));
111771
+ return;
111772
+ }
111773
+ const replacement = import_jscodeshift2.default.callExpression(import_jscodeshift2.default.memberExpression(import_jscodeshift2.default.callExpression(import_jscodeshift2.default.memberExpression(import_jscodeshift2.default.identifier(pbName), import_jscodeshift2.default.identifier("collection")), [import_jscodeshift2.default.literal(table)]), import_jscodeshift2.default.identifier("delete")), [eqVal]);
111774
+ applyRewrite(path, replacement, "rewritten", "from.delete", `from(${JSON.stringify(table)}).delete().eq("id", v) → pb.collection(...).delete(v)`, flags, state);
111775
+ }
111776
+ function flagUnsupportedPatterns(root, supabaseNames, flags) {
111777
+ root.find(import_jscodeshift2.default.CallExpression).forEach((path) => {
111778
+ flagOneUnsupported(path, supabaseNames, flags);
111779
+ });
111780
+ }
111781
+ function flagOneUnsupported(path, supabaseNames, flags) {
111782
+ const root = findChainRoot(path.node);
111783
+ if (!root)
111784
+ return;
111785
+ if (root.type !== "Identifier")
111786
+ return;
111787
+ if (!supabaseNames.has(root.name))
111788
+ return;
111789
+ const parent = path.parent?.node;
111790
+ if (parent?.type === "MemberExpression") {
111791
+ const m = parent;
111792
+ if (m.object === path.node)
111793
+ return;
111794
+ }
111795
+ const steps = readChainSteps(path.node);
111796
+ const first = steps[0];
111797
+ if (!first)
111798
+ return;
111799
+ if (first.method === "storage") {
111800
+ const opStep = findStorageOperation(steps);
111801
+ const opName = opStep?.method ?? "from";
111802
+ flags.push(makeFlag(path, "unsupported", `storage.${opName}`, `supabase.storage.<bucket>.${opName}(...) — PocketBase models files as record-attached fields, not standalone buckets. Rewrite by hand: create a collection with a \`file\` field, then use pb.collection(c).create({ file: blob }) for uploads and pb.files.getURL(record, record.file) for URLs.`));
111803
+ return;
111804
+ }
111805
+ if (first.method === "channel") {
111806
+ flags.push(makeFlag(path, "unsupported", "channel.subscribe", `supabase.channel(...).on(...).subscribe(...) — PB has realtime via pb.collection(c).subscribe("*", cb) but the event shape and filter model differ from Supabase channels. Rewrite by hand.`));
111807
+ return;
111808
+ }
111809
+ if (first.method === "rpc") {
111810
+ const fnName = first.call ? readFirstStringArg(first.call) ?? "<unknown>" : "<unknown>";
111811
+ flags.push(makeFlag(path, "unsupported", "rpc", `supabase.rpc(${JSON.stringify(fnName)}, ...) — Postgres function calls don't have a PocketBase equivalent. Move the logic into your app server code OR a PB hook (.pb_hooks/).`));
111812
+ return;
111813
+ }
111814
+ const invokeStep = steps[1];
111815
+ if (first.method === "functions" && invokeStep?.method === "invoke") {
111816
+ const fnName = invokeStep.call ? readFirstStringArg(invokeStep.call) ?? "<unknown>" : "<unknown>";
111817
+ flags.push(makeFlag(path, "unsupported", "functions.invoke", `supabase.functions.invoke(${JSON.stringify(fnName)}, ...) — Edge Functions don't run on Percher. Move the function code into the Percher app server, or host it on a separate platform (Deno Deploy, Cloudflare Workers) and call it via fetch.`));
111818
+ return;
111819
+ }
111820
+ }
111821
+ var STORAGE_OPERATIONS = new Set([
111822
+ "upload",
111823
+ "uploadToSignedUrl",
111824
+ "download",
111825
+ "list",
111826
+ "remove",
111827
+ "move",
111828
+ "copy",
111829
+ "createSignedUrl",
111830
+ "createSignedUrls",
111831
+ "createSignedUploadUrl",
111832
+ "getPublicUrl",
111833
+ "update",
111834
+ "exists",
111835
+ "info"
111836
+ ]);
111837
+ var CHAIN_CONTINUATIONS = new Set(["then", "catch", "finally"]);
111838
+ function findStorageOperation(steps) {
111839
+ for (const step of steps) {
111840
+ if (STORAGE_OPERATIONS.has(step.method))
111841
+ return step;
111842
+ }
111843
+ for (let i = steps.length - 1;i >= 0; i--) {
111844
+ const step = steps[i];
111845
+ if (!step)
111846
+ continue;
111847
+ if (step.method === "storage" || step.method === "from")
111848
+ continue;
111849
+ if (CHAIN_CONTINUATIONS.has(step.method))
111850
+ continue;
111851
+ return step;
111852
+ }
111853
+ return null;
111854
+ }
111855
+ function findChainRoot(node) {
111856
+ let cursor = node;
111857
+ while (true) {
111858
+ if (cursor.type === "CallExpression") {
111859
+ const c = cursor;
111860
+ if (c.callee.type !== "MemberExpression")
111861
+ return null;
111862
+ cursor = c.callee.object;
111863
+ continue;
111864
+ }
111865
+ if (cursor.type === "MemberExpression") {
111866
+ cursor = cursor.object;
111867
+ continue;
111868
+ }
111869
+ return cursor;
111870
+ }
111871
+ }
111872
+ function readChainSteps(outer) {
111873
+ const reversed = [];
111874
+ let cursor = outer;
111875
+ while (true) {
111876
+ if (cursor.type === "CallExpression") {
111877
+ const call = cursor;
111878
+ if (call.callee.type !== "MemberExpression")
111879
+ break;
111880
+ const callee = call.callee;
111881
+ if (callee.property.type === "Identifier") {
111882
+ reversed.push({
111883
+ method: callee.property.name,
111884
+ call
111885
+ });
111886
+ }
111887
+ cursor = callee.object;
111888
+ continue;
111889
+ }
111890
+ if (cursor.type === "MemberExpression") {
111891
+ const m = cursor;
111892
+ if (m.property.type === "Identifier") {
111893
+ reversed.push({
111894
+ method: m.property.name,
111895
+ call: null
111896
+ });
111897
+ }
111898
+ cursor = m.object;
111899
+ continue;
111900
+ }
111901
+ break;
111902
+ }
111903
+ return reversed.reverse();
111904
+ }
111905
+ function readFirstStringArg(call) {
111906
+ const a = call.arguments[0];
111907
+ if (!a)
111908
+ return null;
111909
+ if (a.type === "Literal" || a.type === "StringLiteral") {
111910
+ const v = a.value;
111911
+ if (typeof v === "string")
111912
+ return v;
111913
+ }
111914
+ return null;
111915
+ }
111916
+ var EMPTY_SCAN = {
111917
+ importsSupabase: false,
111918
+ authCalls: 0,
111919
+ fromCalls: 0,
111920
+ storage: 0,
111921
+ rpc: 0,
111922
+ realtime: 0,
111923
+ edgeFunctions: 0,
111924
+ usesPb: false,
111925
+ danglingPb: false
111926
+ };
111927
+ function scanSupabaseUsage(input) {
111928
+ const supabaseNames = new Set(input.supabaseIdentifiers ?? ["supabase"]);
111929
+ const pbName = input.pbIdentifier ?? "pb";
111930
+ const mentionsSupabase = sourceMentionsSupabase(input.source, supabaseNames);
111931
+ const mentionsPb = input.source.includes(pbName);
111932
+ if (!mentionsSupabase && !mentionsPb)
111933
+ return { ...EMPTY_SCAN };
111934
+ let root;
111935
+ try {
111936
+ root = tsx2(input.source);
111937
+ } catch (err) {
111938
+ return { ...EMPTY_SCAN, parseError: err instanceof Error ? err.message : String(err) };
111939
+ }
111940
+ const scan = { ...EMPTY_SCAN };
111941
+ scan.importsSupabase = importsSupabasePackage(root);
111942
+ root.find(import_jscodeshift2.default.CallExpression).forEach((path) => {
111943
+ const chainRoot = findChainRoot(path.node);
111944
+ if (chainRoot?.type !== "Identifier")
111945
+ return;
111946
+ if (!supabaseNames.has(chainRoot.name))
111947
+ return;
111948
+ const parent = path.parent?.node;
111949
+ if (parent?.type === "MemberExpression" && parent.object === path.node) {
111950
+ return;
111951
+ }
111952
+ const steps = readChainSteps(path.node);
111953
+ const first = steps[0];
111954
+ if (!first)
111955
+ return;
111956
+ switch (first.method) {
111957
+ case "auth":
111958
+ scan.authCalls += 1;
111959
+ break;
111960
+ case "from":
111961
+ scan.fromCalls += 1;
111962
+ break;
111963
+ case "storage":
111964
+ scan.storage += 1;
111965
+ break;
111966
+ case "rpc":
111967
+ scan.rpc += 1;
111968
+ break;
111969
+ case "channel":
111970
+ scan.realtime += 1;
111971
+ break;
111972
+ case "functions":
111973
+ if (steps[1]?.method === "invoke")
111974
+ scan.edgeFunctions += 1;
111975
+ break;
111976
+ }
111977
+ });
111978
+ const pb = analyzePbBinding(root, pbName);
111979
+ scan.usesPb = pb.usesPb;
111980
+ scan.danglingPb = pb.usesPb && !pb.declared;
111981
+ return scan;
111982
+ }
111983
+ function importsSupabasePackage(root) {
111984
+ let found = false;
111985
+ root.find(import_jscodeshift2.default.ImportDeclaration).forEach((p) => {
111986
+ const src = p.node.source.value;
111987
+ if (typeof src === "string" && src.startsWith("@supabase/"))
111988
+ found = true;
111989
+ });
111990
+ if (found)
111991
+ return true;
111992
+ root.find(import_jscodeshift2.default.CallExpression).forEach((p) => {
111993
+ const callee = p.node.callee;
111994
+ const isRequire = callee.type === "Identifier" && callee.name === "require";
111995
+ const isDynImport = callee.type === "Import";
111996
+ if (!isRequire && !isDynImport)
111997
+ return;
111998
+ const arg = p.node.arguments[0];
111999
+ if ((arg?.type === "Literal" || arg?.type === "StringLiteral") && typeof arg.value === "string" && arg.value.startsWith("@supabase/")) {
112000
+ found = true;
112001
+ }
112002
+ });
112003
+ return found;
112004
+ }
112005
+ function analyzePbBinding(root, pbName) {
112006
+ let declared = false;
112007
+ root.find(import_jscodeshift2.default.ImportDeclaration).forEach((p) => {
112008
+ for (const spec of p.node.specifiers ?? []) {
112009
+ if (spec.local?.name === pbName)
112010
+ declared = true;
112011
+ }
112012
+ });
112013
+ root.find(import_jscodeshift2.default.VariableDeclarator).forEach((p) => {
112014
+ const id = p.node.id;
112015
+ if (id.type === "Identifier" && id.name === pbName)
112016
+ declared = true;
112017
+ if (id.type === "ObjectPattern" && objectPatternBindsName(id, pbName)) {
112018
+ declared = true;
112019
+ }
112020
+ });
112021
+ const checkParams = (params) => {
112022
+ for (const param of params) {
112023
+ if (param.type === "Identifier" && param.name === pbName) {
112024
+ declared = true;
112025
+ }
112026
+ }
112027
+ };
112028
+ root.find(import_jscodeshift2.default.FunctionDeclaration).forEach((p) => {
112029
+ checkParams(p.node.params);
112030
+ });
112031
+ root.find(import_jscodeshift2.default.FunctionExpression).forEach((p) => {
112032
+ checkParams(p.node.params);
112033
+ });
112034
+ root.find(import_jscodeshift2.default.ArrowFunctionExpression).forEach((p) => {
112035
+ checkParams(p.node.params);
112036
+ });
112037
+ let usedAsObject = false;
112038
+ root.find(import_jscodeshift2.default.MemberExpression).forEach((p) => {
112039
+ const obj = p.node.object;
112040
+ if (obj.type === "Identifier" && obj.name === pbName)
112041
+ usedAsObject = true;
112042
+ });
112043
+ return { usesPb: usedAsObject, declared };
112044
+ }
112045
+ function objectPatternBindsName(pattern, name) {
112046
+ for (const prop of pattern.properties) {
112047
+ if ((prop.type === "Property" || prop.type === "ObjectProperty") && "value" in prop && prop.value.type === "Identifier" && prop.value.name === name) {
112048
+ return true;
112049
+ }
112050
+ }
112051
+ return false;
112052
+ }
112053
+ function findObjectProp(obj, name) {
112054
+ for (const prop of obj.properties) {
112055
+ if ((prop.type === "Property" || prop.type === "ObjectProperty") && "key" in prop && prop.key.type === "Identifier" && prop.key.name === name) {
112056
+ if (prop.shorthand === true) {
112057
+ return import_jscodeshift2.default.identifier(name);
112058
+ }
112059
+ if ("value" in prop) {
112060
+ const val = prop.value;
112061
+ if (val.type !== "SpreadElement" && val.type !== "RestElement") {
112062
+ return val;
112063
+ }
112064
+ }
112065
+ }
112066
+ }
112067
+ return null;
112068
+ }
112069
+ function makeFlag(pathOrLoc, kind, pattern, note) {
112070
+ let line;
112071
+ let column;
112072
+ if ("node" in pathOrLoc) {
112073
+ const loc = pathOrLoc.node.loc;
112074
+ line = loc?.start.line;
112075
+ column = loc?.start.column;
112076
+ } else {
112077
+ line = pathOrLoc.line;
112078
+ column = pathOrLoc.column;
112079
+ }
112080
+ return { kind, pattern, line, column, note };
112081
+ }
112082
+ function captureLoc(path) {
112083
+ const loc = path.node.loc;
112084
+ return { line: loc?.start.line, column: loc?.start.column };
112085
+ }
112086
+ function applyRewrite(path, replacement, kind, pattern, note, flags, state) {
112087
+ const loc = captureLoc(path);
112088
+ path.replace(replacement);
112089
+ flags.push(makeFlag(loc, kind, pattern, note));
112090
+ state.mutated = true;
112091
+ }
112092
+
112093
+ // ../core/dist/commands/migrate-supabase-walker.js
112094
+ var import_ignore3 = __toESM(require_ignore(), 1);
112095
+ import { mkdir as mkdir2, readdir, readFile as readFile3, stat, writeFile as writeFile2 } from "node:fs/promises";
112096
+ import { dirname as dirname4, isAbsolute as isAbsolute2, join as join17, relative as relative3, resolve as resolve6, sep as sep3 } from "node:path";
112097
+ var REWRITABLE_EXTENSIONS = new Set([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"]);
112098
+ var DEFAULT_EXCLUDES = [
112099
+ "node_modules",
112100
+ ".git",
112101
+ "dist",
112102
+ "build",
112103
+ ".next",
112104
+ ".svelte-kit",
112105
+ ".astro",
112106
+ ".nuxt",
112107
+ ".output",
112108
+ "coverage",
112109
+ ".bun",
112110
+ ".cache",
112111
+ ".turbo",
112112
+ "migration-preview",
112113
+ "pb_data",
112114
+ "pb_migrations"
112115
+ ];
112116
+ async function walkSupabaseProject(input) {
112117
+ const rootAbs = resolve6(input.rootDir);
112118
+ const ig = import_ignore3.default().add(DEFAULT_EXCLUDES);
112119
+ if (input.extraExcludes && input.extraExcludes.length > 0) {
112120
+ ig.add(input.extraExcludes);
112121
+ }
112122
+ const files = [];
112123
+ const skipped = [];
112124
+ const pendingConfig = [];
112125
+ for await (const absPath of walkTree(rootAbs, rootAbs, ig)) {
112126
+ const rel = relative3(rootAbs, absPath).split(sep3).join("/");
112127
+ const kind = classifyFile2(rel);
112128
+ if (kind === null)
112129
+ continue;
112130
+ let source;
112131
+ try {
112132
+ source = await readFile3(absPath, "utf8");
112133
+ } catch (err) {
112134
+ skipped.push({
112135
+ relativePath: rel,
112136
+ reason: "read_error",
112137
+ detail: err instanceof Error ? err.message : String(err)
112138
+ });
112139
+ continue;
112140
+ }
112141
+ if (looksBinary(source)) {
112142
+ skipped.push({ relativePath: rel, reason: "binary" });
112143
+ continue;
112144
+ }
112145
+ if (kind === "code") {
112146
+ const sdkResult = rewriteSupabaseSdk({
112147
+ source,
112148
+ filePath: rel,
112149
+ pbIdentifier: input.pbIdentifier,
112150
+ supabaseIdentifiers: input.supabaseIdentifiers
112151
+ });
112152
+ if (sdkResult.parseError !== undefined) {
112153
+ skipped.push({
112154
+ relativePath: rel,
112155
+ reason: "parse_error",
112156
+ detail: sdkResult.parseError
112157
+ });
112158
+ continue;
112159
+ }
112160
+ files.push({
112161
+ relativePath: rel,
112162
+ kind,
112163
+ source,
112164
+ rewritten: sdkResult.rewritten,
112165
+ changed: sdkResult.changed,
112166
+ flags: sdkResult.flags
112167
+ });
112168
+ continue;
112169
+ }
112170
+ pendingConfig.push({ relativePath: rel, kind, source });
112171
+ }
112172
+ let supabaseUsageRemaining = 0;
112173
+ for (const file2 of files) {
112174
+ if (file2.kind !== "code")
112175
+ continue;
112176
+ const scan = scanSupabaseUsage({
112177
+ source: file2.rewritten,
112178
+ supabaseIdentifiers: input.supabaseIdentifiers
112179
+ });
112180
+ supabaseUsageRemaining += scan.authCalls + scan.storage + scan.rpc + scan.realtime + scan.edgeFunctions;
112181
+ if (scan.importsSupabase)
112182
+ supabaseUsageRemaining += 1;
112183
+ }
112184
+ const migrationComplete = supabaseUsageRemaining === 0;
112185
+ for (const cfg of pendingConfig) {
112186
+ if (!migrationComplete) {
112187
+ files.push({
112188
+ relativePath: cfg.relativePath,
112189
+ kind: cfg.kind,
112190
+ source: cfg.source,
112191
+ rewritten: cfg.source,
112192
+ changed: false,
112193
+ flags: []
112194
+ });
112195
+ continue;
112196
+ }
112197
+ const configResult = cfg.kind === "package_json" ? rewritePackageJson(cfg.source) : rewriteEnvFile(cfg.source);
112198
+ files.push({
112199
+ relativePath: cfg.relativePath,
112200
+ kind: cfg.kind,
112201
+ source: cfg.source,
112202
+ rewritten: configResult.rewritten,
112203
+ changed: configResult.changed,
112204
+ flags: configResult.flags
112205
+ });
112206
+ }
112207
+ const flagsByPattern = {};
112208
+ let flagCount = 0;
112209
+ let changedFiles = 0;
112210
+ let packageJsonChanged = false;
112211
+ let envFilesChanged = 0;
112212
+ for (const file2 of files) {
112213
+ if (file2.changed) {
112214
+ changedFiles += 1;
112215
+ if (file2.kind === "package_json")
112216
+ packageJsonChanged = true;
112217
+ if (file2.kind === "env")
112218
+ envFilesChanged += 1;
112219
+ }
112220
+ for (const flag of file2.flags) {
112221
+ flagCount += 1;
112222
+ flagsByPattern[flag.pattern] = (flagsByPattern[flag.pattern] ?? 0) + 1;
112223
+ }
112224
+ }
112225
+ return {
112226
+ files,
112227
+ skipped,
112228
+ flagsByPattern,
112229
+ summary: {
112230
+ totalFiles: files.length,
112231
+ changedFiles,
112232
+ flagCount,
112233
+ packageJsonChanged,
112234
+ envFilesChanged,
112235
+ migrationComplete,
112236
+ supabaseUsageRemaining
112237
+ }
112238
+ };
112239
+ }
112240
+ async function* walkTree(dir, rootAbs, ig) {
112241
+ let entries;
112242
+ try {
112243
+ entries = await readdir(dir);
112244
+ } catch {
112245
+ return;
112246
+ }
112247
+ for (const name of entries) {
112248
+ const abs = join17(dir, name);
112249
+ const rel = relative3(rootAbs, abs).split(sep3).join("/");
112250
+ if (rel.length > 0 && ig.ignores(rel))
112251
+ continue;
112252
+ let st;
112253
+ try {
112254
+ st = await stat(abs);
112255
+ } catch {
112256
+ continue;
112257
+ }
112258
+ if (st.isDirectory()) {
112259
+ if (ig.ignores(`${rel}/`))
112260
+ continue;
112261
+ yield* walkTree(abs, rootAbs, ig);
112262
+ continue;
112263
+ }
112264
+ if (st.isFile()) {
112265
+ yield abs;
112266
+ }
112267
+ }
112268
+ }
112269
+ function classifyFile2(relPath) {
112270
+ const base = relPath.split("/").pop() ?? relPath;
112271
+ if (base === "package.json")
112272
+ return "package_json";
112273
+ if (base === ".env" || base.startsWith(".env."))
112274
+ return "env";
112275
+ const dot = base.lastIndexOf(".");
112276
+ if (dot < 0)
112277
+ return null;
112278
+ const ext = base.slice(dot);
112279
+ if (REWRITABLE_EXTENSIONS.has(ext))
112280
+ return "code";
112281
+ return null;
112282
+ }
112283
+ function looksBinary(source) {
112284
+ const limit = Math.min(source.length, 8192);
112285
+ for (let i = 0;i < limit; i++) {
112286
+ if (source.charCodeAt(i) === 0)
112287
+ return true;
112288
+ }
112289
+ return false;
112290
+ }
112291
+ function rewritePackageJson(source) {
112292
+ let pkg;
112293
+ try {
112294
+ pkg = JSON.parse(source);
112295
+ } catch {
112296
+ return { rewritten: source, changed: false, flags: [] };
112297
+ }
112298
+ const depSections = [
112299
+ "dependencies",
112300
+ "devDependencies",
112301
+ "peerDependencies",
112302
+ "optionalDependencies"
112303
+ ];
112304
+ let changed = false;
112305
+ const flags = [];
112306
+ for (const section of depSections) {
112307
+ const deps = pkg[section];
112308
+ if (!deps || typeof deps !== "object" || Array.isArray(deps))
112309
+ continue;
112310
+ const depsObj = deps;
112311
+ if ("@supabase/supabase-js" in depsObj) {
112312
+ delete depsObj["@supabase/supabase-js"];
112313
+ if (!("pocketbase" in depsObj)) {
112314
+ depsObj.pocketbase = "^0.21.0";
112315
+ }
112316
+ changed = true;
112317
+ flags.push({
112318
+ kind: "rewritten",
112319
+ pattern: `package.${section}`,
112320
+ note: `${section}: @supabase/supabase-js → pocketbase`
112321
+ });
112322
+ }
112323
+ }
112324
+ if (!changed) {
112325
+ return { rewritten: source, changed: false, flags: [] };
112326
+ }
112327
+ const rewritten = `${JSON.stringify(pkg, null, 2)}
112328
+ `;
112329
+ return { rewritten, changed: true, flags };
112330
+ }
112331
+ function rewriteEnvFile(source) {
112332
+ const lines = source.split(/\r?\n/);
112333
+ const flags = [];
112334
+ const seenPrefixes = new Set;
112335
+ const outLines = [];
112336
+ let changed = false;
112337
+ const HEADER_MARKER = "# === Percher migration: Supabase → PocketBase ===";
112338
+ if (source.includes(HEADER_MARKER)) {
112339
+ return { rewritten: source, changed: false, flags: [] };
112340
+ }
112341
+ for (const [i, line] of lines.entries()) {
112342
+ const match = line.match(/^\s*([A-Z][A-Z0-9_]*)\s*=(.*)$/);
112343
+ if (!match) {
112344
+ outLines.push(line);
112345
+ continue;
112346
+ }
112347
+ const key = match[1] ?? "";
112348
+ if (!key.includes("SUPABASE")) {
112349
+ outLines.push(line);
112350
+ continue;
112351
+ }
112352
+ const prefix = extractPublicPrefix(key);
112353
+ seenPrefixes.add(prefix);
112354
+ outLines.push(`# was: ${line.trim()}`);
112355
+ flags.push({
112356
+ kind: "rewritten",
112357
+ pattern: "env.supabase_key",
112358
+ line: i + 1,
112359
+ note: `${key} commented out — replace with the appropriate POCKETBASE_URL value.`
112360
+ });
112361
+ changed = true;
112362
+ }
112363
+ if (!changed) {
112364
+ return { rewritten: source, changed: false, flags: [] };
112365
+ }
112366
+ const stubLines = [];
112367
+ stubLines.push(HEADER_MARKER);
112368
+ stubLines.push("# Old SUPABASE_* keys are kept above as `# was:` comments.");
112369
+ stubLines.push("# Fill in the POCKETBASE_URL values below and remove the comments");
112370
+ stubLines.push("# once you've verified the migration.");
112371
+ for (const prefix of [...seenPrefixes].sort()) {
112372
+ const pbKey = prefix ? `${prefix}POCKETBASE_URL` : "POCKETBASE_URL";
112373
+ stubLines.push(`${pbKey}=`);
112374
+ }
112375
+ stubLines.push("");
112376
+ const rewritten = `${stubLines.join(`
112377
+ `)}
112378
+ ${outLines.join(`
112379
+ `)}`;
112380
+ return { rewritten, changed: true, flags };
112381
+ }
112382
+ function extractPublicPrefix(key) {
112383
+ for (const p of [
112384
+ "NEXT_PUBLIC_",
112385
+ "VITE_",
112386
+ "NUXT_PUBLIC_",
112387
+ "PUBLIC_",
112388
+ "REACT_APP_",
112389
+ "VUE_APP_",
112390
+ "EXPO_PUBLIC_"
112391
+ ]) {
112392
+ if (key.startsWith(p))
112393
+ return p;
112394
+ }
112395
+ return "";
112396
+ }
112397
+ async function writeWalkResult(input) {
112398
+ const targetAbs = resolve6(input.targetDir);
112399
+ const changedOnly = input.changedOnly !== false;
112400
+ const written = [];
112401
+ for (const file2 of input.result.files) {
112402
+ if (changedOnly && !file2.changed)
112403
+ continue;
112404
+ const abs = resolve6(targetAbs, file2.relativePath);
112405
+ const rel = relative3(targetAbs, abs);
112406
+ const isParentTraversal = rel === ".." || rel.startsWith(`..${sep3}`) || rel.startsWith("../");
112407
+ if (rel.length === 0 || isParentTraversal || isAbsolute2(rel)) {
112408
+ throw new Error(`writeWalkResult refused path-traversing file "${file2.relativePath}" → "${abs}" (would escape targetDir "${targetAbs}").`);
112409
+ }
112410
+ await mkdir2(dirname4(abs), { recursive: true });
112411
+ await writeFile2(abs, file2.rewritten, "utf8");
112412
+ written.push(file2.relativePath);
112413
+ }
112414
+ return { written };
112415
+ }
112416
+
112417
+ // ../core/dist/commands/migrate-supabase-status.js
112418
+ var migrationStatusInputSchema = exports_external.object({
112419
+ rootDir: exports_external.string().optional().describe("Project root to scan. Relative paths resolve against ctx.cwd. Defaults to ctx.cwd."),
112420
+ build: exports_external.boolean().optional().describe("Also run the project's build as a final gate. Off by default — a half-migrated project legitimately fails to build, so the noise is opt-in."),
112421
+ pbIdentifier: exports_external.string().optional().describe("PocketBase client identifier the rewrite used (defaults to `pb`). Pass the same value here that `rewrite_client` used, or the undefined-reference check can't see a custom identifier (e.g. `db`)."),
112422
+ supabaseIdentifiers: exports_external.array(exports_external.string()).optional().describe("Supabase client variable names to recognise (beyond `supabase`).")
112423
+ });
112424
+ function analyzeMigration(files, opts = {}) {
112425
+ const pbName = opts.pbIdentifier ?? "pb";
112426
+ const supabaseImportFiles = [];
112427
+ const danglingPbFiles = [];
112428
+ let authCalls = 0;
112429
+ let storage = 0;
112430
+ let rpc = 0;
112431
+ let realtime = 0;
112432
+ let edgeFunctions = 0;
112433
+ let anyPbUsage = false;
112434
+ let pocketbaseDepDeclared = false;
112435
+ let supabaseDepDeclared = false;
112436
+ let pocketbaseUrlEnv = false;
112437
+ let supabaseEnvPresent = false;
112438
+ for (const file2 of files) {
112439
+ if (file2.kind === "code") {
112440
+ const scan = scanSupabaseUsage({
112441
+ source: file2.source,
112442
+ supabaseIdentifiers: opts.supabaseIdentifiers,
112443
+ pbIdentifier: pbName
112444
+ });
112445
+ if (scan.importsSupabase)
112446
+ supabaseImportFiles.push(file2.relativePath);
112447
+ if (scan.danglingPb)
112448
+ danglingPbFiles.push(file2.relativePath);
112449
+ if (scan.usesPb)
112450
+ anyPbUsage = true;
112451
+ authCalls += scan.authCalls;
112452
+ storage += scan.storage;
112453
+ rpc += scan.rpc;
112454
+ realtime += scan.realtime;
112455
+ edgeFunctions += scan.edgeFunctions;
112456
+ continue;
112457
+ }
112458
+ if (file2.kind === "package_json") {
112459
+ const deps = readDeps(file2.source);
112460
+ if ("pocketbase" in deps)
112461
+ pocketbaseDepDeclared = true;
112462
+ if ("@supabase/supabase-js" in deps || "@supabase/ssr" in deps)
112463
+ supabaseDepDeclared = true;
112464
+ continue;
112465
+ }
112466
+ if (/^\s*[A-Z][A-Z0-9_]*POCKETBASE_URL\s*=/m.test(file2.source))
112467
+ pocketbaseUrlEnv = true;
112468
+ if (/^\s*[A-Z][A-Z0-9_]*SUPABASE[A-Z0-9_]*\s*=/m.test(file2.source))
112469
+ supabaseEnvPresent = true;
112470
+ }
112471
+ const remaining = supabaseImportFiles.length + authCalls + storage + rpc + realtime + edgeFunctions;
112472
+ const migrationComplete = remaining === 0;
112473
+ const checks3 = [];
112474
+ checks3.push({
112475
+ id: "supabaseImportsRemaining",
112476
+ label: "Supabase imports removed",
112477
+ status: supabaseImportFiles.length === 0 ? "pass" : "warn",
112478
+ count: supabaseImportFiles.length,
112479
+ detail: supabaseImportFiles.length === 0 ? "No files import @supabase/*." : `${supabaseImportFiles.length} file(s) still import @supabase/* — migrate them, or keep them if this is intentionally hybrid.`,
112480
+ ...supabaseImportFiles.length > 0 ? { files: supabaseImportFiles } : {}
112481
+ });
112482
+ checks3.push({
112483
+ id: "undefinedPbReferences",
112484
+ label: "PocketBase client wired",
112485
+ status: danglingPbFiles.length === 0 ? "pass" : "fail",
112486
+ count: danglingPbFiles.length,
112487
+ detail: danglingPbFiles.length === 0 ? `Every \`${pbName}\` reference resolves to an imported client.` : `${danglingPbFiles.length} file(s) use \`${pbName}\` with no import in scope — the app won't run. Scaffold + import a client: percher migrate-from-supabase --rewrite-client --scaffold-client.`,
112488
+ ...danglingPbFiles.length > 0 ? { files: danglingPbFiles } : {}
112489
+ });
112490
+ checks3.push(usageCheck("authCallsRemaining", "Auth calls migrated", authCalls, "supabase.auth.* call(s) still to map — see the auth recipes in REWRITE_NOTES.md."));
112491
+ checks3.push(usageCheck("storageUsage", "Storage migrated", storage, "supabase.storage.* call(s) remain — PocketBase models files as record fields; rewrite by hand."));
112492
+ checks3.push(usageCheck("rpcUsage", "RPC migrated", rpc, "supabase.rpc(...) call(s) remain — move the logic into app code or a PB hook."));
112493
+ checks3.push(usageCheck("realtimeUsage", "Realtime migrated", realtime, "supabase.channel(...) call(s) remain — PB realtime uses pb.collection(c).subscribe(); the event shape differs."));
112494
+ checks3.push(usageCheck("edgeFunctionUsage", "Edge functions migrated", edgeFunctions, "supabase.functions.invoke(...) call(s) remain — host the function elsewhere and fetch it."));
112495
+ checks3.push({
112496
+ id: "pocketbaseDepDeclared",
112497
+ label: "pocketbase dependency declared",
112498
+ status: pocketbaseDepDeclared ? "pass" : anyPbUsage ? "warn" : "n/a",
112499
+ count: 0,
112500
+ detail: pocketbaseDepDeclared ? "package.json depends on pocketbase." : anyPbUsage ? "Your code uses `pb` but package.json has no `pocketbase` dependency — add it." : "No PocketBase client in use yet."
112501
+ });
112502
+ checks3.push(cleanupCheck({ migrationComplete, supabaseDepDeclared, remaining, anyPbUsage }));
112503
+ checks3.push({
112504
+ id: "envWired",
112505
+ label: "POCKETBASE_URL in env",
112506
+ status: pocketbaseUrlEnv ? "pass" : anyPbUsage ? "warn" : "n/a",
112507
+ count: 0,
112508
+ detail: pocketbaseUrlEnv ? "POCKETBASE_URL is set for local dev." : anyPbUsage ? "No POCKETBASE_URL in your env files. Percher injects it automatically in production; add it to .env for local dev." : "No PocketBase env needed yet."
112509
+ });
112510
+ const rls = opts.rlsManualCount ?? null;
112511
+ checks3.push({
112512
+ id: "rlsRulesToWrite",
112513
+ label: "RLS → PB API rules",
112514
+ status: rls === null ? "n/a" : rls === 0 ? "pass" : "warn",
112515
+ count: rls ?? 0,
112516
+ detail: rls === null ? "No migration-preview/MIGRATION_NOTES.md — run migrate-from-supabase to generate the schema + RLS report." : rls === 0 ? "No RLS policies need manual translation." : `${rls} RLS policy/policies still need PB API rules — see migration-preview/MIGRATION_NOTES.md.`
112517
+ });
112518
+ let supabaseEnvNote = "";
112519
+ if (!migrationComplete && !supabaseEnvPresent && supabaseDepDeclared) {
112520
+ supabaseEnvNote = " Note: Supabase calls remain but no SUPABASE_* env was found — make sure those keys are still set.";
112521
+ }
112522
+ if (supabaseEnvNote) {
112523
+ const envCheck = checks3.find((c) => c.id === "envWired");
112524
+ if (envCheck)
112525
+ envCheck.detail += supabaseEnvNote;
112526
+ }
112527
+ const state = deriveState(checks3, migrationComplete, anyPbUsage, remaining);
112528
+ return { checks: checks3, migrationComplete, state };
112529
+ }
112530
+ function usageCheck(id, label, count, remainingDetail) {
112531
+ return {
112532
+ id,
112533
+ label,
112534
+ status: count === 0 ? "pass" : "warn",
112535
+ count,
112536
+ detail: count === 0 ? "None remaining." : `${count} ${remainingDetail}`
112537
+ };
112538
+ }
112539
+ function cleanupCheck(args) {
112540
+ const base = { id: "supabaseCleanup", label: "Supabase removed", count: args.remaining };
112541
+ if (args.migrationComplete) {
112542
+ if (args.supabaseDepDeclared) {
112543
+ return {
112544
+ ...base,
112545
+ status: "warn",
112546
+ detail: "Migration looks complete — you can now drop @supabase/supabase-js and the Supabase env keys."
112547
+ };
112548
+ }
112549
+ return { ...base, status: "pass", detail: "Supabase fully removed." };
112550
+ }
112551
+ if (!args.supabaseDepDeclared && args.remaining > 0) {
112552
+ return {
112553
+ ...base,
112554
+ status: "fail",
112555
+ detail: `@supabase/supabase-js was dropped but ${args.remaining} Supabase reference(s) still need it — restore the dependency or finish migrating them.`
112556
+ };
112557
+ }
112558
+ return {
112559
+ ...base,
112560
+ status: "warn",
112561
+ detail: `Hybrid: ${args.remaining} Supabase reference(s) remain (storage/rpc/realtime/edge/un-mapped auth or @supabase imports). Keep @supabase/supabase-js + Supabase env until they're migrated.`
112562
+ };
112563
+ }
112564
+ function deriveState(checks3, migrationComplete, anyPbUsage, remaining) {
112565
+ if (checks3.some((c) => c.status === "fail"))
112566
+ return "broken";
112567
+ if (migrationComplete)
112568
+ return "complete";
112569
+ if (anyPbUsage)
112570
+ return "hybrid";
112571
+ return remaining > 0 ? "not_started" : "complete";
112572
+ }
112573
+ function readDeps(source) {
112574
+ let pkg;
112575
+ try {
112576
+ pkg = JSON.parse(source);
112577
+ } catch {
112578
+ return {};
112579
+ }
112580
+ const out = {};
112581
+ for (const section of [
112582
+ "dependencies",
112583
+ "devDependencies",
112584
+ "peerDependencies",
112585
+ "optionalDependencies"
112586
+ ]) {
112587
+ const deps = pkg[section];
112588
+ if (deps && typeof deps === "object" && !Array.isArray(deps)) {
112589
+ Object.assign(out, deps);
112590
+ }
112591
+ }
112592
+ return out;
112593
+ }
112594
+ var STATUS_GLYPH = {
112595
+ pass: "✓",
112596
+ fail: "✗",
112597
+ warn: "⚠",
112598
+ "n/a": "•"
112599
+ };
112600
+ function renderMigrationChecklist(checks3) {
112601
+ const lines = [];
112602
+ for (const check2 of checks3) {
112603
+ const glyph = STATUS_GLYPH[check2.status];
112604
+ const countSuffix = check2.count > 0 ? ` (${check2.count})` : "";
112605
+ lines.push(`${glyph} ${check2.label}${countSuffix} — ${check2.detail}`);
112606
+ if (check2.files && check2.files.length > 0) {
112607
+ for (const f of check2.files.slice(0, 10))
112608
+ lines.push(` - ${f}`);
112609
+ if (check2.files.length > 10)
112610
+ lines.push(` …and ${check2.files.length - 10} more`);
112611
+ }
112612
+ }
112613
+ return lines.join(`
112614
+ `);
112615
+ }
112616
+ var STATE_SUMMARY = {
112617
+ broken: "Migration is in a broken state — fix the ✗ items before deploying.",
112618
+ hybrid: "Hybrid migration — some calls are on PocketBase, some still on Supabase (both SDKs needed).",
112619
+ not_started: "Supabase is still in use — nothing migrated to PocketBase yet.",
112620
+ complete: "Migration looks complete — no Supabase usage remains."
112621
+ };
112622
+ async function migrationStatus(ctx, input) {
112623
+ const rootAbs = input.rootDir ? resolve7(ctx.cwd, input.rootDir) : resolve7(ctx.cwd);
112624
+ ctx.status(`Scanning ${relative4(ctx.cwd, rootAbs) || "."} for migration status...`);
112625
+ let files;
112626
+ try {
112627
+ const walk2 = await walkSupabaseProject({ rootDir: rootAbs });
112628
+ files = walk2.files.map((f) => ({
112629
+ relativePath: f.relativePath,
112630
+ kind: f.kind,
112631
+ source: f.source
112632
+ }));
112633
+ } catch (err) {
112634
+ return failure2(rootAbs, err);
112635
+ }
112636
+ const rlsManualCount = await readManualRlsCount(rootAbs);
112637
+ const analysis = analyzeMigration(files, {
112638
+ rlsManualCount,
112639
+ pbIdentifier: input.pbIdentifier,
112640
+ supabaseIdentifiers: input.supabaseIdentifiers
112641
+ });
112642
+ let build;
112643
+ if (input.build === true) {
112644
+ build = await runProjectBuild(rootAbs);
112645
+ }
112646
+ const checklist = renderMigrationChecklist(analysis.checks);
112647
+ const failing = analysis.checks.filter((c) => c.status === "fail");
112648
+ const warning = analysis.checks.filter((c) => c.status === "warn");
112649
+ const buildFailed = build?.ran === true && !build.passed;
112650
+ const allGreen = failing.length === 0 && warning.length === 0 && !buildFailed;
112651
+ const recovery = allGreen ? recoveryNone() : recoveryAsk({
112652
+ prompt: buildPrompt(analysis.state, failing, warning, build),
112653
+ reasonCode: "unknown"
112654
+ });
112655
+ const summary = `${STATE_SUMMARY[analysis.state]}${build ? ` Build: ${build.ran ? build.passed ? "passed" : "FAILED" : "skipped"}.` : ""}`;
112656
+ return {
112657
+ status: "ok",
112658
+ rootDir: rootAbs,
112659
+ state: analysis.state,
112660
+ migrationComplete: analysis.migrationComplete,
112661
+ checks: analysis.checks,
112662
+ ...build ? { build } : {},
112663
+ recovery,
112664
+ summary,
112665
+ checklist
112666
+ };
112667
+ }
112668
+ function buildPrompt(state, failing, warning, build) {
112669
+ const bits = [];
112670
+ if (failing.length > 0) {
112671
+ bits.push(`fix first: ${failing.map((c) => `${c.label} — ${c.detail}`).join("; ")}`);
112672
+ }
112673
+ if (warning.length > 0) {
112674
+ bits.push(`still to do: ${warning.map((c) => `${c.label} (${c.count || "n/a"})`).join(", ")}`);
112675
+ }
112676
+ if (build?.ran && !build.passed) {
112677
+ bits.push(`the build failed: ${build.detail}`);
112678
+ }
112679
+ const lead = state === "broken" ? "The migration is in a broken state." : "The migration isn't finished.";
112680
+ return `${lead} ${bits.join(". ")}. Work through migration-preview/REWRITE_NOTES.md, then re-run --status.`;
112681
+ }
112682
+ async function readManualRlsCount(rootAbs) {
112683
+ for (const dir of ["migration-preview", "."]) {
112684
+ try {
112685
+ const notes = await readFile4(join18(rootAbs, dir, "MIGRATION_NOTES.md"), "utf8");
112686
+ const m = notes.match(/\*\*RLS policies:\*\*\s*\d+\s*\((\d+)\s*need manual review\)/);
112687
+ if (m?.[1] !== undefined)
112688
+ return Number.parseInt(m[1], 10);
112689
+ return 0;
112690
+ } catch {}
112691
+ }
112692
+ return null;
112693
+ }
112694
+ async function runProjectBuild(rootAbs) {
112695
+ let hasBuildScript = false;
112696
+ try {
112697
+ const pkg = JSON.parse(await readFile4(join18(rootAbs, "package.json"), "utf8"));
112698
+ hasBuildScript = typeof pkg.scripts?.build === "string";
112699
+ } catch {
112700
+ return { ran: false, passed: false, detail: "No readable package.json — nothing to build." };
112701
+ }
112702
+ if (!hasBuildScript) {
112703
+ return { ran: false, passed: false, detail: "No `build` script in package.json." };
112704
+ }
112705
+ const pm = await detectPackageManager(rootAbs);
112706
+ const result = await spawnCapture(pm, ["run", "build"], rootAbs, 300000);
112707
+ if (result.timedOut) {
112708
+ return { ran: true, passed: false, detail: `\`${pm} run build\` timed out after 5 min.` };
112709
+ }
112710
+ if (result.spawnError) {
112711
+ return {
112712
+ ran: false,
112713
+ passed: false,
112714
+ detail: `Couldn't run \`${pm} run build\` (${result.spawnError}). Is ${pm} installed?`
112715
+ };
112716
+ }
112717
+ const passed = result.code === 0;
112718
+ const tail = lastLines(result.output, 12);
112719
+ return {
112720
+ ran: true,
112721
+ passed,
112722
+ detail: passed ? `\`${pm} run build\` succeeded.` : `\`${pm} run build\` exited ${result.code}.${tail ? `
112723
+ ${tail}` : ""}`
112724
+ };
112725
+ }
112726
+ async function detectPackageManager(rootAbs) {
112727
+ const has = async (name) => {
112728
+ try {
112729
+ await readFile4(join18(rootAbs, name), "utf8");
112730
+ return true;
112731
+ } catch {
112732
+ return false;
112733
+ }
112734
+ };
112735
+ if (await has("bun.lock") || await has("bun.lockb"))
112736
+ return "bun";
112737
+ if (await has("pnpm-lock.yaml"))
112738
+ return "pnpm";
112739
+ if (await has("yarn.lock"))
112740
+ return "yarn";
112741
+ return "npm";
112742
+ }
112743
+ function spawnCapture(cmd, args, cwd, timeoutMs) {
112744
+ return new Promise((resolve8) => {
112745
+ const child = import_cross_spawn.default(cmd, args, { cwd, stdio: ["ignore", "pipe", "pipe"] });
112746
+ let output = "";
112747
+ const onData = (chunk) => {
112748
+ output += chunk.toString();
112749
+ if (output.length > 64000)
112750
+ output = output.slice(-64000);
112751
+ };
112752
+ child.stdout?.on("data", onData);
112753
+ child.stderr?.on("data", onData);
112754
+ let timedOut = false;
112755
+ const timer = setTimeout(() => {
112756
+ timedOut = true;
112757
+ child.kill("SIGTERM");
112758
+ }, timeoutMs);
112759
+ child.on("error", (err) => {
112760
+ clearTimeout(timer);
112761
+ resolve8({ code: 1, output, timedOut, spawnError: err.message });
112762
+ });
112763
+ child.on("close", (code) => {
112764
+ clearTimeout(timer);
112765
+ resolve8({ code: code ?? 1, output, timedOut });
112766
+ });
112767
+ });
112768
+ }
112769
+ function lastLines(text, n) {
112770
+ const lines = text.split(/\r?\n/).filter((l) => l.trim().length > 0);
112771
+ return lines.slice(-n).join(`
112772
+ `);
112773
+ }
112774
+ function failure2(rootAbs, err) {
112775
+ const message = err instanceof Error ? err.message : String(err);
112776
+ return {
112777
+ status: "failed",
112778
+ rootDir: rootAbs,
112779
+ state: "broken",
112780
+ migrationComplete: false,
112781
+ checks: [],
112782
+ recovery: recoveryAsk({
112783
+ prompt: `Couldn't scan the project for migration status (${message}). Check the path exists and is readable, then re-run.`,
112784
+ reasonCode: "unknown",
112785
+ retryable: true
112786
+ }),
112787
+ summary: `Migration status scan failed: ${message}`,
112788
+ checklist: "",
112789
+ error: {
112790
+ code: "status_failed",
112791
+ title: "Migration status scan failed",
112792
+ explanation: message,
112793
+ suggestion: "Check the project path exists and is readable, then re-run."
112794
+ }
112795
+ };
112796
+ }
112797
+
112798
+ // ../core/dist/commands/migrate-supabase-rewrite.js
112799
+ var rewriteSupabaseClientInputSchema = exports_external.object({
112800
+ rootDir: exports_external.string().optional().describe("Project root to rewrite. Relative paths resolve against ctx.cwd. Defaults to ctx.cwd."),
112801
+ outputDir: exports_external.string().optional().describe("Where preview-mode writes the rewritten tree. Ignored when `apply` is true. Defaults to `<root>/migration-preview/rewritten`."),
112802
+ apply: exports_external.boolean().optional().describe("When true, overwrite changed files in place (originals backed up to `migration-preview/backup/` first). Default false = preview only."),
112803
+ pbIdentifier: exports_external.string().optional().describe("PocketBase client variable name to emit. Defaults to `pb`."),
112804
+ supabaseIdentifiers: exports_external.array(exports_external.string()).optional().describe("Extra Supabase client variable names to recognise (beyond `supabase`)."),
112805
+ scaffoldClient: exports_external.boolean().optional().describe("Generate a PocketBase client module (src/lib/pocketbase.<ext>) and insert `import { pb }` into rewritten files. Default true when there are rewrites; pass false to opt out. Skips silently if a pb client already exists.")
112806
+ });
112807
+ async function rewriteSupabaseClient(ctx, input) {
112808
+ const rootAbs = input.rootDir ? resolve8(ctx.cwd, input.rootDir) : resolve8(ctx.cwd);
112809
+ const apply = input.apply === true;
112810
+ const mode = apply ? "apply" : "preview";
112811
+ ctx.status(`Scanning ${relative5(ctx.cwd, rootAbs) || "."} for Supabase SDK calls...`);
112812
+ let walk2;
112813
+ try {
112814
+ walk2 = await walkSupabaseProject({
112815
+ rootDir: rootAbs,
112816
+ pbIdentifier: input.pbIdentifier,
112817
+ supabaseIdentifiers: input.supabaseIdentifiers
112818
+ });
112819
+ } catch (err) {
112820
+ return failure3(rootAbs, mode, err, `Couldn't scan ${relative5(ctx.cwd, rootAbs) || "."}: check the path exists and is readable, then re-run.`);
112821
+ }
112822
+ const changed = walk2.files.filter((f) => f.changed);
112823
+ const flags = collectManualFlags(walk2);
112824
+ if (changed.length === 0 && flags.length === 0 && walk2.skipped.length === 0) {
112825
+ return {
112826
+ status: "ok",
112827
+ mode,
112828
+ rootDir: rootAbs,
112829
+ writtenTo: rootAbs,
112830
+ backupDir: null,
112831
+ filesWritten: [],
112832
+ changedCount: 0,
112833
+ flags: [],
112834
+ flagsByPattern: {},
112835
+ packageJsonChanged: false,
112836
+ envFilesChanged: 0,
112837
+ clientModule: null,
112838
+ skipped: [],
112839
+ recovery: recoveryNone(),
112840
+ summary: "No Supabase SDK calls found to rewrite. If you intend to keep Supabase as your backend, " + 'set `[data] mode = "supabase"` in percher.toml instead.'
112841
+ };
112842
+ }
112843
+ const hadRewrites = changed.length > 0;
112844
+ const scaffoldEnabled = input.scaffoldClient !== false && hadRewrites;
112845
+ const scaffold = scaffoldEnabled ? scaffoldPocketBaseClient({
112846
+ files: walk2.files,
112847
+ changedRelPaths: changed.map((f) => f.relativePath),
112848
+ pbIdentifier: input.pbIdentifier
112849
+ }) : null;
112850
+ if (scaffold) {
112851
+ for (const [rel, content] of scaffold.importInsertions) {
112852
+ const file2 = walk2.files.find((f) => f.relativePath === rel);
112853
+ if (file2)
112854
+ file2.rewritten = content;
112855
+ }
112856
+ flags.push(...scaffold.flags);
112857
+ }
112858
+ const reportNeeded = hadRewrites || flags.length > 0 || walk2.skipped.length > 0;
112859
+ const backupDir = apply && changed.length > 0 ? join19(rootAbs, "migration-preview", "backup") : null;
112860
+ const rewriteTarget = apply ? rootAbs : input.outputDir ? resolve8(ctx.cwd, input.outputDir) : join19(rootAbs, "migration-preview", "rewritten");
112861
+ const filesWritten = [];
112862
+ let clientModuleWritten = null;
112863
+ try {
112864
+ if (changed.length > 0) {
112865
+ if (apply && backupDir) {
112866
+ ctx.status(`Backing up ${changed.length} original file(s) to migration-preview/backup/...`);
112867
+ await writeWalkResult({
112868
+ result: { ...walk2, files: changed.map((f) => ({ ...f, rewritten: f.source })) },
112869
+ targetDir: backupDir,
112870
+ changedOnly: false
112871
+ });
112872
+ }
112873
+ ctx.status(apply ? `Rewriting ${changed.length} file(s) in place...` : `Writing ${changed.length} rewritten file(s) to migration-preview/rewritten/...`);
112874
+ const out = await writeWalkResult({
112875
+ result: walk2,
112876
+ targetDir: rewriteTarget,
112877
+ changedOnly: true
112878
+ });
112879
+ for (const rel of out.written) {
112880
+ filesWritten.push(relative5(ctx.cwd, join19(rewriteTarget, rel)));
112881
+ }
112882
+ if (scaffold?.clientModule) {
112883
+ const moduleAbs = join19(rewriteTarget, scaffold.clientModule.relativePath);
112884
+ await mkdir3(dirname5(moduleAbs), { recursive: true });
112885
+ await writeFile3(moduleAbs, scaffold.clientModule.content, "utf8");
112886
+ clientModuleWritten = relative5(ctx.cwd, moduleAbs).split(sep4).join("/");
112887
+ filesWritten.push(clientModuleWritten);
112888
+ }
112889
+ }
112890
+ if (reportNeeded) {
112891
+ const reportAbs = join19(rootAbs, "migration-preview", "REWRITE_NOTES.md");
112892
+ await mkdir3(dirname5(reportAbs), { recursive: true });
112893
+ const analysis = analyzeMigration(walk2.files.map((f) => ({
112894
+ relativePath: f.relativePath,
112895
+ kind: f.kind,
112896
+ source: f.rewritten
112897
+ })), { supabaseIdentifiers: input.supabaseIdentifiers, pbIdentifier: input.pbIdentifier });
112898
+ await writeFile3(reportAbs, renderReport({
112899
+ flags,
112900
+ skipped: walk2.skipped,
112901
+ hadRewrites,
112902
+ migrationComplete: walk2.summary.migrationComplete,
112903
+ supabaseUsageRemaining: walk2.summary.supabaseUsageRemaining,
112904
+ checklist: renderMigrationChecklist(analysis.checks),
112905
+ scaffoldedClient: scaffold?.clientModule?.relativePath ?? null,
112906
+ scaffoldSkippedExisting: scaffold?.skippedReason === "pb_client_exists"
112907
+ }), "utf8");
112908
+ filesWritten.push(relative5(ctx.cwd, reportAbs));
112909
+ }
112910
+ } catch (err) {
112911
+ return failure3(rootAbs, mode, err, apply ? "The in-place rewrite failed partway. Your originals are safe — restore from `migration-preview/backup/` and re-run." : "Couldn't write the rewritten preview. Check the output directory is writeable and re-run.");
112912
+ }
112913
+ const flagsByPattern = {};
112914
+ for (const flag of flags) {
112915
+ flagsByPattern[flag.pattern] = (flagsByPattern[flag.pattern] ?? 0) + 1;
112916
+ }
112917
+ const recovery = reportNeeded ? recoveryAsk({
112918
+ prompt: buildPrompt2(flags, walk2.skipped.length, hadRewrites, clientModuleWritten),
112919
+ reasonCode: "unknown"
112920
+ }) : recoveryNone();
112921
+ return {
112922
+ status: "ok",
112923
+ mode,
112924
+ rootDir: rootAbs,
112925
+ writtenTo: changed.length > 0 ? rewriteTarget : rootAbs,
112926
+ backupDir,
112927
+ filesWritten,
112928
+ changedCount: changed.length,
112929
+ flags,
112930
+ flagsByPattern,
112931
+ packageJsonChanged: walk2.summary.packageJsonChanged,
112932
+ envFilesChanged: walk2.summary.envFilesChanged,
112933
+ clientModule: clientModuleWritten,
112934
+ skipped: walk2.skipped,
112935
+ recovery,
112936
+ summary: renderSummary2({
112937
+ mode,
112938
+ changed: changed.length,
112939
+ walk: walk2,
112940
+ flagCount: flags.length,
112941
+ clientModule: clientModuleWritten
112942
+ })
112943
+ };
112944
+ }
112945
+ function isHybrid(walk2) {
112946
+ return !walk2.summary.migrationComplete && walk2.summary.supabaseUsageRemaining > 0;
112947
+ }
112948
+ function collectManualFlags(walk2) {
112949
+ const out = [];
112950
+ for (const file2 of walk2.files) {
112951
+ for (const flag of file2.flags) {
112952
+ if (flag.kind === "manual_review" || flag.kind === "unsupported") {
112953
+ out.push({
112954
+ file: file2.relativePath,
112955
+ line: flag.line,
112956
+ column: flag.column,
112957
+ kind: flag.kind,
112958
+ pattern: flag.pattern,
112959
+ note: flag.note
112960
+ });
112961
+ }
112962
+ }
112963
+ }
112964
+ return out;
112965
+ }
112966
+ function buildPrompt2(flags, skippedCount, hadRewrites, clientModule) {
112967
+ const rewritten = flags.filter((f) => f.kind === "manual_review").length;
112968
+ const untouched = flags.filter((f) => f.kind === "unsupported").length;
112969
+ const bits = [];
112970
+ if (clientModule) {
112971
+ bits.push(`review the scaffolded PocketBase client at \`${clientModule}\``);
112972
+ } else if (hadRewrites) {
112973
+ bits.push("create the `pb` PocketBase client the rewritten code now uses (it isn't created for you)");
112974
+ }
112975
+ if (rewritten > 0) {
112976
+ bits.push(`${rewritten} rewritten to PocketBase but with semantics that differ from Supabase`);
112977
+ }
112978
+ if (untouched > 0) {
112979
+ bits.push(`${untouched} left untouched (no PocketBase equivalent — storage, realtime, rpc, or edge functions)`);
112980
+ }
112981
+ if (skippedCount > 0) {
112982
+ bits.push(`${skippedCount} file${skippedCount === 1 ? "" : "s"} couldn't be parsed`);
112983
+ }
112984
+ return `Before deploying, work through migration-preview/REWRITE_NOTES.md: ${bits.join("; ")}.`;
112985
+ }
112986
+ function renderSummary2(args) {
112987
+ const parts = [];
112988
+ if (args.changed > 0) {
112989
+ const where = args.mode === "apply" ? "rewritten in place (originals in `migration-preview/backup/`)" : "written to `migration-preview/rewritten/` for review";
112990
+ parts.push(`${args.changed} file${args.changed === 1 ? "" : "s"} ${where}.`);
112991
+ } else {
112992
+ parts.push("No files needed automatic rewriting.");
112993
+ }
112994
+ if (args.clientModule) {
112995
+ parts.push(`Scaffolded a PocketBase client at \`${args.clientModule}\` and imported it.`);
112996
+ }
112997
+ if (args.walk.summary.packageJsonChanged) {
112998
+ parts.push("`package.json` swapped `@supabase/supabase-js` → `pocketbase`.");
112999
+ }
113000
+ if (args.walk.summary.envFilesChanged > 0) {
113001
+ parts.push(`${args.walk.summary.envFilesChanged} .env file${args.walk.summary.envFilesChanged === 1 ? "" : "s"} stubbed with PocketBase keys.`);
113002
+ }
113003
+ if (isHybrid(args.walk)) {
113004
+ parts.push(`Hybrid migration — ${args.walk.summary.supabaseUsageRemaining} Supabase reference${args.walk.summary.supabaseUsageRemaining === 1 ? "" : "s"} still need${args.walk.summary.supabaseUsageRemaining === 1 ? "s" : ""} \`@supabase/supabase-js\`, so the dependency + Supabase env were kept. Drop them once the rest is migrated.`);
113005
+ }
113006
+ if (args.flagCount > 0) {
113007
+ parts.push(`${args.flagCount} pattern${args.flagCount === 1 ? "" : "s"} need manual review — see \`migration-preview/REWRITE_NOTES.md\`.`);
113008
+ }
113009
+ if (args.walk.skipped.length > 0) {
113010
+ parts.push(`${args.walk.skipped.length} file${args.walk.skipped.length === 1 ? "" : "s"} couldn't be parsed (listed in \`REWRITE_NOTES.md\`).`);
113011
+ }
113012
+ return parts.join(" ");
113013
+ }
113014
+ function renderReport(args) {
113015
+ const lines = [];
113016
+ lines.push("# Supabase → PocketBase — review notes");
113017
+ lines.push("");
113018
+ lines.push("The automated rewrite converted the high-confidence auth and CRUD call sites. It does NOT create your PocketBase client, and the items below still need a human. There are no inline markers — work from this list.");
113019
+ lines.push("");
113020
+ if (args.checklist) {
113021
+ lines.push("## Status checklist");
113022
+ lines.push("");
113023
+ lines.push("Same scoreboard as `percher migrate-from-supabase --status`:");
113024
+ lines.push("");
113025
+ lines.push("```");
113026
+ lines.push(args.checklist);
113027
+ lines.push("```");
113028
+ lines.push("");
113029
+ }
113030
+ if (!args.migrationComplete && args.supabaseUsageRemaining > 0) {
113031
+ lines.push("## Hybrid state — Supabase kept on purpose");
113032
+ lines.push("");
113033
+ lines.push(`${args.supabaseUsageRemaining} Supabase reference${args.supabaseUsageRemaining === 1 ? "" : "s"} (storage / realtime / rpc / edge functions / un-mapped auth, or files still importing \`@supabase/*\`) ${args.supabaseUsageRemaining === 1 ? "was" : "were"} left in place because ${args.supabaseUsageRemaining === 1 ? "it has" : "they have"} no clean PocketBase equivalent. While they remain, your app needs **both** SDKs:`);
113034
+ lines.push("");
113035
+ lines.push("- `package.json` still depends on `@supabase/supabase-js` (and `pocketbase` once you add it) — **this is correct**, don't remove the Supabase dep yet.");
113036
+ lines.push("- your Supabase env vars (`SUPABASE_*` / `VITE_SUPABASE_*` / …) were **kept** — they're still needed by the calls below.");
113037
+ lines.push("");
113038
+ lines.push("Once you've migrated every item in this report, drop `@supabase/supabase-js` and the Supabase env keys. Run `percher migrate-from-supabase --status` to check what's left.");
113039
+ lines.push("");
113040
+ }
113041
+ if (args.scaffoldedClient) {
113042
+ lines.push("## PocketBase client (scaffolded for you)");
113043
+ lines.push("");
113044
+ lines.push(`A PocketBase client was generated at \`${args.scaffoldedClient}\` and \`import { pb } from "…"\` was inserted into the rewritten files. Review the URL accessor — it's a working default, adjust it to match your framework if needed.`);
113045
+ lines.push("");
113046
+ } else if (args.hadRewrites) {
113047
+ lines.push("## Wire the PocketBase client (required first)");
113048
+ lines.push("");
113049
+ lines.push(args.scaffoldSkippedExisting ? "The rewritten call sites use a `pb` client. Your project already exports one, so no module was generated — make sure each rewritten file imports `pb` from it." : "The rewritten call sites now use a `pb` client this tool did not create — until you add it, they reference an undefined `pb` and the app won't run.");
113050
+ lines.push("");
113051
+ lines.push("1. Replace your Supabase client setup with a PocketBase one, exported under the same name the rewrites use (`pb`):");
113052
+ lines.push("");
113053
+ lines.push("```js");
113054
+ lines.push('import PocketBase from "pocketbase";');
113055
+ lines.push("// Percher injects POCKETBASE_URL / VITE_POCKETBASE_URL at deploy time.");
113056
+ lines.push("export const pb = new PocketBase(import.meta.env.VITE_POCKETBASE_URL ?? process.env.POCKETBASE_URL);");
113057
+ lines.push("```");
113058
+ lines.push("");
113059
+ lines.push("2. Import `pb` in the rewritten files from wherever you export it.");
113060
+ lines.push("3. Remove the leftover `@supabase/*` imports (the `createClient(...)` setup, `@supabase/ssr` helpers, etc.) once nothing else needs them.");
113061
+ lines.push("");
113062
+ }
113063
+ const rewritten = args.flags.filter((f) => f.kind === "manual_review");
113064
+ const untouched = args.flags.filter((f) => f.kind === "unsupported");
113065
+ if (rewritten.length > 0) {
113066
+ lines.push("## Rewritten — verify the semantics");
113067
+ lines.push("");
113068
+ lines.push("These calls were converted to PocketBase, but the behaviour isn't identical (event shapes, filter escaping, pagination). Confirm each still does what you intend.");
113069
+ lines.push("");
113070
+ appendFlagsByFile(lines, rewritten);
113071
+ }
113072
+ if (untouched.length > 0) {
113073
+ lines.push("## Left untouched — rewrite by hand");
113074
+ lines.push("");
113075
+ lines.push("These have no clean PocketBase equivalent, so they remain as Supabase calls in your source. Replace each one yourself.");
113076
+ lines.push("");
113077
+ appendFlagsByFile(lines, untouched);
113078
+ }
113079
+ const recipeLines = renderRecipesSection(args.flags.map((f) => f.pattern));
113080
+ for (const line of recipeLines)
113081
+ lines.push(line);
113082
+ if (args.skipped.length > 0) {
113083
+ lines.push("## Files that couldn't be parsed");
113084
+ lines.push("");
113085
+ lines.push("These were skipped — review them manually for Supabase calls the rewriter missed.");
113086
+ lines.push("");
113087
+ for (const file2 of args.skipped) {
113088
+ lines.push(`- \`${file2.relativePath}\` — ${file2.reason}${file2.detail ? `: ${file2.detail}` : ""}`);
113089
+ }
113090
+ lines.push("");
113091
+ }
113092
+ return lines.join(`
113093
+ `);
113094
+ }
113095
+ function appendFlagsByFile(lines, flags) {
113096
+ const byFile = new Map;
113097
+ for (const flag of flags) {
113098
+ const list = byFile.get(flag.file) ?? [];
113099
+ list.push(flag);
113100
+ byFile.set(flag.file, list);
113101
+ }
113102
+ for (const [file2, fileFlags] of byFile) {
113103
+ lines.push(`### \`${file2}\``);
113104
+ lines.push("");
113105
+ for (const flag of fileFlags) {
113106
+ const loc = flag.line !== undefined ? `L${flag.line}${flag.column !== undefined ? `:${flag.column}` : ""}` : "(location unknown)";
113107
+ lines.push(`- ${loc} \`${flag.pattern}\` — ${flag.note}`);
113108
+ }
113109
+ lines.push("");
113110
+ }
113111
+ }
113112
+ function failure3(rootAbs, mode, err, suggestion) {
113113
+ const message = err instanceof Error ? err.message : String(err);
113114
+ return {
113115
+ status: "failed",
113116
+ mode,
113117
+ rootDir: rootAbs,
113118
+ writtenTo: rootAbs,
113119
+ backupDir: null,
113120
+ filesWritten: [],
113121
+ changedCount: 0,
113122
+ flags: [],
113123
+ flagsByPattern: {},
113124
+ packageJsonChanged: false,
113125
+ envFilesChanged: 0,
113126
+ clientModule: null,
113127
+ skipped: [],
113128
+ recovery: recoveryAsk({
113129
+ prompt: `${suggestion} (${message})`,
113130
+ reasonCode: "unknown",
113131
+ retryable: true
113132
+ }),
113133
+ summary: `Client rewrite failed: ${message}`,
113134
+ error: {
113135
+ code: "rewrite_failed",
113136
+ title: "Supabase client rewrite failed",
113137
+ explanation: message,
113138
+ suggestion
113139
+ }
113140
+ };
113141
+ }
110869
113142
  // ../core/dist/commands/migrate-supabase-schema.js
110870
- import { mkdir as mkdir2, writeFile as writeFile2 } from "node:fs/promises";
110871
- import { isAbsolute as isAbsolute2, join as join17, relative as relative3, resolve as resolve6 } from "node:path";
113143
+ import { mkdir as mkdir4, writeFile as writeFile4 } from "node:fs/promises";
113144
+ import { isAbsolute as isAbsolute3, join as join20, relative as relative6, resolve as resolve9 } from "node:path";
110872
113145
 
110873
113146
  // ../core/dist/commands/migrate-supabase-scripts.js
110874
113147
  function generateDataImportScripts(preview) {
@@ -111316,7 +113589,7 @@ var migrateSupabaseSchemaInputSchema = exports_external.object({
111316
113589
  });
111317
113590
  async function migrateSupabaseSchema(ctx, input) {
111318
113591
  const outputDirAbs = resolveOutputDir(ctx.cwd, input.outputDir);
111319
- const outputDirRel = relative3(ctx.cwd, outputDirAbs) || ".";
113592
+ const outputDirRel = relative6(ctx.cwd, outputDirAbs) || ".";
111320
113593
  ctx.status(`Inspecting Supabase project ${input.projectRef}...`);
111321
113594
  const inspection = await inspectSupabase(ctx, {
111322
113595
  projectRef: input.projectRef,
@@ -111362,7 +113635,7 @@ async function migrateSupabaseSchema(ctx, input) {
111362
113635
  }
111363
113636
  };
111364
113637
  }
111365
- const summary = renderSummary2({
113638
+ const summary = renderSummary3({
111366
113639
  projectRef: input.projectRef,
111367
113640
  outputDirRel,
111368
113641
  inspection,
@@ -111380,28 +113653,28 @@ async function migrateSupabaseSchema(ctx, input) {
111380
113653
  }
111381
113654
  function resolveOutputDir(cwd, requested) {
111382
113655
  const raw = requested ?? "./migration-preview";
111383
- return isAbsolute2(raw) ? raw : resolve6(cwd, raw);
113656
+ return isAbsolute3(raw) ? raw : resolve9(cwd, raw);
111384
113657
  }
111385
113658
  async function writePreviewFiles(ctx, outputDir, preview) {
111386
- await mkdir2(outputDir, { recursive: true });
113659
+ await mkdir4(outputDir, { recursive: true });
111387
113660
  const schemaJson = renderSchemaJson(preview);
111388
113661
  const notesMd = renderMigrationNotes(preview);
111389
113662
  const scripts = generateDataImportScripts(preview);
111390
- const schemaPath = join17(outputDir, "pb_schema.json");
111391
- const notesPath = join17(outputDir, "MIGRATION_NOTES.md");
111392
- const migratePath = join17(outputDir, "pb_migrate.js");
111393
- const storagePath = join17(outputDir, "pb_migrate_storage.js");
111394
- await writeFile2(schemaPath, schemaJson, "utf8");
111395
- await writeFile2(notesPath, notesMd, "utf8");
111396
- await writeFile2(migratePath, scripts.pbMigrate, "utf8");
113663
+ const schemaPath = join20(outputDir, "pb_schema.json");
113664
+ const notesPath = join20(outputDir, "MIGRATION_NOTES.md");
113665
+ const migratePath = join20(outputDir, "pb_migrate.js");
113666
+ const storagePath = join20(outputDir, "pb_migrate_storage.js");
113667
+ await writeFile4(schemaPath, schemaJson, "utf8");
113668
+ await writeFile4(notesPath, notesMd, "utf8");
113669
+ await writeFile4(migratePath, scripts.pbMigrate, "utf8");
111397
113670
  const written = [
111398
- relative3(ctx.cwd, schemaPath),
111399
- relative3(ctx.cwd, notesPath),
111400
- relative3(ctx.cwd, migratePath)
113671
+ relative6(ctx.cwd, schemaPath),
113672
+ relative6(ctx.cwd, notesPath),
113673
+ relative6(ctx.cwd, migratePath)
111401
113674
  ];
111402
113675
  if (scripts.pbMigrateStorage !== null) {
111403
- await writeFile2(storagePath, scripts.pbMigrateStorage, "utf8");
111404
- written.push(relative3(ctx.cwd, storagePath));
113676
+ await writeFile4(storagePath, scripts.pbMigrateStorage, "utf8");
113677
+ written.push(relative6(ctx.cwd, storagePath));
111405
113678
  }
111406
113679
  return written;
111407
113680
  }
@@ -111550,7 +113823,7 @@ function renderMigrationNotes(preview) {
111550
113823
  return lines.join(`
111551
113824
  `);
111552
113825
  }
111553
- function renderSummary2(args) {
113826
+ function renderSummary3(args) {
111554
113827
  const counts = args.preview.summary;
111555
113828
  return [
111556
113829
  `Wrote migration preview for Supabase project ${args.projectRef} to ${args.outputDirRel}/.`,
@@ -111560,29 +113833,6 @@ function renderSummary2(args) {
111560
113833
  "Review `MIGRATION_NOTES.md` before running the import step."
111561
113834
  ].join(" ");
111562
113835
  }
111563
- // ../core/dist/commands/migrate-supabase-sdk.js
111564
- var import_jscodeshift = __toESM(require_core3(), 1);
111565
- var tsx = import_jscodeshift.default.withParser("tsx");
111566
- var STORAGE_OPERATIONS = new Set([
111567
- "upload",
111568
- "uploadToSignedUrl",
111569
- "download",
111570
- "list",
111571
- "remove",
111572
- "move",
111573
- "copy",
111574
- "createSignedUrl",
111575
- "createSignedUrls",
111576
- "createSignedUploadUrl",
111577
- "getPublicUrl",
111578
- "update",
111579
- "exists",
111580
- "info"
111581
- ]);
111582
- var CHAIN_CONTINUATIONS = new Set(["then", "catch", "finally"]);
111583
- // ../core/dist/commands/migrate-supabase-walker.js
111584
- var import_ignore3 = __toESM(require_ignore(), 1);
111585
- var REWRITABLE_EXTENSIONS = new Set([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"]);
111586
113836
  // ../core/dist/commands/open.js
111587
113837
  var openInputSchema = exports_external.object({
111588
113838
  app: exports_external.string().optional()
@@ -111640,7 +113890,7 @@ async function previewBranchShow(ctx, input = {}) {
111640
113890
  }
111641
113891
  // ../core/dist/commands/publish.js
111642
113892
  import { existsSync as existsSync14 } from "node:fs";
111643
- import { join as join20 } from "node:path";
113893
+ import { join as join23 } from "node:path";
111644
113894
 
111645
113895
  // ../shared/dist/pow.js
111646
113896
  import { createHash as createHash3 } from "node:crypto";
@@ -112017,7 +114267,7 @@ async function runDeployWithRetry(opts) {
112017
114267
 
112018
114268
  // ../core/dist/commands/env-scan.js
112019
114269
  import { readdirSync as readdirSync3, readFileSync as readFileSync10, statSync as statSync3 } from "node:fs";
112020
- import { join as join18 } from "node:path";
114270
+ import { join as join21 } from "node:path";
112021
114271
  var SOURCE_EXTS = new Set([
112022
114272
  ".ts",
112023
114273
  ".tsx",
@@ -112054,7 +114304,7 @@ function scanForMissingBuildEnvRefs(cwd, existingKeys) {
112054
114304
  continue;
112055
114305
  let content;
112056
114306
  try {
112057
- content = readFileSync10(join18(cwd, rel), "utf8");
114307
+ content = readFileSync10(join21(cwd, rel), "utf8");
112058
114308
  } catch {
112059
114309
  continue;
112060
114310
  }
@@ -112086,7 +114336,7 @@ function* walkDir(dir, base) {
112086
114336
  for (const name of entries) {
112087
114337
  if (SKIP_DIRS.has(name))
112088
114338
  continue;
112089
- const full = join18(dir, name);
114339
+ const full = join21(dir, name);
112090
114340
  let st;
112091
114341
  try {
112092
114342
  st = statSync3(full);
@@ -112447,9 +114697,9 @@ function titleFromCode(code) {
112447
114697
 
112448
114698
  // ../core/dist/commands/publish-node.js
112449
114699
  import { existsSync as existsSync13, readFileSync as readFileSync11 } from "node:fs";
112450
- import { join as join19 } from "node:path";
114700
+ import { join as join22 } from "node:path";
112451
114701
  function resolveNodeVersion(cwd) {
112452
- const nvmrc = join19(cwd, ".nvmrc");
114702
+ const nvmrc = join22(cwd, ".nvmrc");
112453
114703
  if (existsSync13(nvmrc)) {
112454
114704
  try {
112455
114705
  const v = readFileSync11(nvmrc, "utf8").trim();
@@ -112457,7 +114707,7 @@ function resolveNodeVersion(cwd) {
112457
114707
  return { value: v, source: ".nvmrc" };
112458
114708
  } catch {}
112459
114709
  }
112460
- const pkgPath = join19(cwd, "package.json");
114710
+ const pkgPath = join22(cwd, "package.json");
112461
114711
  if (!existsSync13(pkgPath))
112462
114712
  return null;
112463
114713
  try {
@@ -112483,7 +114733,7 @@ var publishInputSchema = exports_external.object({
112483
114733
  var SUSPICIOUS_BYTES = 50 * 1024 * 1024;
112484
114734
  var SUSPICIOUS_FILES = 1e4;
112485
114735
  function tomlPathFor2(cwd) {
112486
- return join20(cwd, "percher.toml");
114736
+ return join23(cwd, "percher.toml");
112487
114737
  }
112488
114738
  async function buildReplacedResult2(opts) {
112489
114739
  const { ctx, app, deployment, tarball, cwd } = opts;
@@ -113103,13 +115353,11 @@ async function handleAnonymousPublish(ctx, config2, input, tarball) {
113103
115353
  bundle: { fileCount: tarball.fileCount, bytes: tarball.bytes }
113104
115354
  };
113105
115355
  }
113106
- saveConfig({
113107
- token: created.token,
113108
- anonClaim: {
113109
- app: created.app.name,
113110
- claimToken: created.claimToken,
113111
- expiresAt: created.expiresAt
113112
- }
115356
+ saveConfig({ token: created.token });
115357
+ setAnonClaim({
115358
+ app: created.app.name,
115359
+ claimToken: created.claimToken,
115360
+ expiresAt: created.expiresAt
113113
115361
  });
113114
115362
  const newClient = new PercherClient({
113115
115363
  apiUrl: ctx.client.apiUrl,
@@ -113150,7 +115398,7 @@ async function handleAnonymousPublish(ctx, config2, input, tarball) {
113150
115398
  };
113151
115399
  }
113152
115400
  async function loadOrGenerate(ctx) {
113153
- const tomlPath = join20(ctx.cwd, "percher.toml");
115401
+ const tomlPath = join23(ctx.cwd, "percher.toml");
113154
115402
  if (!existsSync14(tomlPath)) {
113155
115403
  ctx.status("No percher.toml found — detecting framework...");
113156
115404
  await init(ctx);
@@ -113201,7 +115449,7 @@ function emitPreflight(ctx, config2, tarball) {
113201
115449
  }
113202
115450
  // ../core/dist/commands/push.js
113203
115451
  import { existsSync as existsSync15 } from "node:fs";
113204
- import { join as join21 } from "node:path";
115452
+ import { join as join24 } from "node:path";
113205
115453
  var pushInputSchema = exports_external.object({
113206
115454
  dryRun: exports_external.boolean().optional(),
113207
115455
  force: exports_external.boolean().optional(),
@@ -113212,7 +115460,7 @@ var SUSPICIOUS_BYTES2 = 50 * 1024 * 1024;
113212
115460
  var SUSPICIOUS_FILES2 = 1e4;
113213
115461
  var PLACEHOLDER_PREFIXES = ["add-your-", "your-key-here"];
113214
115462
  async function loadOrGenerate2(ctx) {
113215
- const tomlPath = join21(ctx.cwd, "percher.toml");
115463
+ const tomlPath = join24(ctx.cwd, "percher.toml");
113216
115464
  if (!existsSync15(tomlPath)) {
113217
115465
  ctx.status("No percher.toml found — detecting framework...");
113218
115466
  const result = await init(ctx);
@@ -113324,7 +115572,7 @@ async function push(ctx, input = {}, internals = {}) {
113324
115572
  fileCount: tarball.fileCount,
113325
115573
  recovery: RECOVERY_NONE,
113326
115574
  summary: `Dry run for ${config2.app.name}: ${tarball.fileCount} files, ${(tarball.bytes / 1024).toFixed(1)} KB — no deploy performed.`,
113327
- configPath: join21(ctx.cwd, "percher.toml"),
115575
+ configPath: join24(ctx.cwd, "percher.toml"),
113328
115576
  bundle: { fileCount: tarball.fileCount, bytes: tarball.bytes }
113329
115577
  };
113330
115578
  }
@@ -113507,7 +115755,7 @@ ${deployment.errorMessage}` : "";
113507
115755
  fileCount: tarball.fileCount,
113508
115756
  recovery: RECOVERY_NONE,
113509
115757
  summary,
113510
- configPath: join21(ctx.cwd, "percher.toml"),
115758
+ configPath: join24(ctx.cwd, "percher.toml"),
113511
115759
  bundle: { fileCount: tarball.fileCount, bytes: tarball.bytes }
113512
115760
  };
113513
115761
  }
@@ -113837,7 +116085,7 @@ function failureResult(error48) {
113837
116085
  }
113838
116086
  // ../core/dist/commands/rename.js
113839
116087
  import { existsSync as existsSync16, readFileSync as readFileSync12, writeFileSync as writeFileSync8 } from "node:fs";
113840
- import { join as join22 } from "node:path";
116088
+ import { join as join25 } from "node:path";
113841
116089
  var renameInputSchema = exports_external.object({
113842
116090
  app: exports_external.string().optional(),
113843
116091
  name: exports_external.string().min(3).max(40)
@@ -113857,7 +116105,7 @@ async function rename2(ctx, input) {
113857
116105
  };
113858
116106
  }
113859
116107
  function updateLocalTomlName(cwd, oldName, newName) {
113860
- const p = join22(cwd, "percher.toml");
116108
+ const p = join25(cwd, "percher.toml");
113861
116109
  if (!existsSync16(p))
113862
116110
  return false;
113863
116111
  try {
@@ -113876,16 +116124,16 @@ function updateLocalTomlName(cwd, oldName, newName) {
113876
116124
  // ../core/dist/commands/reproduce.js
113877
116125
  import { mkdtempSync, writeFileSync as writeFileSync9 } from "node:fs";
113878
116126
  import { tmpdir } from "node:os";
113879
- import { join as join23 } from "node:path";
113880
- var import_cross_spawn = __toESM(require_cross_spawn(), 1);
116127
+ import { join as join26 } from "node:path";
116128
+ var import_cross_spawn2 = __toESM(require_cross_spawn(), 1);
113881
116129
  function runProcessExit(cmd, args, opts = {}) {
113882
- return new Promise((resolve7, reject) => {
113883
- const child = import_cross_spawn.default(cmd, args, {
116130
+ return new Promise((resolve10, reject) => {
116131
+ const child = import_cross_spawn2.default(cmd, args, {
113884
116132
  cwd: opts.cwd,
113885
116133
  stdio: opts.inherit ? "inherit" : "ignore"
113886
116134
  });
113887
116135
  child.on("error", reject);
113888
- child.on("close", (code) => resolve7(code ?? 1));
116136
+ child.on("close", (code) => resolve10(code ?? 1));
113889
116137
  });
113890
116138
  }
113891
116139
  var reproduceInputSchema = exports_external.object({
@@ -113971,8 +116219,8 @@ async function reproduce(ctx, input) {
113971
116219
  const envMap = await ctx.client.env.list(app.id);
113972
116220
  currentAppEnvKeys = Object.keys(envMap).sort();
113973
116221
  } catch {}
113974
- const tmpDir = mkdtempSync(join23(tmpdir(), `percher-reproduce-${input.deployId}-`));
113975
- const tarballPath = join23(tmpDir, "source.tar.gz");
116222
+ const tmpDir = mkdtempSync(join26(tmpdir(), `percher-reproduce-${input.deployId}-`));
116223
+ const tarballPath = join26(tmpDir, "source.tar.gz");
113976
116224
  writeFileSync9(tarballPath, bytes);
113977
116225
  let extracted = false;
113978
116226
  try {
@@ -115312,8 +117560,8 @@ function registerAppsCommands(cli, ctx) {
115312
117560
  deployId,
115313
117561
  timeoutSeconds: Math.min(Math.ceil(remainingMs / 1000), 30)
115314
117562
  }, { signal: callController.signal }),
115315
- new Promise((resolve7) => {
115316
- raceTimer = setTimeout(() => resolve7(null), remainingMs);
117563
+ new Promise((resolve10) => {
117564
+ raceTimer = setTimeout(() => resolve10(null), remainingMs);
115317
117565
  })
115318
117566
  ]);
115319
117567
  } finally {
@@ -115779,8 +118027,8 @@ function registerDeploysCommands(cli, ctx, argv) {
115779
118027
  const { summary, files } = result;
115780
118028
  await writeLine(ctx, `${summary.filesChanged} file${summary.filesChanged === 1 ? "" : "s"} changed · ${import_picocolors7.default.green(`+${summary.additions}`)} ${import_picocolors7.default.red(`−${summary.deletions}`)} (${result.base.slice(0, 10)} → ${result.head.slice(0, 10)})`);
115781
118029
  for (const f of files) {
115782
- const stat = f.binary ? import_picocolors7.default.dim("binary") : `${import_picocolors7.default.green(`+${f.additions}`)} ${import_picocolors7.default.red(`−${f.deletions}`)}`;
115783
- await writeLine(ctx, ` ${f.status} ${f.path} ${stat}${f.truncated ? import_picocolors7.default.dim(" (truncated)") : ""}`);
118030
+ const stat2 = f.binary ? import_picocolors7.default.dim("binary") : `${import_picocolors7.default.green(`+${f.additions}`)} ${import_picocolors7.default.red(`−${f.deletions}`)}`;
118031
+ await writeLine(ctx, ` ${f.status} ${f.path} ${stat2}${f.truncated ? import_picocolors7.default.dim(" (truncated)") : ""}`);
115784
118032
  if (options.patch && f.patch) {
115785
118033
  await writeLine(ctx, f.patch.replace(/\n$/, ""));
115786
118034
  }
@@ -115852,7 +118100,7 @@ function registerEnvCommands(cli, ctx) {
115852
118100
  if (action === "set") {
115853
118101
  const { resolveEnvSetInputs: resolveEnvSetInputs2, EnvSetInputError: EnvSetInputError2 } = await Promise.resolve().then(() => (init_env_set_input(), exports_env_set_input));
115854
118102
  const { promptHidden: promptHidden2 } = await Promise.resolve().then(() => (init_prompt_hidden(), exports_prompt_hidden));
115855
- const { readFile: readFile3 } = await import("node:fs/promises");
118103
+ const { readFile: readFile5 } = await import("node:fs/promises");
115856
118104
  try {
115857
118105
  const values = await resolveEnvSetInputs2({
115858
118106
  args,
@@ -115864,7 +118112,7 @@ function registerEnvCommands(cli, ctx) {
115864
118112
  chunks.push(c);
115865
118113
  return Buffer.concat(chunks).toString("utf8");
115866
118114
  },
115867
- readFile: async (p) => readFile3(p, "utf8"),
118115
+ readFile: async (p) => readFile5(p, "utf8"),
115868
118116
  promptHidden: promptHidden2
115869
118117
  });
115870
118118
  await envSet(ctx, { app: options.app, values });
@@ -115978,9 +118226,30 @@ function registerGithubCommands(cli, ctx) {
115978
118226
  // src/commands/migrate.ts
115979
118227
  var import_picocolors11 = __toESM(require_picocolors(), 1);
115980
118228
  function registerMigrateCommands(cli, ctx) {
115981
- cli.command("migrate-from-supabase", "Migrate a Supabase project to PocketBase (FUTURE9 Phase A read-only + Phase B preview writes)").option("--project <ref>", "Supabase project reference (the 20-char id from the project URL)").option("--token <token>", "Supabase personal access token (sbp_...). Read from SUPABASE_ACCESS_TOKEN if omitted.").option("--inspect-only", "Run schema introspection only (Phase A — read-only, no file writes)").option("--output-dir <dir>", "Where to write the Phase B preview files (default: ./migration-preview/)").option("--json", "Output the structured result as JSON").action(async (options) => {
118229
+ cli.command("migrate-from-supabase", "Migrate a Supabase project to PocketBase: schema + data-import script, optionally rewrite SDK calls").option("--project <ref>", "Supabase project reference (the 20-char id from the project URL)").option("--token <token>", "Supabase personal access token (sbp_...). Read from SUPABASE_ACCESS_TOKEN if omitted.").option("--inspect-only", "Only print the schema that would migrate — read-only, no file writes").option("--output-dir <dir>", "Where to write the preview files (default: ./migration-preview/)").option("--rewrite-client", "Also convert your Supabase SDK calls to PocketBase across the project").option("--apply", "With --rewrite-client: overwrite files in place (originals backed up first). Default: preview only.").option("--root <dir>", "Project root to rewrite with --rewrite-client (default: current directory)").option("--no-scaffold-client", "With --rewrite-client: don't generate a PocketBase client module / insert pb imports (default: scaffold one)").option("--status", "Show a migration scoreboard for the local project — what's still on Supabase vs PocketBase. Local scan, no Supabase token needed.").option("--build", "With --status: also run the project build as a final gate").option("--pb-identifier <name>", "With --status: the PocketBase client identifier to check for (default: pb). Match what the rewrite used.").option("--json", "Output the structured result as JSON").action(async (options) => {
118230
+ if (options.status) {
118231
+ const result2 = await migrationStatus(ctx, {
118232
+ rootDir: options.root,
118233
+ build: options.build === true,
118234
+ pbIdentifier: options.pbIdentifier
118235
+ });
118236
+ if (options.json) {
118237
+ await writeLine(ctx, JSON.stringify(result2, null, 2));
118238
+ if (result2.status === "failed")
118239
+ throw new SilentExitError(1);
118240
+ return;
118241
+ }
118242
+ await renderStatusHuman(ctx, result2);
118243
+ if (result2.status === "failed")
118244
+ throw new SilentExitError(1);
118245
+ return;
118246
+ }
115982
118247
  const projectRef = options.project;
115983
118248
  const token = options.token ?? ctx.env.SUPABASE_ACCESS_TOKEN;
118249
+ if (options.apply && !options.rewriteClient) {
118250
+ await writeLine(ctx, `${import_picocolors11.default.red("✗")} --apply only applies to the client rewrite. Pass --rewrite-client --apply together.`);
118251
+ throw new SilentExitError(1);
118252
+ }
115984
118253
  if (!projectRef) {
115985
118254
  await writeLine(ctx, `${import_picocolors11.default.red("✗")} Missing --project. Pass your Supabase project ref (e.g. --project abcdefghijklmnopqrst).`);
115986
118255
  throw new SilentExitError(1);
@@ -116007,15 +118276,29 @@ function registerMigrateCommands(cli, ctx) {
116007
118276
  token,
116008
118277
  outputDir: options.outputDir
116009
118278
  });
118279
+ let rewrite;
118280
+ if (options.rewriteClient && result.status === "ok") {
118281
+ rewrite = await rewriteSupabaseClient(ctx, {
118282
+ rootDir: options.root,
118283
+ apply: options.apply === true,
118284
+ scaffoldClient: options.scaffoldClient !== false
118285
+ });
118286
+ }
116010
118287
  if (options.json) {
116011
- await writeLine(ctx, JSON.stringify(result, null, 2));
116012
- if (result.status === "failed")
118288
+ await writeLine(ctx, JSON.stringify(rewrite ? { schema: result, rewrite } : result, null, 2));
118289
+ if (result.status === "failed" || rewrite?.status === "failed") {
116013
118290
  throw new SilentExitError(1);
118291
+ }
116014
118292
  return;
116015
118293
  }
116016
- await renderSchemaHuman(ctx, result);
116017
- if (result.status === "failed")
118294
+ await renderSchemaHuman(ctx, result, {
118295
+ clientRewriteRequested: options.rewriteClient === true
118296
+ });
118297
+ if (rewrite)
118298
+ await renderRewriteHuman(ctx, rewrite);
118299
+ if (result.status === "failed" || rewrite?.status === "failed") {
116018
118300
  throw new SilentExitError(1);
118301
+ }
116019
118302
  });
116020
118303
  }
116021
118304
  async function renderInspectHuman(ctx, result) {
@@ -116061,9 +118344,9 @@ async function renderInspectHuman(ctx, result) {
116061
118344
  }
116062
118345
  }
116063
118346
  await writeLine(ctx, "");
116064
- await writeLine(ctx, import_picocolors11.default.dim("--inspect-only is read-only. Drop the flag to also write the Phase B PocketBase-schema preview."));
118347
+ await writeLine(ctx, import_picocolors11.default.dim("--inspect-only is read-only. Drop the flag to also write the PocketBase schema preview + pb_migrate.js data-import script to ./migration-preview/."));
116065
118348
  }
116066
- async function renderSchemaHuman(ctx, result) {
118349
+ async function renderSchemaHuman(ctx, result, opts) {
116067
118350
  if (result.status === "failed") {
116068
118351
  const err = result.error;
116069
118352
  await writeLine(ctx, `${import_picocolors11.default.red("✗")} ${err?.title ?? "Migration preview failed"}`);
@@ -116102,7 +118385,86 @@ async function renderSchemaHuman(ctx, result) {
116102
118385
  }
116103
118386
  }
116104
118387
  await writeLine(ctx, "");
116105
- await writeLine(ctx, import_picocolors11.default.dim("Phase B is a preview. Phase C (data import) and Phase D (client rewrite) ship in later releases. Review MIGRATION_NOTES.md before any import."));
118388
+ await writeLine(ctx, import_picocolors11.default.dim("Preview only — nothing has touched your PocketBase yet. ./migration-preview/ includes pb_migrate.js, the data-import script: review MIGRATION_NOTES.md, then run it against your app's PocketBase to copy your rows over."));
118389
+ if (!opts.clientRewriteRequested) {
118390
+ await writeLine(ctx, import_picocolors11.default.dim("Add --rewrite-client to also convert your Supabase SDK calls to PocketBase (preview first; --apply writes in place)."));
118391
+ }
118392
+ }
118393
+ async function renderRewriteHuman(ctx, result) {
118394
+ await writeLine(ctx, "");
118395
+ if (result.status === "failed") {
118396
+ const err = result.error;
118397
+ await writeLine(ctx, `${import_picocolors11.default.red("✗")} ${err?.title ?? "Client rewrite failed"}`);
118398
+ if (err?.explanation)
118399
+ await writeLine(ctx, ` ${err.explanation}`);
118400
+ if (err?.suggestion)
118401
+ await writeLine(ctx, import_picocolors11.default.dim(` ${err.suggestion}`));
118402
+ return;
118403
+ }
118404
+ await writeLine(ctx, `${import_picocolors11.default.green("✓")} ${result.summary}`);
118405
+ if (result.filesWritten.length > 0) {
118406
+ await writeLine(ctx, "");
118407
+ await writeLine(ctx, import_picocolors11.default.bold("Files written"));
118408
+ for (const path of result.filesWritten.slice(0, 20)) {
118409
+ await writeLine(ctx, ` ${import_picocolors11.default.cyan(path)}`);
118410
+ }
118411
+ if (result.filesWritten.length > 20) {
118412
+ await writeLine(ctx, import_picocolors11.default.dim(` …and ${result.filesWritten.length - 20} more`));
118413
+ }
118414
+ }
118415
+ if (result.flags.length > 0) {
118416
+ await writeLine(ctx, "");
118417
+ await writeLine(ctx, import_picocolors11.default.bold("Needs review (see migration-preview/REWRITE_NOTES.md)"));
118418
+ for (const flag of result.flags.slice(0, 15)) {
118419
+ const loc = flag.line !== undefined ? `:${flag.line}` : "";
118420
+ const tag = flag.kind === "manual_review" ? "rewritten, verify semantics" : "left untouched";
118421
+ await writeLine(ctx, ` ${import_picocolors11.default.yellow("⚠")} ${import_picocolors11.default.cyan(`${flag.file}${loc}`)} ${flag.pattern} ${import_picocolors11.default.dim(`(${tag}) — ${flag.note}`)}`);
118422
+ }
118423
+ if (result.flags.length > 15) {
118424
+ await writeLine(ctx, import_picocolors11.default.dim(` …and ${result.flags.length - 15} more — see REWRITE_NOTES.md`));
118425
+ }
118426
+ }
118427
+ if (result.skipped.length > 0) {
118428
+ await writeLine(ctx, import_picocolors11.default.dim(`
118429
+ ${result.skipped.length} file(s) couldn't be parsed and were skipped — listed in REWRITE_NOTES.md.`));
118430
+ }
118431
+ await writeLine(ctx, "");
118432
+ if (result.mode === "apply") {
118433
+ await writeLine(ctx, import_picocolors11.default.dim(result.changedCount > 0 ? "Files rewritten in place. Originals are in ./migration-preview/backup/ — diff against them (or git) before committing." : "No files were rewritten — the work left is the manual review above."));
118434
+ } else {
118435
+ await writeLine(ctx, import_picocolors11.default.dim(result.changedCount > 0 ? "Preview only — diff ./migration-preview/rewritten/ against your project, then re-run with --rewrite-client --apply to write in place." : "Preview only — no files needed automatic rewriting; work through the manual review above."));
118436
+ }
118437
+ }
118438
+ async function renderStatusHuman(ctx, result) {
118439
+ if (result.status === "failed") {
118440
+ const err = result.error;
118441
+ await writeLine(ctx, `${import_picocolors11.default.red("✗")} ${err?.title ?? "Migration status scan failed"}`);
118442
+ if (err?.explanation)
118443
+ await writeLine(ctx, ` ${err.explanation}`);
118444
+ if (err?.suggestion)
118445
+ await writeLine(ctx, import_picocolors11.default.dim(` ${err.suggestion}`));
118446
+ return;
118447
+ }
118448
+ await writeLine(ctx, import_picocolors11.default.bold("Migration status"));
118449
+ await writeLine(ctx, "");
118450
+ for (const check2 of result.checks) {
118451
+ const mark = check2.status === "pass" ? import_picocolors11.default.green("✓") : check2.status === "fail" ? import_picocolors11.default.red("✗") : check2.status === "warn" ? import_picocolors11.default.yellow("⚠") : import_picocolors11.default.dim("•");
118452
+ const count = check2.count > 0 ? import_picocolors11.default.dim(` (${check2.count})`) : "";
118453
+ await writeLine(ctx, ` ${mark} ${check2.label}${count} ${import_picocolors11.default.dim(`— ${check2.detail}`)}`);
118454
+ for (const file2 of (check2.files ?? []).slice(0, 10)) {
118455
+ await writeLine(ctx, import_picocolors11.default.dim(` - ${file2}`));
118456
+ }
118457
+ if ((check2.files?.length ?? 0) > 10) {
118458
+ await writeLine(ctx, import_picocolors11.default.dim(` …and ${(check2.files?.length ?? 0) - 10} more`));
118459
+ }
118460
+ }
118461
+ if (result.build) {
118462
+ await writeLine(ctx, "");
118463
+ const mark = !result.build.ran ? import_picocolors11.default.dim("•") : result.build.passed ? import_picocolors11.default.green("✓") : import_picocolors11.default.red("✗");
118464
+ await writeLine(ctx, ` ${mark} Build ${import_picocolors11.default.dim(`— ${result.build.detail}`)}`);
118465
+ }
118466
+ await writeLine(ctx, "");
118467
+ await writeLine(ctx, import_picocolors11.default.dim(result.summary));
116106
118468
  }
116107
118469
 
116108
118470
  // src/commands/sharing.ts
@@ -116443,7 +118805,7 @@ async function renderError(stderr, error48) {
116443
118805
  // package.json
116444
118806
  var package_default = {
116445
118807
  name: "percher",
116446
- version: "0.5.6",
118808
+ version: "0.5.8",
116447
118809
  description: "CLI for the Percher hosting platform — publish apps with one command",
116448
118810
  type: "module",
116449
118811
  bin: {
@@ -116525,9 +118887,9 @@ async function showTelemetryNotice() {
116525
118887
  return;
116526
118888
  const { homedir: homedir2 } = await import("node:os");
116527
118889
  const { existsSync: existsSync17, mkdirSync: mkdirSync6, writeFileSync: writeFileSync10 } = await import("node:fs");
116528
- const { join: join24 } = await import("node:path");
116529
- const configDir = join24(homedir2(), ".percher");
116530
- const markerFile = join24(configDir, ".telemetry-notice-shown");
118890
+ const { join: join27 } = await import("node:path");
118891
+ const configDir = join27(homedir2(), ".percher");
118892
+ const markerFile = join27(configDir, ".telemetry-notice-shown");
116531
118893
  if (existsSync17(markerFile))
116532
118894
  return;
116533
118895
  console.log("Percher sends non-account-linked usage stats (command, result, error type, OS, Bun version).");