percher 0.5.7 → 0.5.9

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.
@@ -3604,8 +3604,8 @@ var require_streamx = __commonJS((exports, module) => {
3604
3604
  return this;
3605
3605
  },
3606
3606
  next() {
3607
- return new Promise(function(resolve6, reject) {
3608
- promiseResolve = resolve6;
3607
+ return new Promise(function(resolve7, reject) {
3608
+ promiseResolve = resolve7;
3609
3609
  promiseReject = reject;
3610
3610
  const data2 = stream.read();
3611
3611
  if (data2 !== null)
@@ -3642,14 +3642,14 @@ var require_streamx = __commonJS((exports, module) => {
3642
3642
  }
3643
3643
  function destroy(err) {
3644
3644
  stream.destroy(err);
3645
- return new Promise((resolve6, reject) => {
3645
+ return new Promise((resolve7, reject) => {
3646
3646
  if (stream._duplexState & DESTROYED)
3647
- return resolve6({ value: undefined, done: true });
3647
+ return resolve7({ value: undefined, done: true });
3648
3648
  stream.once("close", function() {
3649
3649
  if (err)
3650
3650
  reject(err);
3651
3651
  else
3652
- resolve6({ value: undefined, done: true });
3652
+ resolve7({ value: undefined, done: true });
3653
3653
  });
3654
3654
  });
3655
3655
  }
@@ -3701,8 +3701,8 @@ var require_streamx = __commonJS((exports, module) => {
3701
3701
  return Promise.resolve(true);
3702
3702
  if (state.drains === null)
3703
3703
  state.drains = [];
3704
- return new Promise((resolve6) => {
3705
- state.drains.push({ writes, resolve: resolve6 });
3704
+ return new Promise((resolve7) => {
3705
+ state.drains.push({ writes, resolve: resolve7 });
3706
3706
  });
3707
3707
  }
3708
3708
  write(data2) {
@@ -3816,11 +3816,11 @@ var require_streamx = __commonJS((exports, module) => {
3816
3816
  cb(null);
3817
3817
  }
3818
3818
  function pipelinePromise(...streams) {
3819
- return new Promise((resolve6, reject) => {
3819
+ return new Promise((resolve7, reject) => {
3820
3820
  return pipeline(...streams, (err) => {
3821
3821
  if (err)
3822
3822
  return reject(err);
3823
- resolve6();
3823
+ resolve7();
3824
3824
  });
3825
3825
  });
3826
3826
  }
@@ -4534,16 +4534,16 @@ var require_extract = __commonJS((exports, module) => {
4534
4534
  entryCallback = null;
4535
4535
  cb(err);
4536
4536
  }
4537
- function onnext(resolve6, reject) {
4537
+ function onnext(resolve7, reject) {
4538
4538
  if (error48) {
4539
4539
  return reject(error48);
4540
4540
  }
4541
4541
  if (entryStream) {
4542
- resolve6({ value: entryStream, done: false });
4542
+ resolve7({ value: entryStream, done: false });
4543
4543
  entryStream = null;
4544
4544
  return;
4545
4545
  }
4546
- promiseResolve = resolve6;
4546
+ promiseResolve = resolve7;
4547
4547
  promiseReject = reject;
4548
4548
  consumeCallback(null);
4549
4549
  if (extract._finished && promiseResolve) {
@@ -4574,14 +4574,14 @@ var require_extract = __commonJS((exports, module) => {
4574
4574
  function destroy(err) {
4575
4575
  extract.destroy(err);
4576
4576
  consumeCallback(err);
4577
- return new Promise((resolve6, reject) => {
4577
+ return new Promise((resolve7, reject) => {
4578
4578
  if (extract.destroyed)
4579
- return resolve6({ value: undefined, done: true });
4579
+ return resolve7({ value: undefined, done: true });
4580
4580
  extract.once("close", function() {
4581
4581
  if (err)
4582
4582
  reject(err);
4583
4583
  else
4584
- resolve6({ value: undefined, done: true });
4584
+ resolve7({ value: undefined, done: true });
4585
4585
  });
4586
4586
  });
4587
4587
  }
@@ -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(resolve6) {
5073
- resolve6(value);
5072
+ return value instanceof P ? value : new P(function(resolve7) {
5073
+ resolve7(value);
5074
5074
  });
5075
5075
  }
5076
- return new (P || (P = Promise))(function(resolve6, reject) {
5076
+ return new (P || (P = Promise))(function(resolve7, 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 ? resolve6(result.value) : adopt(result.value).then(fulfilled, rejected);
5092
+ result.done ? resolve7(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(resolve6, reject) {
5322
- v = o[n](v), settle(resolve6, reject, v.done, v.value);
5321
+ return new Promise(function(resolve7, reject) {
5322
+ v = o[n](v), settle(resolve7, reject, v.done, v.value);
5323
5323
  });
5324
5324
  };
5325
5325
  }
5326
- function settle(resolve6, reject, d, v) {
5326
+ function settle(resolve7, reject, d, v) {
5327
5327
  Promise.resolve(v).then(function(v2) {
5328
- resolve6({ value: v2, done: d });
5328
+ resolve7({ 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 isAbsolute2 = exports.isAbsolute(path);
8827
+ var isAbsolute3 = 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 = isAbsolute2 ? "/" : ".";
8847
+ path = isAbsolute3 ? "/" : ".";
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 join17(aRoot, aPath) {
8856
+ function join18(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 = join17;
8888
+ exports.join = join18;
8889
8889
  exports.isAbsolute = function(aPath) {
8890
8890
  return aPath.charAt(0) === "/" || urlRegexp.test(aPath);
8891
8891
  };
8892
- function relative3(aRoot, aPath) {
8892
+ function relative4(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 = relative3;
8911
+ exports.relative = relative4;
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 = join17(urlGenerate(parsed), sourceURL);
9061
+ sourceURL = join18(urlGenerate(parsed), sourceURL);
9062
9062
  }
9063
9063
  return normalize2(sourceURL);
9064
9064
  }
@@ -19563,10 +19563,10 @@ else`, adjustClause(path.call(print, "alternate"), options));
19563
19563
  }
19564
19564
  case "ForStatement": {
19565
19565
  var init2 = path.call(print, "init");
19566
- var sep3 = init2.length > 1 ? `;
19566
+ var sep4 = init2.length > 1 ? `;
19567
19567
  ` : "; ";
19568
19568
  var forParen = "for (";
19569
- var indented = (0, lines_1.fromString)(sep3).join([init2, path.call(print, "test"), path.call(print, "update")]).indentTail(forParen.length);
19569
+ var indented = (0, lines_1.fromString)(sep4).join([init2, path.call(print, "test"), path.call(print, "update")]).indentTail(forParen.length);
19570
19570
  var head = (0, lines_1.concat)([forParen, indented, ")"]);
19571
19571
  var clause = adjustClause(path.call(print, "body"), options);
19572
19572
  parts.push(head);
@@ -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(resolve7, reject) {
85330
+ isexe(path, options || {}, function(er, is) {
85331
+ if (er) {
85332
+ reject(er);
85333
+ } else {
85334
+ resolve7(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((resolve7, reject) => {
85397
+ if (i === pathEnv.length)
85398
+ return opt.all && found.length ? resolve7(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
+ resolve7(subStep(p, i, 0));
85404
+ });
85405
+ const subStep = (p, i, ii) => new Promise((resolve7, reject) => {
85406
+ if (ii === pathExt.length)
85407
+ return resolve7(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 resolve7(p + ext);
85415
+ }
85416
+ return resolve7(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(resolve9, reject) {
89843
+ return new Promise(function(resolve11, reject) {
89388
89844
  try {
89389
89845
  const data2 = QRCode.create(text, opts);
89390
- resolve9(renderFunc(data2, canvas, opts));
89846
+ resolve11(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(resolve9, reject) {
89925
+ return new Promise(function(resolve11, 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) : resolve9(data3);
89929
+ return err ? reject(err) : resolve11(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(stat2, path, options) {
89569
- if (!stat2.isSymbolicLink() && !stat2.isFile()) {
89570
- return false;
89571
- }
89572
- return checkPathExt(path, options);
89573
- }
89574
- function isexe(path, options, cb) {
89575
- fs.stat(path, function(er, stat2) {
89576
- cb(er, er ? false : checkStat(stat2, 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, stat2) {
89591
- cb(er, er ? false : checkStat(stat2, options));
89592
- });
89593
- }
89594
- function sync(path, options) {
89595
- return checkStat(fs.statSync(path), options);
89596
- }
89597
- function checkStat(stat2, options) {
89598
- return stat2.isFile() && checkMode(stat2, options);
89599
- }
89600
- function checkMode(stat2, options) {
89601
- var mod = stat2.mode;
89602
- var uid = stat2.uid;
89603
- var gid = stat2.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(resolve9, reject) {
89636
- isexe(path, options || {}, function(er, is) {
89637
- if (er) {
89638
- reject(er);
89639
- } else {
89640
- resolve9(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((resolve9, reject) => {
89703
- if (i === pathEnv.length)
89704
- return opt.all && found.length ? resolve9(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
- resolve9(subStep(p, i, 0));
89710
- });
89711
- const subStep = (p, i, ii) => new Promise((resolve9, reject) => {
89712
- if (ii === pathExt.length)
89713
- return resolve9(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 resolve9(p + ext);
89721
- }
89722
- return resolve9(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((resolve9, reject) => {
90184
+ return new Promise((resolve11, 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
- resolve9(buf.replace(/\r$/, ""));
90200
+ resolve11(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
- resolve9(buf.replace(/\r$/, ""));
90222
+ resolve11(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((resolve9, reject) => {
90240
+ return await new Promise((resolve11, 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
- resolve9(buf);
90250
+ resolve11(buf);
90251
90251
  return;
90252
90252
  }
90253
90253
  if (ch === "\x03") {
@@ -105399,6 +105399,181 @@ var appResourcesInputSchema = exports_external.object({
105399
105399
  var appTopologyInputSchema = exports_external.object({
105400
105400
  app: exports_external.string().optional()
105401
105401
  });
105402
+ // ../core/dist/commands/appstore-kit.js
105403
+ import { existsSync as existsSync3, mkdirSync as mkdirSync3, writeFileSync as writeFileSync3 } from "node:fs";
105404
+ import { basename, dirname as dirname3, isAbsolute, join as join5, relative, resolve as resolve3, sep } from "node:path";
105405
+
105406
+ // ../core/dist/appstore-artifacts.js
105407
+ var BRAND_GREEN = "#2d6a4f";
105408
+ var ICON_COLOUR_HEX = {
105409
+ green: BRAND_GREEN,
105410
+ terracotta: "#d0653a",
105411
+ blue: "#4a6fa4",
105412
+ purple: "#6e4dba",
105413
+ olive: "#b8923a"
105414
+ };
105415
+ function themeColorForToken(token) {
105416
+ if (token && token in ICON_COLOUR_HEX)
105417
+ return ICON_COLOUR_HEX[token] ?? BRAND_GREEN;
105418
+ return BRAND_GREEN;
105419
+ }
105420
+ function hostFromUrl(url2) {
105421
+ try {
105422
+ return new URL(url2).host;
105423
+ } catch {
105424
+ return url2.replace(/^https?:\/\//, "").replace(/\/.*$/, "");
105425
+ }
105426
+ }
105427
+ function shortName(name) {
105428
+ const cleaned = name.replace(/[^A-Za-z0-9]/g, "");
105429
+ return (cleaned || "App").slice(0, 12);
105430
+ }
105431
+ function manifestStarter({ name, themeColorHex }) {
105432
+ return JSON.stringify({
105433
+ name,
105434
+ short_name: shortName(name),
105435
+ start_url: "/",
105436
+ display: "standalone",
105437
+ background_color: "#ffffff",
105438
+ theme_color: themeColorHex
105439
+ }, null, 2);
105440
+ }
105441
+ function serviceWorkerStarter() {
105442
+ return `// sw.js — minimal offline shell. Drop in at your app root and serve from /sw.js.
105443
+ const CACHE = "app-shell-v1";
105444
+ const SHELL = ["/"];
105445
+
105446
+ self.addEventListener("install", (event) => {
105447
+ event.waitUntil(caches.open(CACHE).then((cache) => cache.addAll(SHELL)));
105448
+ self.skipWaiting();
105449
+ });
105450
+
105451
+ self.addEventListener("activate", (event) => {
105452
+ event.waitUntil(
105453
+ caches.keys().then((keys) =>
105454
+ Promise.all(keys.filter((k) => k !== CACHE).map((k) => caches.delete(k))),
105455
+ ),
105456
+ );
105457
+ self.clients.claim();
105458
+ });
105459
+
105460
+ self.addEventListener("fetch", (event) => {
105461
+ if (event.request.method !== "GET") return;
105462
+ event.respondWith(
105463
+ caches.match(event.request).then((cached) => cached || fetch(event.request)),
105464
+ );
105465
+ });`;
105466
+ }
105467
+ function swRegistrationSnippet() {
105468
+ return `if ("serviceWorker" in navigator) {
105469
+ navigator.serviceWorker.register("/sw.js");
105470
+ }`;
105471
+ }
105472
+ function bubblewrapCommand({ url: url2 }) {
105473
+ const host = hostFromUrl(url2);
105474
+ return `# generate the Android project, pointed at your manifest
105475
+ npx @bubblewrap/cli init --manifest https://${host}/manifest.json
105476
+ npx @bubblewrap/cli build`;
105477
+ }
105478
+ function capacitorConfig({ name, url: url2 }) {
105479
+ const host = hostFromUrl(url2);
105480
+ return `import type { CapacitorConfig } from "@capacitor/cli";
105481
+ const config: CapacitorConfig = {
105482
+ appId: "app.percher.yourapp",
105483
+ appName: ${JSON.stringify(name)},
105484
+ webDir: "dist",
105485
+ server: { url: "https://${host}", cleartext: false },
105486
+ };
105487
+ export default config;`;
105488
+ }
105489
+ function assetlinksJson({ packageName, sha256Fingerprint }) {
105490
+ const pkg = packageName.trim() || "app.percher.yourapp";
105491
+ const fp = sha256Fingerprint.trim() || "<your signing cert SHA-256>";
105492
+ return `[{
105493
+ "relation": ["delegate_permission/common.handle_all_urls"],
105494
+ "target": {
105495
+ "namespace": "android_app",
105496
+ "package_name": ${JSON.stringify(pkg)},
105497
+ "sha256_cert_fingerprints": [${JSON.stringify(fp)}]
105498
+ }
105499
+ }]`;
105500
+ }
105501
+ function appleAppSiteAssociation({ teamId, bundleId }) {
105502
+ const team = teamId.trim() || "TEAMID";
105503
+ const bundle = bundleId.trim() || "app.percher.yourapp";
105504
+ return `{
105505
+ "applinks": {
105506
+ "apps": [],
105507
+ "details": [{ "appID": ${JSON.stringify(`${team}.${bundle}`)}, "paths": ["*"] }]
105508
+ }
105509
+ }`;
105510
+ }
105511
+
105512
+ // ../core/dist/commands/appstore-kit.js
105513
+ var appstoreKitInputSchema = exports_external.object({
105514
+ name: exports_external.string().optional(),
105515
+ url: exports_external.string().optional(),
105516
+ packageName: exports_external.string().optional(),
105517
+ fingerprint: exports_external.string().optional(),
105518
+ teamId: exports_external.string().optional(),
105519
+ bundleId: exports_external.string().optional(),
105520
+ force: exports_external.boolean().optional(),
105521
+ outDir: exports_external.string().optional()
105522
+ });
105523
+ async function appstoreKit(ctx, input = {}) {
105524
+ const name = (input.name ?? readPercherTomlAppName(ctx.cwd) ?? basename(ctx.cwd) ?? "app").trim() || "app";
105525
+ const url2 = input.url?.trim() || `https://${name}.percher.run`;
105526
+ const themeHex = themeColorForToken(null);
105527
+ const base = resolve3(ctx.cwd, input.outDir ?? ".");
105528
+ const baseRel = relative(ctx.cwd, base);
105529
+ if (baseRel.startsWith("..") || isAbsolute(baseRel)) {
105530
+ throw new PercherCoreError("Output directory must stay inside the project", {
105531
+ code: "appstore-kit.bad-out-dir",
105532
+ hint: "Pass a path inside the current project (e.g. --out public), not an absolute or parent path."
105533
+ });
105534
+ }
105535
+ const files = [
105536
+ { rel: "manifest.json", content: manifestStarter({ name, themeColorHex: themeHex }) },
105537
+ { rel: "sw.js", content: serviceWorkerStarter() },
105538
+ { rel: "capacitor.config.ts", content: capacitorConfig({ name, url: url2 }) },
105539
+ {
105540
+ rel: ".well-known/assetlinks.json",
105541
+ content: assetlinksJson({
105542
+ packageName: input.packageName ?? "",
105543
+ sha256Fingerprint: input.fingerprint ?? ""
105544
+ })
105545
+ },
105546
+ {
105547
+ rel: ".well-known/apple-app-site-association",
105548
+ content: appleAppSiteAssociation({
105549
+ teamId: input.teamId ?? "",
105550
+ bundleId: input.bundleId ?? ""
105551
+ })
105552
+ }
105553
+ ];
105554
+ const written = [];
105555
+ const skipped = [];
105556
+ for (const f of files) {
105557
+ const abs = join5(base, ...f.rel.split("/"));
105558
+ const display = relative(ctx.cwd, abs).split(sep).join("/");
105559
+ if (existsSync3(abs) && !input.force) {
105560
+ skipped.push(display);
105561
+ continue;
105562
+ }
105563
+ mkdirSync3(dirname3(abs), { recursive: true });
105564
+ writeFileSync3(abs, `${f.content}
105565
+ `, "utf8");
105566
+ written.push(display);
105567
+ }
105568
+ return {
105569
+ appName: name,
105570
+ appUrl: url2,
105571
+ written,
105572
+ skipped,
105573
+ bubblewrapCommand: bubblewrapCommand({ url: url2 }),
105574
+ swRegistration: swRegistrationSnippet()
105575
+ };
105576
+ }
105402
105577
  // ../core/dist/commands/billing.js
105403
105578
  var billingUpgradeInputSchema = exports_external.object({
105404
105579
  plan: exports_external.enum(["starter", "maker", "pro"])
@@ -105422,22 +105597,22 @@ async function cacheReset(ctx, input = {}) {
105422
105597
  var capabilitiesInputSchema = exports_external.object({});
105423
105598
  // ../client/dist/abortable-sleep.js
105424
105599
  function abortableSleep(ms, signal) {
105425
- return new Promise((resolve3) => {
105600
+ return new Promise((resolve4) => {
105426
105601
  if (!signal) {
105427
- setTimeout(resolve3, ms);
105602
+ setTimeout(resolve4, ms);
105428
105603
  return;
105429
105604
  }
105430
105605
  if (signal.aborted) {
105431
- resolve3();
105606
+ resolve4();
105432
105607
  return;
105433
105608
  }
105434
105609
  const onAbort = () => {
105435
105610
  clearTimeout(t);
105436
- resolve3();
105611
+ resolve4();
105437
105612
  };
105438
105613
  const t = setTimeout(() => {
105439
105614
  signal.removeEventListener("abort", onAbort);
105440
- resolve3();
105615
+ resolve4();
105441
105616
  }, ms);
105442
105617
  signal.addEventListener("abort", onAbort, { once: true });
105443
105618
  });
@@ -105456,9 +105631,9 @@ function isAutoForwardedBuildKey(name) {
105456
105631
  return AUTO_FORWARD_PREFIXES.some((p) => name.startsWith(p));
105457
105632
  }
105458
105633
  // ../client/dist/config.js
105459
- import { existsSync as existsSync3, mkdirSync as mkdirSync3, readFileSync as readFileSync4, renameSync, writeFileSync as writeFileSync3 } from "node:fs";
105634
+ import { existsSync as existsSync4, mkdirSync as mkdirSync4, readFileSync as readFileSync4, renameSync, writeFileSync as writeFileSync4 } from "node:fs";
105460
105635
  import { homedir } from "node:os";
105461
- import { dirname as dirname3, join as join5 } from "node:path";
105636
+ import { dirname as dirname4, join as join6 } from "node:path";
105462
105637
  var DEFAULT_API_URL = "https://api.percher.run";
105463
105638
  function home() {
105464
105639
  return process.env.HOME ?? process.env.USERPROFILE ?? homedir();
@@ -105466,12 +105641,12 @@ function home() {
105466
105641
  function configPath() {
105467
105642
  const xdg = process.env.XDG_CONFIG_HOME;
105468
105643
  if (xdg)
105469
- return join5(xdg, "percher", "config.json");
105470
- return join5(home(), ".percher", "config.json");
105644
+ return join6(xdg, "percher", "config.json");
105645
+ return join6(home(), ".percher", "config.json");
105471
105646
  }
105472
105647
  function readFile2() {
105473
105648
  const p = configPath();
105474
- if (!existsSync3(p))
105649
+ if (!existsSync4(p))
105475
105650
  return {};
105476
105651
  try {
105477
105652
  const parsed = JSON.parse(readFileSync4(p, "utf8"));
@@ -105499,11 +105674,11 @@ function readAnonClaims() {
105499
105674
  }
105500
105675
  function saveConfig(partial2) {
105501
105676
  const p = configPath();
105502
- mkdirSync3(dirname3(p), { recursive: true });
105677
+ mkdirSync4(dirname4(p), { recursive: true });
105503
105678
  const current = readFile2();
105504
105679
  const merged = { ...current, ...partial2 };
105505
105680
  const tmp = `${p}.tmp-${process.pid}-${Date.now()}`;
105506
- writeFileSync3(tmp, JSON.stringify(merged, null, 2), "utf8");
105681
+ writeFileSync4(tmp, JSON.stringify(merged, null, 2), "utf8");
105507
105682
  renameSync(tmp, p);
105508
105683
  }
105509
105684
  function getAnonClaim(app) {
@@ -105907,6 +106082,15 @@ class AppsResource {
105907
106082
  unsetPreviewBranch(appRef) {
105908
106083
  return this.http.deleteJson(`/apps/${encodeURIComponent(appRef)}/preview-branch`);
105909
106084
  }
106085
+ listWellKnown(appRef) {
106086
+ return this.http.get(`/apps/${encodeURIComponent(appRef)}/well-known`);
106087
+ }
106088
+ setWellKnown(appRef, kind, content) {
106089
+ return this.http.put(`/apps/${encodeURIComponent(appRef)}/well-known/${encodeURIComponent(kind)}`, { content });
106090
+ }
106091
+ clearWellKnown(appRef, kind) {
106092
+ return this.http.deleteJson(`/apps/${encodeURIComponent(appRef)}/well-known/${encodeURIComponent(kind)}`);
106093
+ }
105910
106094
  setDescription(appRef, description) {
105911
106095
  return this.http.patch(`/apps/${encodeURIComponent(appRef)}/description`, {
105912
106096
  description
@@ -106582,17 +106766,17 @@ async function claim(ctx, input = {}) {
106582
106766
  };
106583
106767
  }
106584
106768
  // ../core/dist/commands/create.js
106585
- import { join as join7, resolve as resolve4 } from "node:path";
106769
+ import { join as join8, resolve as resolve5 } from "node:path";
106586
106770
 
106587
106771
  // ../core/dist/templates.js
106588
- import { existsSync as existsSync4, mkdirSync as mkdirSync4, readdirSync, readFileSync as readFileSync5, statSync, writeFileSync as writeFileSync4 } from "node:fs";
106589
- import { basename, join as join6, normalize, relative, resolve as resolve3 } from "node:path";
106772
+ import { existsSync as existsSync5, mkdirSync as mkdirSync5, readdirSync, readFileSync as readFileSync5, statSync, writeFileSync as writeFileSync5 } from "node:fs";
106773
+ import { basename as basename2, join as join7, normalize, relative as relative2, resolve as resolve4 } from "node:path";
106590
106774
  var __dirname = "C:\\dev\\Percher\\packages\\core\\dist";
106591
- var TEMPLATES_DIR = resolve3(import.meta.dirname ?? __dirname, "../templates");
106775
+ var TEMPLATES_DIR = resolve4(import.meta.dirname ?? __dirname, "../templates");
106592
106776
  var PLACEHOLDER = "__APP_NAME__";
106593
106777
  function listTemplates() {
106594
106778
  return readdirSync(TEMPLATES_DIR).filter((name) => {
106595
- const full = join6(TEMPLATES_DIR, name);
106779
+ const full = join7(TEMPLATES_DIR, name);
106596
106780
  return statSync(full).isDirectory();
106597
106781
  });
106598
106782
  }
@@ -106602,36 +106786,36 @@ function scaffoldTemplate(input) {
106602
106786
  if (!available.includes(template)) {
106603
106787
  throw new Error(`Unknown template "${template}". Available: ${available.join(", ")}`);
106604
106788
  }
106605
- const absTarget = resolve3(targetDir);
106606
- if (existsSync4(absTarget)) {
106789
+ const absTarget = resolve4(targetDir);
106790
+ if (existsSync5(absTarget)) {
106607
106791
  const entries = readdirSync(absTarget);
106608
106792
  if (entries.length > 0 && !force) {
106609
106793
  throw new Error(`Target directory "${absTarget}" is not empty. Use --force to overwrite.`);
106610
106794
  }
106611
106795
  }
106612
- const srcDir = join6(TEMPLATES_DIR, template);
106796
+ const srcDir = join7(TEMPLATES_DIR, template);
106613
106797
  const files = [];
106614
106798
  function copyDir(src, dest) {
106615
- mkdirSync4(dest, { recursive: true });
106799
+ mkdirSync5(dest, { recursive: true });
106616
106800
  for (const entry of readdirSync(src)) {
106617
- const srcPath = join6(src, entry);
106618
- const destPath = join6(dest, entry);
106619
- const rel = relative(absTarget, normalize(destPath));
106620
- if (rel.startsWith("..") || resolve3(destPath) === resolve3(absTarget, "..", basename(absTarget))) {
106801
+ const srcPath = join7(src, entry);
106802
+ const destPath = join7(dest, entry);
106803
+ const rel = relative2(absTarget, normalize(destPath));
106804
+ if (rel.startsWith("..") || resolve4(destPath) === resolve4(absTarget, "..", basename2(absTarget))) {
106621
106805
  throw new Error(`Template contains path traversal: ${entry}`);
106622
106806
  }
106623
106807
  if (statSync(srcPath).isDirectory()) {
106624
106808
  copyDir(srcPath, destPath);
106625
106809
  } else {
106626
- if (existsSync4(destPath) && !force) {
106810
+ if (existsSync5(destPath) && !force) {
106627
106811
  continue;
106628
106812
  }
106629
106813
  let content = readFileSync5(srcPath, "utf-8");
106630
106814
  content = content.replaceAll(PLACEHOLDER, appName);
106631
106815
  content = content.replace(/\r\n/g, `
106632
106816
  `);
106633
- writeFileSync4(destPath, content, "utf-8");
106634
- files.push(relative(absTarget, destPath).replace(/\\/g, "/"));
106817
+ writeFileSync5(destPath, content, "utf-8");
106818
+ files.push(relative2(absTarget, destPath).replace(/\\/g, "/"));
106635
106819
  }
106636
106820
  }
106637
106821
  }
@@ -106656,14 +106840,14 @@ async function create(ctx, input) {
106656
106840
  }
106657
106841
  let targetDir;
106658
106842
  if (input.directory) {
106659
- targetDir = resolve4(ctx.cwd, input.directory);
106660
- if (!targetDir.startsWith(resolve4(ctx.cwd))) {
106843
+ targetDir = resolve5(ctx.cwd, input.directory);
106844
+ if (!targetDir.startsWith(resolve5(ctx.cwd))) {
106661
106845
  throw new PercherCoreError("Directory must be within the current workspace", {
106662
106846
  code: "create.failed"
106663
106847
  });
106664
106848
  }
106665
106849
  } else {
106666
- targetDir = join7(ctx.cwd, input.name);
106850
+ targetDir = join8(ctx.cwd, input.name);
106667
106851
  }
106668
106852
  try {
106669
106853
  const result = scaffoldTemplate({
@@ -106759,7 +106943,7 @@ async function data(ctx, input = {}) {
106759
106943
  };
106760
106944
  }
106761
106945
  // ../core/dist/commands/data-export.js
106762
- import { resolve as resolve5 } from "node:path";
106946
+ import { resolve as resolve6 } from "node:path";
106763
106947
  var dataExportInputSchema = exports_external.object({
106764
106948
  app: exports_external.string().optional().describe("App name or id. Defaults to the app in percher.toml."),
106765
106949
  out: exports_external.string().optional().describe("Output file path. Defaults to ./<app>-pb-<timestamp>.tar.gz in the current directory.")
@@ -106775,7 +106959,7 @@ async function dataExport(ctx, input) {
106775
106959
  ctx.status?.(`Exporting ${appName} data...`);
106776
106960
  const stamp = new Date().toISOString().replace(/[:.]/g, "-").slice(0, 19);
106777
106961
  const fileName = input.out ?? `${appName}-pb-${stamp}.tar.gz`;
106778
- const path = resolve5(ctx.cwd, fileName);
106962
+ const path = resolve6(ctx.cwd, fileName);
106779
106963
  const res = await ctx.client.apps.streamDataExport(appName);
106780
106964
  const bytes = await writeResponseToFile(res, path);
106781
106965
  return {
@@ -106871,14 +107055,14 @@ async function deploysInspect(ctx, input) {
106871
107055
  return { deploy, buildLog };
106872
107056
  }
106873
107057
  // ../core/dist/commands/dev.js
106874
- import { existsSync as existsSync7 } from "node:fs";
106875
- import { join as join10 } from "node:path";
107058
+ import { existsSync as existsSync8 } from "node:fs";
107059
+ import { join as join11 } from "node:path";
106876
107060
 
106877
107061
  // ../core/dist/tarball.js
106878
107062
  var import_ignore = __toESM(require_ignore(), 1);
106879
107063
  import { createHash as createHash2 } from "node:crypto";
106880
- import { existsSync as existsSync5, readdirSync as readdirSync2, readFileSync as readFileSync6, statSync as statSync2 } from "node:fs";
106881
- import { join as join8, relative as relative2, sep } from "node:path";
107064
+ import { existsSync as existsSync6, readdirSync as readdirSync2, readFileSync as readFileSync6, statSync as statSync2 } from "node:fs";
107065
+ import { join as join9, relative as relative3, sep as sep2 } from "node:path";
106882
107066
  import { Readable } from "node:stream";
106883
107067
  import { createGzip } from "node:zlib";
106884
107068
 
@@ -106904,8 +107088,8 @@ var DEFAULT_IGNORE = [
106904
107088
  function* walk(dir, baseDir, ig) {
106905
107089
  const entries = readdirSync2(dir);
106906
107090
  for (const name of entries) {
106907
- const full = join8(dir, name);
106908
- const rel = relative2(baseDir, full).split(sep).join("/");
107091
+ const full = join9(dir, name);
107092
+ const rel = relative3(baseDir, full).split(sep2).join("/");
106909
107093
  if (ig.ignores(rel))
106910
107094
  continue;
106911
107095
  const stats = statSync2(full);
@@ -106921,15 +107105,15 @@ function* walk(dir, baseDir, ig) {
106921
107105
  async function createTarball(options) {
106922
107106
  const ig = import_ignore.default();
106923
107107
  ig.add(DEFAULT_IGNORE);
106924
- const gitignorePath = join8(options.cwd, ".gitignore");
106925
- if (existsSync5(gitignorePath)) {
107108
+ const gitignorePath = join9(options.cwd, ".gitignore");
107109
+ if (existsSync6(gitignorePath)) {
106926
107110
  ig.add(readFileSync6(gitignorePath, "utf8"));
106927
107111
  }
106928
107112
  if (options.extraIgnore)
106929
107113
  ig.add(options.extraIgnore);
106930
107114
  const fileBuffers = [];
106931
107115
  for (const rel of walk(options.cwd, options.cwd, ig)) {
106932
- const data2 = readFileSync6(join8(options.cwd, rel));
107116
+ const data2 = readFileSync6(join9(options.cwd, rel));
106933
107117
  fileBuffers.push({ path: rel, size: data2.length, data: data2 });
106934
107118
  }
106935
107119
  fileBuffers.sort((a, b) => a.path < b.path ? -1 : a.path > b.path ? 1 : 0);
@@ -106948,8 +107132,8 @@ async function createTarball(options) {
106948
107132
  const pack = $pack();
106949
107133
  (async () => {
106950
107134
  for (const file2 of fileBuffers) {
106951
- await new Promise((resolve6, reject) => {
106952
- pack.entry({ name: file2.path, size: file2.data.length }, file2.data, (err) => err ? reject(err) : resolve6());
107135
+ await new Promise((resolve7, reject) => {
107136
+ pack.entry({ name: file2.path, size: file2.data.length }, file2.data, (err) => err ? reject(err) : resolve7());
106953
107137
  });
106954
107138
  }
106955
107139
  pack.finalize();
@@ -106969,8 +107153,8 @@ async function createTarball(options) {
106969
107153
 
106970
107154
  // ../core/dist/watcher.js
106971
107155
  var import_ignore2 = __toESM(require_ignore(), 1);
106972
- import { existsSync as existsSync6, readFileSync as readFileSync7, watch } from "node:fs";
106973
- import { join as join9, sep as sep2 } from "node:path";
107156
+ import { existsSync as existsSync7, readFileSync as readFileSync7, watch } from "node:fs";
107157
+ import { join as join10, sep as sep3 } from "node:path";
106974
107158
  var DEFAULT_IGNORE2 = [
106975
107159
  "node_modules",
106976
107160
  ".git",
@@ -106990,8 +107174,8 @@ function createWatcher(options) {
106990
107174
  const debounceMs = options.debounceMs ?? 500;
106991
107175
  const ig = import_ignore2.default();
106992
107176
  ig.add(DEFAULT_IGNORE2);
106993
- const gitignorePath = join9(options.cwd, ".gitignore");
106994
- if (existsSync6(gitignorePath)) {
107177
+ const gitignorePath = join10(options.cwd, ".gitignore");
107178
+ if (existsSync7(gitignorePath)) {
106995
107179
  ig.add(readFileSync7(gitignorePath, "utf8"));
106996
107180
  }
106997
107181
  if (options.extraIgnore)
@@ -107001,7 +107185,7 @@ function createWatcher(options) {
107001
107185
  const fsWatcher = watch(options.cwd, { recursive: true }, (_event, filename) => {
107002
107186
  if (!filename)
107003
107187
  return;
107004
- const rel = filename.split(sep2).join("/");
107188
+ const rel = filename.split(sep3).join("/");
107005
107189
  if (ig.ignores(rel))
107006
107190
  return;
107007
107191
  pending.add(rel);
@@ -107030,8 +107214,8 @@ var devInputSchema = exports_external.object({
107030
107214
  app: exports_external.string().optional()
107031
107215
  });
107032
107216
  async function loadConfig2(ctx, appOverride) {
107033
- const tomlPath = join10(ctx.cwd, "percher.toml");
107034
- if (!existsSync7(tomlPath)) {
107217
+ const tomlPath = join11(ctx.cwd, "percher.toml");
107218
+ if (!existsSync8(tomlPath)) {
107035
107219
  throw new PercherCoreError("No percher.toml found. Run: percher init", {
107036
107220
  code: "dev.no-app",
107037
107221
  hint: "Create a percher.toml first with `percher init`."
@@ -107185,12 +107369,12 @@ async function dev(ctx, input, callbacks) {
107185
107369
  }
107186
107370
  });
107187
107371
  try {
107188
- await new Promise((resolve6) => {
107372
+ await new Promise((resolve7) => {
107189
107373
  if (callbacks.signal.aborted) {
107190
- resolve6();
107374
+ resolve7();
107191
107375
  return;
107192
107376
  }
107193
- callbacks.signal.addEventListener("abort", () => resolve6(), { once: true });
107377
+ callbacks.signal.addEventListener("abort", () => resolve7(), { once: true });
107194
107378
  });
107195
107379
  } finally {
107196
107380
  logStream.ctrl?.abort();
@@ -107225,8 +107409,8 @@ async function diff(ctx, input = {}) {
107225
107409
  });
107226
107410
  }
107227
107411
  // ../core/dist/commands/doctor.js
107228
- import { existsSync as existsSync8 } from "node:fs";
107229
- import { join as join12 } from "node:path";
107412
+ import { existsSync as existsSync9 } from "node:fs";
107413
+ import { join as join13 } from "node:path";
107230
107414
 
107231
107415
  // ../core/dist/error-classifier.js
107232
107416
  function extractEnvVarsFromLog(combined) {
@@ -107771,7 +107955,7 @@ function recoveryFromErrorClass(errorClass, failure = {}) {
107771
107955
  }
107772
107956
 
107773
107957
  // ../core/dist/commands/publish-failure.js
107774
- import { join as join11 } from "node:path";
107958
+ import { join as join12 } from "node:path";
107775
107959
 
107776
107960
  // ../core/dist/structured-error-codes.js
107777
107961
  var MAPPINGS = {
@@ -107849,7 +108033,7 @@ function trimMessage(raw) {
107849
108033
 
107850
108034
  // ../core/dist/commands/publish-failure.js
107851
108035
  function tomlPathFor(cwd) {
107852
- return join11(cwd, "percher.toml");
108036
+ return join12(cwd, "percher.toml");
107853
108037
  }
107854
108038
  async function buildFailureError(ctx, app, deployment, signal) {
107855
108039
  let buildLogTail;
@@ -108192,8 +108376,8 @@ async function doctor(ctx, input = {}) {
108192
108376
  });
108193
108377
  return summarize(checks3, { appProvided: !!input.app });
108194
108378
  }
108195
- const tomlPath = join12(ctx.cwd, "percher.toml");
108196
- const tomlExists = existsSync8(tomlPath);
108379
+ const tomlPath = join13(ctx.cwd, "percher.toml");
108380
+ const tomlExists = existsSync9(tomlPath);
108197
108381
  let tomlValid = false;
108198
108382
  if (!tomlExists) {
108199
108383
  checks3.push({
@@ -108973,7 +109157,7 @@ async function envList(ctx, input = {}) {
108973
109157
  import { randomUUID } from "node:crypto";
108974
109158
  import { createWriteStream } from "node:fs";
108975
109159
  import { rename, unlink } from "node:fs/promises";
108976
- import { isAbsolute, resolve as resolvePath } from "node:path";
109160
+ import { isAbsolute as isAbsolute2, resolve as resolvePath } from "node:path";
108977
109161
  var exportInputSchema = exports_external.object({
108978
109162
  app: exports_external.string().optional(),
108979
109163
  out: exports_external.string().optional(),
@@ -108997,7 +109181,7 @@ async function streamToFile(outPath, source) {
108997
109181
  const tmpPath = `${outPath}.part-${randomUUID()}`;
108998
109182
  const out = createWriteStream(tmpPath);
108999
109183
  const reader = source.getReader();
109000
- const closed = new Promise((resolve6) => out.once("close", () => resolve6()));
109184
+ const closed = new Promise((resolve7) => out.once("close", () => resolve7()));
109001
109185
  let onWriteError;
109002
109186
  const writeFailed = new Promise((_, reject) => {
109003
109187
  onWriteError = reject;
@@ -109014,14 +109198,14 @@ async function streamToFile(outPath, source) {
109014
109198
  bytes += value.byteLength;
109015
109199
  if (!out.write(value)) {
109016
109200
  await Promise.race([
109017
- new Promise((resolve6) => out.once("drain", resolve6)),
109201
+ new Promise((resolve7) => out.once("drain", resolve7)),
109018
109202
  writeFailed
109019
109203
  ]);
109020
109204
  }
109021
109205
  }
109022
109206
  }
109023
- await new Promise((resolve6, reject) => {
109024
- out.end((err) => err ? reject(err) : resolve6());
109207
+ await new Promise((resolve7, reject) => {
109208
+ out.end((err) => err ? reject(err) : resolve7());
109025
109209
  });
109026
109210
  await closed;
109027
109211
  } catch (err) {
@@ -109039,7 +109223,7 @@ async function streamToFile(outPath, source) {
109039
109223
  return { bytes };
109040
109224
  }
109041
109225
  function resolveOutPath(ctxCwd, filename) {
109042
- if (isAbsolute(filename))
109226
+ if (isAbsolute2(filename))
109043
109227
  return filename;
109044
109228
  return resolvePath(ctxCwd, filename);
109045
109229
  }
@@ -109100,8 +109284,8 @@ var forgejoSetupWebhookInputSchema = exports_external.object({
109100
109284
  app: exports_external.string().optional().describe("App name (overrides percher.toml)")
109101
109285
  });
109102
109286
  // ../core/dist/commands/generate.js
109103
- import { existsSync as existsSync9, mkdirSync as mkdirSync5, writeFileSync as writeFileSync5 } from "node:fs";
109104
- import { join as join13 } from "node:path";
109287
+ import { existsSync as existsSync10, mkdirSync as mkdirSync6, writeFileSync as writeFileSync6 } from "node:fs";
109288
+ import { join as join14 } from "node:path";
109105
109289
  var generateInputSchema = exports_external.object({
109106
109290
  cwd: exports_external.string().optional()
109107
109291
  });
@@ -109187,8 +109371,8 @@ function generateTypeScript(config2) {
109187
109371
  }
109188
109372
  async function generate(ctx, input = {}) {
109189
109373
  const cwd = input.cwd ?? ctx.cwd;
109190
- const tomlPath = join13(cwd, "percher.toml");
109191
- if (!existsSync9(tomlPath)) {
109374
+ const tomlPath = join14(cwd, "percher.toml");
109375
+ if (!existsSync10(tomlPath)) {
109192
109376
  throw new PercherCoreError("No percher.toml found", {
109193
109377
  code: "dev.no-app",
109194
109378
  hint: "Run percher init first."
@@ -109197,14 +109381,14 @@ async function generate(ctx, input = {}) {
109197
109381
  const config2 = await parseFile(tomlPath);
109198
109382
  const files = [];
109199
109383
  const envExample = generateEnvExample(config2);
109200
- writeFileSync5(join13(cwd, ".env.example"), envExample);
109384
+ writeFileSync6(join14(cwd, ".env.example"), envExample);
109201
109385
  files.push(".env.example");
109202
109386
  const tsTypes = generateTypeScript(config2);
109203
- writeFileSync5(join13(cwd, "percher.generated.d.ts"), tsTypes);
109387
+ writeFileSync6(join14(cwd, "percher.generated.d.ts"), tsTypes);
109204
109388
  files.push("percher.generated.d.ts");
109205
109389
  const agentInstructions = generateAgentInstructions(config2);
109206
- mkdirSync5(join13(cwd, ".percher"), { recursive: true });
109207
- writeFileSync5(join13(cwd, ".percher", "agent-instructions.md"), agentInstructions);
109390
+ mkdirSync6(join14(cwd, ".percher"), { recursive: true });
109391
+ writeFileSync6(join14(cwd, ".percher", "agent-instructions.md"), agentInstructions);
109208
109392
  files.push(".percher/agent-instructions.md");
109209
109393
  return { files };
109210
109394
  }
@@ -109353,8 +109537,8 @@ async function githubSetupWebhook(ctx, input) {
109353
109537
  };
109354
109538
  }
109355
109539
  // ../core/dist/commands/import-project.js
109356
- import { existsSync as existsSync10, readFileSync as readFileSync8, writeFileSync as writeFileSync6 } from "node:fs";
109357
- import { join as join14 } from "node:path";
109540
+ import { existsSync as existsSync11, readFileSync as readFileSync8, writeFileSync as writeFileSync7 } from "node:fs";
109541
+ import { join as join15 } from "node:path";
109358
109542
 
109359
109543
  // ../core/dist/static-docker.js
109360
109544
  var STATIC_DOCKER_PORT = 8080;
@@ -109415,9 +109599,9 @@ var importInputSchema = exports_external.object({
109415
109599
  app: exports_external.string().optional().describe("App name to import into")
109416
109600
  });
109417
109601
  function detectProvider(cwd) {
109418
- if (existsSync10(join14(cwd, "vercel.json")))
109602
+ if (existsSync11(join15(cwd, "vercel.json")))
109419
109603
  return "vercel";
109420
- if (existsSync10(join14(cwd, "netlify.toml")))
109604
+ if (existsSync11(join15(cwd, "netlify.toml")))
109421
109605
  return "netlify";
109422
109606
  return null;
109423
109607
  }
@@ -109435,7 +109619,7 @@ function mapVercelFramework(framework) {
109435
109619
  return map2[framework ?? ""] ?? { runtime: "node" };
109436
109620
  }
109437
109621
  function parseVercelJson(cwd) {
109438
- const raw = readFileSync8(join14(cwd, "vercel.json"), "utf-8");
109622
+ const raw = readFileSync8(join15(cwd, "vercel.json"), "utf-8");
109439
109623
  const config2 = JSON.parse(raw);
109440
109624
  const warnings = [];
109441
109625
  const envVars = [];
@@ -109489,12 +109673,12 @@ health = "/api/health"
109489
109673
  return { toml, warnings, envVars, staticBuild };
109490
109674
  }
109491
109675
  function parseNetlifyToml(cwd) {
109492
- const raw = readFileSync8(join14(cwd, "netlify.toml"), "utf-8");
109676
+ const raw = readFileSync8(join15(cwd, "netlify.toml"), "utf-8");
109493
109677
  const warnings = [];
109494
109678
  const envVars = [];
109495
109679
  const buildCommand = raw.match(/command\s*=\s*"([^"]+)"/)?.[1] ?? "bun run build";
109496
109680
  const publishDir = raw.match(/publish\s*=\s*"([^"]+)"/)?.[1] ?? "dist";
109497
- const hasPackageJson = existsSync10(join14(cwd, "package.json"));
109681
+ const hasPackageJson = existsSync11(join15(cwd, "package.json"));
109498
109682
  const looksLikeStaticOutput = publishDir === "dist" || publishDir === "build" || publishDir === "public";
109499
109683
  let toml = `[app]
109500
109684
  name = "imported-app"
@@ -109565,11 +109749,11 @@ async function importProject(ctx, input = {}) {
109565
109749
  hint: "Supported providers: vercel, netlify"
109566
109750
  });
109567
109751
  }
109568
- const tomlPath = join14(ctx.cwd, "percher.toml");
109569
- if (existsSync10(tomlPath)) {
109752
+ const tomlPath = join15(ctx.cwd, "percher.toml");
109753
+ if (existsSync11(tomlPath)) {
109570
109754
  result.warnings.unshift("percher.toml already exists — overwriting with imported config");
109571
109755
  }
109572
- writeFileSync6(tomlPath, result.toml);
109756
+ writeFileSync7(tomlPath, result.toml);
109573
109757
  const scaffoldedFiles = [];
109574
109758
  if (result.staticBuild) {
109575
109759
  const targets = [
@@ -109583,12 +109767,12 @@ async function importProject(ctx, input = {}) {
109583
109767
  }
109584
109768
  ];
109585
109769
  for (const { name, content } of targets) {
109586
- const target = join14(ctx.cwd, name);
109587
- if (existsSync10(target)) {
109770
+ const target = join15(ctx.cwd, name);
109771
+ if (existsSync11(target)) {
109588
109772
  result.warnings.push(`${name} already exists — left untouched. The imported config expects a multi-stage static build; merge by hand if needed.`);
109589
109773
  continue;
109590
109774
  }
109591
- writeFileSync6(target, content, "utf-8");
109775
+ writeFileSync7(target, content, "utf-8");
109592
109776
  scaffoldedFiles.push(name);
109593
109777
  }
109594
109778
  }
@@ -109601,14 +109785,14 @@ async function importProject(ctx, input = {}) {
109601
109785
  };
109602
109786
  }
109603
109787
  // ../core/dist/commands/init.js
109604
- import { existsSync as existsSync12, writeFileSync as writeFileSync7 } from "node:fs";
109605
- import { basename as basename2, join as join16 } from "node:path";
109788
+ import { existsSync as existsSync13, writeFileSync as writeFileSync8 } from "node:fs";
109789
+ import { basename as basename3, join as join17 } from "node:path";
109606
109790
 
109607
109791
  // ../core/dist/detect.js
109608
- import { existsSync as existsSync11, readFileSync as readFileSync9 } from "node:fs";
109609
- import { join as join15 } from "node:path";
109792
+ import { existsSync as existsSync12, readFileSync as readFileSync9 } from "node:fs";
109793
+ import { join as join16 } from "node:path";
109610
109794
  function exists(dir, ...names) {
109611
- return names.some((n) => existsSync11(join15(dir, n)));
109795
+ return names.some((n) => existsSync12(join16(dir, n)));
109612
109796
  }
109613
109797
  function readJson(path) {
109614
109798
  try {
@@ -109637,8 +109821,8 @@ function detectDataMode(pkg, cwd) {
109637
109821
  return { mode: "none" };
109638
109822
  }
109639
109823
  async function detectFramework(cwd) {
109640
- const pkgPath = join15(cwd, "package.json");
109641
- const pkg = existsSync11(pkgPath) ? readJson(pkgPath) : null;
109824
+ const pkgPath = join16(cwd, "package.json");
109825
+ const pkg = existsSync12(pkgPath) ? readJson(pkgPath) : null;
109642
109826
  if (exists(cwd, "Dockerfile")) {
109643
109827
  return {
109644
109828
  runtime: "docker",
@@ -109740,7 +109924,7 @@ async function detectFramework(cwd) {
109740
109924
  }
109741
109925
  const hasPython = exists(cwd, "requirements.txt", "pyproject.toml");
109742
109926
  if (hasPython) {
109743
- if (existsSync11(join15(cwd, "manage.py"))) {
109927
+ if (existsSync12(join16(cwd, "manage.py"))) {
109744
109928
  return {
109745
109929
  runtime: "python",
109746
109930
  framework: "django",
@@ -109748,7 +109932,7 @@ async function detectFramework(cwd) {
109748
109932
  data: detectDataMode(pkg, cwd)
109749
109933
  };
109750
109934
  }
109751
- const mainPy = existsSync11(join15(cwd, "main.py")) ? readFileSync9(join15(cwd, "main.py"), "utf8") : "";
109935
+ const mainPy = existsSync12(join16(cwd, "main.py")) ? readFileSync9(join16(cwd, "main.py"), "utf8") : "";
109752
109936
  if (/FastAPI\s*\(/.test(mainPy) || /from\s+fastapi/.test(mainPy)) {
109753
109937
  return {
109754
109938
  runtime: "python",
@@ -109757,7 +109941,7 @@ async function detectFramework(cwd) {
109757
109941
  data: detectDataMode(pkg, cwd)
109758
109942
  };
109759
109943
  }
109760
- const appPy = existsSync11(join15(cwd, "app.py")) ? readFileSync9(join15(cwd, "app.py"), "utf8") : "";
109944
+ const appPy = existsSync12(join16(cwd, "app.py")) ? readFileSync9(join16(cwd, "app.py"), "utf8") : "";
109761
109945
  if (/Flask\s*\(/.test(appPy) || /from\s+flask/.test(appPy)) {
109762
109946
  return {
109763
109947
  runtime: "python",
@@ -109772,7 +109956,7 @@ async function detectFramework(cwd) {
109772
109956
  data: detectDataMode(pkg, cwd)
109773
109957
  };
109774
109958
  }
109775
- if (existsSync11(join15(cwd, "index.html"))) {
109959
+ if (existsSync12(join16(cwd, "index.html"))) {
109776
109960
  return { runtime: "static" };
109777
109961
  }
109778
109962
  return null;
@@ -109822,8 +110006,8 @@ function scanEnvVars(_cwd) {
109822
110006
  return {};
109823
110007
  }
109824
110008
  async function init(ctx, input = {}) {
109825
- const path = join16(ctx.cwd, "percher.toml");
109826
- const exists2 = existsSync12(path);
110009
+ const path = join17(ctx.cwd, "percher.toml");
110010
+ const exists2 = existsSync13(path);
109827
110011
  if (exists2 && !input.force) {
109828
110012
  throw new PercherCoreError("percher.toml already exists", {
109829
110013
  code: "init.exists",
@@ -109836,7 +110020,7 @@ async function init(ctx, input = {}) {
109836
110020
  if (input.name) {
109837
110021
  name = input.name;
109838
110022
  } else {
109839
- const suggestion = generateName(basename2(ctx.cwd));
110023
+ const suggestion = generateName(basename3(ctx.cwd));
109840
110024
  const interactive = input.interactive ?? detectInteractive();
109841
110025
  if (isSuspiciousAutoName(suggestion) && interactive) {
109842
110026
  const answer = (await ctx.prompt(`Suggested app name: '${suggestion}'. Press Enter to accept, or type a different name: `, { default: suggestion })).trim();
@@ -109870,7 +110054,7 @@ async function init(ctx, input = {}) {
109870
110054
  if (Object.keys(envVars).length > 0) {
109871
110055
  config2.env = envVars;
109872
110056
  }
109873
- writeFileSync7(path, serialize(config2), "utf8");
110057
+ writeFileSync8(path, serialize(config2), "utf8");
109874
110058
  const scaffoldedFiles = [];
109875
110059
  if (detected?.staticBuild) {
109876
110060
  const targets = [
@@ -109886,10 +110070,10 @@ async function init(ctx, input = {}) {
109886
110070
  }
109887
110071
  ];
109888
110072
  for (const { name: name2, content } of targets) {
109889
- const target = join16(ctx.cwd, name2);
109890
- if (existsSync12(target) && !input.force)
110073
+ const target = join17(ctx.cwd, name2);
110074
+ if (existsSync13(target) && !input.force)
109891
110075
  continue;
109892
- writeFileSync7(target, content, "utf8");
110076
+ writeFileSync8(target, content, "utf8");
109893
110077
  scaffoldedFiles.push(name2);
109894
110078
  }
109895
110079
  }
@@ -109973,7 +110157,7 @@ async function login(ctx, input = {}) {
109973
110157
  return validateAndPersist(ctx, input.apiUrl, result.token);
109974
110158
  }
109975
110159
  if (code.interval > 0) {
109976
- await new Promise((resolve6) => setTimeout(resolve6, code.interval * 1000));
110160
+ await new Promise((resolve7) => setTimeout(resolve7, code.interval * 1000));
109977
110161
  }
109978
110162
  }
109979
110163
  throw new PercherCoreError("Login timed out. Re-run `percher login`.", {
@@ -110890,16 +111074,277 @@ function collectWarnings2(collections, rlsPolicies, unsupported) {
110890
111074
  }
110891
111075
  // ../core/dist/commands/migrate-supabase-rewrite.js
110892
111076
  import { mkdir as mkdir3, writeFile as writeFile3 } from "node:fs/promises";
110893
- import { dirname as dirname5, join as join18, relative as relative4, resolve as resolve7 } from "node:path";
111077
+ import { dirname as dirname6, join as join20, relative as relative6, resolve as resolve9, sep as sep5 } from "node:path";
110894
111078
 
110895
- // ../core/dist/commands/migrate-supabase-walker.js
110896
- var import_ignore3 = __toESM(require_ignore(), 1);
110897
- import { mkdir as mkdir2, readdir, readFile as readFile3, stat, writeFile as writeFile2 } from "node:fs/promises";
110898
- import { dirname as dirname4, isAbsolute as isAbsolute2, join as join17, relative as relative3, resolve as resolve6, sep as sep3 } from "node:path";
111079
+ // ../core/dist/commands/migrate-supabase-recipes.js
111080
+ var AUTH_RECIPES = {
111081
+ "auth.getSession": {
111082
+ title: "getSession → pb.authStore",
111083
+ 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)."
111084
+ },
111085
+ "auth.getClaims": {
111086
+ title: "getClaims → pb.authStore.record",
111087
+ 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."
111088
+ },
111089
+ "auth.getUser": {
111090
+ title: "getUser → pb.authStore.record",
111091
+ 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."
111092
+ },
111093
+ "auth.signInWithOtp": {
111094
+ title: "signInWithOtp → requestOTP + authWithOTP",
111095
+ 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."
111096
+ },
111097
+ "auth.verifyOtp": {
111098
+ title: "verifyOtp → authWithOTP",
111099
+ 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."
111100
+ },
111101
+ "auth.resetPasswordForEmail": {
111102
+ title: "resetPasswordForEmail → requestPasswordReset",
111103
+ 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)."
111104
+ },
111105
+ "auth.updateUser": {
111106
+ title: "updateUser → collection('users').update",
111107
+ 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."
111108
+ },
111109
+ "auth.refreshSession": {
111110
+ title: "refreshSession → authRefresh",
111111
+ 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."
111112
+ },
111113
+ "auth.onAuthStateChange": {
111114
+ title: "onAuthStateChange → pb.authStore.onChange",
111115
+ 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."
111116
+ }
111117
+ };
111118
+ function recipeFor(pattern) {
111119
+ return AUTH_RECIPES[pattern] ?? null;
111120
+ }
111121
+ var GENERAL_AUTH_RECIPES = [
111122
+ {
111123
+ title: "Route guards → pb.authStore.isValid",
111124
+ 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."
111125
+ }
111126
+ ];
111127
+ function renderRecipesSection(patterns2) {
111128
+ const seen = new Set;
111129
+ const recipes = [];
111130
+ for (const pattern of patterns2) {
111131
+ const recipe = recipeFor(pattern);
111132
+ if (recipe && !seen.has(recipe.title)) {
111133
+ seen.add(recipe.title);
111134
+ recipes.push(recipe);
111135
+ }
111136
+ }
111137
+ if (recipes.length === 0)
111138
+ return [];
111139
+ const lines = [];
111140
+ lines.push("## Recipes — Supabase auth → PocketBase");
111141
+ lines.push("");
111142
+ 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/.");
111143
+ lines.push("");
111144
+ for (const recipe of [...recipes, ...GENERAL_AUTH_RECIPES]) {
111145
+ lines.push(`### ${recipe.title}`);
111146
+ lines.push("");
111147
+ lines.push(recipe.recipe);
111148
+ lines.push("");
111149
+ }
111150
+ return lines;
111151
+ }
110899
111152
 
110900
- // ../core/dist/commands/migrate-supabase-sdk.js
111153
+ // ../core/dist/commands/migrate-supabase-scaffold.js
110901
111154
  var import_jscodeshift = __toESM(require_core3(), 1);
111155
+ import { posix } from "node:path";
110902
111156
  var tsx = import_jscodeshift.default.withParser("tsx");
111157
+ var CLIENT_FACTORIES = new Set(["createClient", "createBrowserClient", "createServerClient"]);
111158
+ function scaffoldPocketBaseClient(input) {
111159
+ const pbName = input.pbIdentifier ?? "pb";
111160
+ const codeFiles = input.files.filter((f) => f.kind === "code");
111161
+ const flags = [];
111162
+ for (const file2 of codeFiles) {
111163
+ if (isSupabaseClientModule(file2.source)) {
111164
+ flags.push({
111165
+ file: file2.relativePath,
111166
+ kind: "manual_review",
111167
+ pattern: "supabase.client_module",
111168
+ 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."
111169
+ });
111170
+ }
111171
+ }
111172
+ const existing = codeFiles.find((f) => exportsBinding(f.rewritten, pbName));
111173
+ let targetRelNoExt;
111174
+ let clientModule = null;
111175
+ let skippedReason;
111176
+ if (existing) {
111177
+ targetRelNoExt = stripExt(existing.relativePath);
111178
+ skippedReason = "pb_client_exists";
111179
+ } else {
111180
+ const ext = pickExtension(codeFiles);
111181
+ const baseNoExt = pickModuleBase(codeFiles);
111182
+ const targetRel = `${baseNoExt}.${ext}`;
111183
+ if (input.files.some((f) => f.relativePath === targetRel)) {
111184
+ flags.push({
111185
+ file: targetRel,
111186
+ kind: "manual_review",
111187
+ pattern: "scaffold.path_taken",
111188
+ note: `Couldn't auto-create a PocketBase client — \`${targetRel}\` already exists. Create one that exports \`${pbName}\` and import it in the rewritten files.`
111189
+ });
111190
+ return {
111191
+ clientModule: null,
111192
+ importInsertions: new Map,
111193
+ flags,
111194
+ skippedReason: "target_path_taken"
111195
+ };
111196
+ }
111197
+ targetRelNoExt = baseNoExt;
111198
+ clientModule = { relativePath: targetRel, content: renderClientModule(pbName, codeFiles) };
111199
+ }
111200
+ const importInsertions = new Map;
111201
+ const changed = new Set(input.changedRelPaths);
111202
+ for (const file2 of codeFiles) {
111203
+ if (!changed.has(file2.relativePath))
111204
+ continue;
111205
+ if (file2.relativePath === clientModule?.relativePath)
111206
+ continue;
111207
+ if (!referencesUnboundIdentifier(file2.rewritten, pbName))
111208
+ continue;
111209
+ const importPath = computeImportPath(file2.relativePath, targetRelNoExt);
111210
+ const next = insertNamedImport(file2.rewritten, pbName, importPath);
111211
+ if (next !== null)
111212
+ importInsertions.set(file2.relativePath, next);
111213
+ }
111214
+ return { clientModule, importInsertions, flags, ...skippedReason ? { skippedReason } : {} };
111215
+ }
111216
+ function renderClientModule(pbName, codeFiles) {
111217
+ const usesViteEnv = codeFiles.some((f) => f.source.includes("import.meta.env"));
111218
+ const accessor = usesViteEnv ? "import.meta.env.VITE_POCKETBASE_URL" : "process.env.POCKETBASE_URL";
111219
+ return [
111220
+ 'import PocketBase from "pocketbase";',
111221
+ "",
111222
+ "// Percher injects the PocketBase URL at deploy time. This is a working",
111223
+ "// default — adjust the URL accessor to match your framework if needed.",
111224
+ `export const ${pbName} = new PocketBase(${accessor});`,
111225
+ ""
111226
+ ].join(`
111227
+ `);
111228
+ }
111229
+ function pickExtension(codeFiles) {
111230
+ return codeFiles.some((f) => f.relativePath.endsWith(".ts") || f.relativePath.endsWith(".tsx")) ? "ts" : "js";
111231
+ }
111232
+ function pickModuleBase(codeFiles) {
111233
+ const hasSrc = codeFiles.some((f) => f.relativePath.startsWith("src/"));
111234
+ return hasSrc ? "src/lib/pocketbase" : "lib/pocketbase";
111235
+ }
111236
+ function stripExt(relPath) {
111237
+ const dot = relPath.lastIndexOf(".");
111238
+ return dot > relPath.lastIndexOf("/") ? relPath.slice(0, dot) : relPath;
111239
+ }
111240
+ function computeImportPath(fromFileRel, targetRelNoExt) {
111241
+ let rel = posix.relative(posix.dirname(fromFileRel), targetRelNoExt);
111242
+ if (!rel.startsWith("."))
111243
+ rel = `./${rel}`;
111244
+ return rel;
111245
+ }
111246
+ function insertNamedImport(source, name, spec) {
111247
+ let root;
111248
+ try {
111249
+ root = tsx(source);
111250
+ } catch {
111251
+ return null;
111252
+ }
111253
+ const decl = import_jscodeshift.default.importDeclaration([import_jscodeshift.default.importSpecifier(import_jscodeshift.default.identifier(name))], import_jscodeshift.default.literal(spec));
111254
+ const program = root.get().node.program;
111255
+ program.body.unshift(decl);
111256
+ return root.toSource({ quote: "double" });
111257
+ }
111258
+ function referencesUnboundIdentifier(source, name) {
111259
+ let root;
111260
+ try {
111261
+ root = tsx(source);
111262
+ } catch {
111263
+ return false;
111264
+ }
111265
+ let declared = false;
111266
+ root.find(import_jscodeshift.default.ImportDeclaration).forEach((p) => {
111267
+ for (const spec of p.node.specifiers ?? []) {
111268
+ if (spec.local?.name === name)
111269
+ declared = true;
111270
+ }
111271
+ });
111272
+ root.find(import_jscodeshift.default.VariableDeclarator).forEach((p) => {
111273
+ if (p.node.id.type === "Identifier" && p.node.id.name === name) {
111274
+ declared = true;
111275
+ }
111276
+ });
111277
+ let used = false;
111278
+ root.find(import_jscodeshift.default.MemberExpression).forEach((p) => {
111279
+ const obj = p.node.object;
111280
+ if (obj.type === "Identifier" && obj.name === name)
111281
+ used = true;
111282
+ });
111283
+ return used && !declared;
111284
+ }
111285
+ function exportsBinding(source, name) {
111286
+ if (!source.includes(`export`) || !source.includes(name))
111287
+ return false;
111288
+ let root;
111289
+ try {
111290
+ root = tsx(source);
111291
+ } catch {
111292
+ return false;
111293
+ }
111294
+ let found = false;
111295
+ root.find(import_jscodeshift.default.ExportNamedDeclaration).forEach((p) => {
111296
+ const node = p.node;
111297
+ if (node.declaration?.type === "VariableDeclaration") {
111298
+ for (const d of node.declaration.declarations) {
111299
+ if (d.type === "VariableDeclarator" && d.id.type === "Identifier" && d.id.name === name) {
111300
+ found = true;
111301
+ }
111302
+ }
111303
+ }
111304
+ for (const spec of node.specifiers ?? []) {
111305
+ const exported = spec.exported;
111306
+ if (exported?.type === "Identifier" && exported.name === name) {
111307
+ found = true;
111308
+ }
111309
+ }
111310
+ });
111311
+ return found;
111312
+ }
111313
+ function isSupabaseClientModule(source) {
111314
+ if (!source.includes("@supabase/"))
111315
+ return false;
111316
+ let root;
111317
+ try {
111318
+ root = tsx(source);
111319
+ } catch {
111320
+ return false;
111321
+ }
111322
+ let importsSupabase = false;
111323
+ root.find(import_jscodeshift.default.ImportDeclaration).forEach((p) => {
111324
+ const src = p.node.source.value;
111325
+ if (typeof src === "string" && src.startsWith("@supabase/"))
111326
+ importsSupabase = true;
111327
+ });
111328
+ if (!importsSupabase)
111329
+ return false;
111330
+ let callsFactory = false;
111331
+ root.find(import_jscodeshift.default.CallExpression).forEach((p) => {
111332
+ const callee = p.node.callee;
111333
+ if (callee.type === "Identifier" && CLIENT_FACTORIES.has(callee.name)) {
111334
+ callsFactory = true;
111335
+ }
111336
+ });
111337
+ return callsFactory;
111338
+ }
111339
+
111340
+ // ../core/dist/commands/migrate-supabase-status.js
111341
+ var import_cross_spawn = __toESM(require_cross_spawn(), 1);
111342
+ import { readFile as readFile4 } from "node:fs/promises";
111343
+ import { join as join19, relative as relative5, resolve as resolve8 } from "node:path";
111344
+
111345
+ // ../core/dist/commands/migrate-supabase-sdk.js
111346
+ var import_jscodeshift2 = __toESM(require_core3(), 1);
111347
+ var tsx2 = import_jscodeshift2.default.withParser("tsx");
110903
111348
  function rewriteSupabaseSdk(input) {
110904
111349
  const pbName = input.pbIdentifier ?? "pb";
110905
111350
  const supabaseNames = new Set(input.supabaseIdentifiers ?? ["supabase"]);
@@ -110908,7 +111353,7 @@ function rewriteSupabaseSdk(input) {
110908
111353
  }
110909
111354
  let root;
110910
111355
  try {
110911
- root = tsx(input.source);
111356
+ root = tsx2(input.source);
110912
111357
  } catch (err) {
110913
111358
  return {
110914
111359
  rewritten: input.source,
@@ -110991,7 +111436,7 @@ function sourceMentionsSupabase(source, supabaseNames) {
110991
111436
  return false;
110992
111437
  }
110993
111438
  function rewriteAuthCalls(root, supabaseNames, pbName, flags, state) {
110994
- root.find(import_jscodeshift.default.CallExpression).filter((path) => isSupabaseAuthCall(path, supabaseNames)).forEach((path) => {
111439
+ root.find(import_jscodeshift2.default.CallExpression).filter((path) => isSupabaseAuthCall(path, supabaseNames)).forEach((path) => {
110995
111440
  const callee = path.node.callee;
110996
111441
  const method = callee.property.name;
110997
111442
  switch (method) {
@@ -111010,6 +111455,12 @@ function rewriteAuthCalls(root, supabaseNames, pbName, flags, state) {
111010
111455
  case "onAuthStateChange":
111011
111456
  replaceAuthOnChange(path, pbName, flags, state);
111012
111457
  return;
111458
+ default: {
111459
+ const recipe = recipeFor(`auth.${method}`);
111460
+ 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/).`;
111461
+ flags.push(makeFlag(path, "unsupported", `auth.${method}`, note));
111462
+ return;
111463
+ }
111013
111464
  }
111014
111465
  });
111015
111466
  }
@@ -111019,7 +111470,7 @@ function replaceAuthOnChange(path, pbName, flags, state) {
111019
111470
  flags.push(makeFlag(path, "manual_review", "auth.onAuthStateChange", "onAuthStateChange called with no args — manual review."));
111020
111471
  return;
111021
111472
  }
111022
- const replacement = import_jscodeshift.default.callExpression(import_jscodeshift.default.memberExpression(import_jscodeshift.default.memberExpression(import_jscodeshift.default.identifier(pbName), import_jscodeshift.default.identifier("authStore")), import_jscodeshift.default.identifier("onChange")), [callback]);
111473
+ 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]);
111023
111474
  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);
111024
111475
  }
111025
111476
  function isSupabaseAuthCall(path, supabaseNames) {
@@ -111053,7 +111504,7 @@ function replaceAuthSignIn(path, pbName, flags, state) {
111053
111504
  flagEnvelopeManualReview(path, "auth.signInWithPassword", flags);
111054
111505
  return;
111055
111506
  }
111056
- const replacement = import_jscodeshift.default.callExpression(import_jscodeshift.default.memberExpression(import_jscodeshift.default.callExpression(import_jscodeshift.default.memberExpression(import_jscodeshift.default.identifier(pbName), import_jscodeshift.default.identifier("collection")), [import_jscodeshift.default.literal("users")]), import_jscodeshift.default.identifier("authWithPassword")), [emailExpr, passwordExpr]);
111507
+ 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]);
111057
111508
  applyRewrite(path, replacement, "rewritten", "auth.signInWithPassword", 'signInWithPassword → pb.collection("users").authWithPassword', flags, state);
111058
111509
  }
111059
111510
  function replaceAuthSignUp(path, pbName, flags, state) {
@@ -111072,11 +111523,11 @@ function replaceAuthSignUp(path, pbName, flags, state) {
111072
111523
  flagEnvelopeManualReview(path, "auth.signUp", flags);
111073
111524
  return;
111074
111525
  }
111075
- const replacement = import_jscodeshift.default.callExpression(import_jscodeshift.default.memberExpression(import_jscodeshift.default.callExpression(import_jscodeshift.default.memberExpression(import_jscodeshift.default.identifier(pbName), import_jscodeshift.default.identifier("collection")), [import_jscodeshift.default.literal("users")]), import_jscodeshift.default.identifier("create")), [
111076
- import_jscodeshift.default.objectExpression([
111077
- import_jscodeshift.default.property("init", import_jscodeshift.default.identifier("email"), emailExpr),
111078
- import_jscodeshift.default.property("init", import_jscodeshift.default.identifier("password"), passwordExpr),
111079
- import_jscodeshift.default.property("init", import_jscodeshift.default.identifier("passwordConfirm"), passwordExpr)
111526
+ 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")), [
111527
+ import_jscodeshift2.default.objectExpression([
111528
+ import_jscodeshift2.default.property("init", import_jscodeshift2.default.identifier("email"), emailExpr),
111529
+ import_jscodeshift2.default.property("init", import_jscodeshift2.default.identifier("password"), passwordExpr),
111530
+ import_jscodeshift2.default.property("init", import_jscodeshift2.default.identifier("passwordConfirm"), passwordExpr)
111080
111531
  ])
111081
111532
  ]);
111082
111533
  applyRewrite(path, replacement, "rewritten", "auth.signUp", 'signUp → pb.collection("users").create({...passwordConfirm})', flags, state);
@@ -111086,7 +111537,7 @@ function replaceAuthSignOut(path, pbName, flags, state) {
111086
111537
  flagEnvelopeManualReview(path, "auth.signOut", flags);
111087
111538
  return;
111088
111539
  }
111089
- const replacement = import_jscodeshift.default.callExpression(import_jscodeshift.default.memberExpression(import_jscodeshift.default.memberExpression(import_jscodeshift.default.identifier(pbName), import_jscodeshift.default.identifier("authStore")), import_jscodeshift.default.identifier("clear")), []);
111540
+ 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")), []);
111090
111541
  applyRewrite(path, replacement, "rewritten", "auth.signOut", "signOut → pb.authStore.clear()", flags, state);
111091
111542
  }
111092
111543
  function replaceAuthGetUser(path, pbName, flags, state) {
@@ -111094,11 +111545,11 @@ function replaceAuthGetUser(path, pbName, flags, state) {
111094
111545
  flagEnvelopeManualReview(path, "auth.getUser", flags);
111095
111546
  return;
111096
111547
  }
111097
- const replacement = import_jscodeshift.default.memberExpression(import_jscodeshift.default.memberExpression(import_jscodeshift.default.identifier(pbName), import_jscodeshift.default.identifier("authStore")), import_jscodeshift.default.identifier("model"));
111548
+ 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"));
111098
111549
  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);
111099
111550
  }
111100
111551
  function rewriteFromCalls(root, supabaseNames, pbName, flags, state) {
111101
- root.find(import_jscodeshift.default.CallExpression).filter((path) => isSupabaseFromTerminal(path, supabaseNames)).forEach((path) => {
111552
+ root.find(import_jscodeshift2.default.CallExpression).filter((path) => isSupabaseFromTerminal(path, supabaseNames)).forEach((path) => {
111102
111553
  rewriteFromChain(path, supabaseNames, pbName, flags, state);
111103
111554
  });
111104
111555
  }
@@ -111204,7 +111655,7 @@ function rewriteSelect(path, pbName, table, steps, flags, state) {
111204
111655
  let paginationPerPage = 0;
111205
111656
  const fieldsValue = extractSelectFields(select);
111206
111657
  if (fieldsValue !== null)
111207
- opts.fields = import_jscodeshift.default.literal(fieldsValue);
111658
+ opts.fields = import_jscodeshift2.default.literal(fieldsValue);
111208
111659
  for (const step of tail) {
111209
111660
  switch (step.method) {
111210
111661
  case "eq": {
@@ -111228,7 +111679,7 @@ function rewriteSelect(path, pbName, table, steps, flags, state) {
111228
111679
  reviewNotes.push(`.order() arguments not in the recognised shape — manual review.`);
111229
111680
  continue;
111230
111681
  }
111231
- opts.sort = import_jscodeshift.default.literal(opts.sort ? `${literalString(opts.sort)},${sortFrag}` : sortFrag);
111682
+ opts.sort = import_jscodeshift2.default.literal(opts.sort ? `${literalString(opts.sort)},${sortFrag}` : sortFrag);
111232
111683
  break;
111233
111684
  }
111234
111685
  case "limit": {
@@ -111289,7 +111740,7 @@ function rewriteSelect(path, pbName, table, steps, flags, state) {
111289
111740
  if (usePagination) {
111290
111741
  methodName = "getList";
111291
111742
  const trailingOpts = buildOptionsObject(opts);
111292
- methodArgs = [import_jscodeshift.default.literal(paginationPage), import_jscodeshift.default.literal(paginationPerPage)];
111743
+ methodArgs = [import_jscodeshift2.default.literal(paginationPage), import_jscodeshift2.default.literal(paginationPerPage)];
111293
111744
  if (trailingOpts)
111294
111745
  methodArgs.push(trailingOpts);
111295
111746
  } else {
@@ -111297,7 +111748,7 @@ function rewriteSelect(path, pbName, table, steps, flags, state) {
111297
111748
  const optsObj = buildOptionsObject(opts);
111298
111749
  methodArgs = optsObj ? [optsObj] : [];
111299
111750
  }
111300
- const replacement = import_jscodeshift.default.callExpression(import_jscodeshift.default.memberExpression(import_jscodeshift.default.callExpression(import_jscodeshift.default.memberExpression(import_jscodeshift.default.identifier(pbName), import_jscodeshift.default.identifier("collection")), [import_jscodeshift.default.literal(table)]), import_jscodeshift.default.identifier(methodName)), methodArgs);
111751
+ 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);
111301
111752
  const kind = needsReview ? "manual_review" : "rewritten";
111302
111753
  const baseNote = `from(${JSON.stringify(table)}).select(...) → pb.collection(...).${methodName}(...)`;
111303
111754
  const note = needsReview ? `${baseNote} — ${reviewNotes.join(" · ")}` : baseNote;
@@ -111328,23 +111779,23 @@ function buildEqFilter(step) {
111328
111779
  const v = valArg.value;
111329
111780
  if (typeof v === "string") {
111330
111781
  return {
111331
- expression: import_jscodeshift.default.literal(`${column} = "${escapeFilterString(v)}"`),
111782
+ expression: import_jscodeshift2.default.literal(`${column} = "${escapeFilterString(v)}"`),
111332
111783
  column,
111333
111784
  identifierValue: false
111334
111785
  };
111335
111786
  }
111336
111787
  if (typeof v === "number" || typeof v === "boolean") {
111337
111788
  return {
111338
- expression: import_jscodeshift.default.literal(`${column} = ${v}`),
111789
+ expression: import_jscodeshift2.default.literal(`${column} = ${v}`),
111339
111790
  column,
111340
111791
  identifierValue: false
111341
111792
  };
111342
111793
  }
111343
111794
  return null;
111344
111795
  }
111345
- const template = import_jscodeshift.default.templateLiteral([
111346
- import_jscodeshift.default.templateElement({ raw: `${column} = "`, cooked: `${column} = "` }, false),
111347
- import_jscodeshift.default.templateElement({ raw: `"`, cooked: `"` }, true)
111796
+ const template = import_jscodeshift2.default.templateLiteral([
111797
+ import_jscodeshift2.default.templateElement({ raw: `${column} = "`, cooked: `${column} = "` }, false),
111798
+ import_jscodeshift2.default.templateElement({ raw: `"`, cooked: `"` }, true)
111348
111799
  ], [valArg]);
111349
111800
  return {
111350
111801
  expression: template,
@@ -111361,17 +111812,17 @@ function combineFilterStatic(current, next) {
111361
111812
  const a = literalString(current);
111362
111813
  const b = literalString(next);
111363
111814
  if (a !== null && b !== null) {
111364
- return import_jscodeshift.default.literal(`(${a}) && (${b})`);
111815
+ return import_jscodeshift2.default.literal(`(${a}) && (${b})`);
111365
111816
  }
111366
111817
  return combineFilterDynamic(current, next);
111367
111818
  }
111368
111819
  function combineFilterDynamic(current, next) {
111369
111820
  if (!current)
111370
111821
  return next;
111371
- return import_jscodeshift.default.templateLiteral([
111372
- import_jscodeshift.default.templateElement({ raw: "(", cooked: "(" }, false),
111373
- import_jscodeshift.default.templateElement({ raw: ") && (", cooked: ") && (" }, false),
111374
- import_jscodeshift.default.templateElement({ raw: ")", cooked: ")" }, true)
111822
+ return import_jscodeshift2.default.templateLiteral([
111823
+ import_jscodeshift2.default.templateElement({ raw: "(", cooked: "(" }, false),
111824
+ import_jscodeshift2.default.templateElement({ raw: ") && (", cooked: ") && (" }, false),
111825
+ import_jscodeshift2.default.templateElement({ raw: ")", cooked: ")" }, true)
111375
111826
  ], [current, next]);
111376
111827
  }
111377
111828
  function literalString(node) {
@@ -111425,17 +111876,17 @@ function extractNumber(node) {
111425
111876
  function buildOptionsObject(opts) {
111426
111877
  const props = [];
111427
111878
  if (opts.fields !== undefined) {
111428
- props.push(import_jscodeshift.default.property("init", import_jscodeshift.default.identifier("fields"), opts.fields));
111879
+ props.push(import_jscodeshift2.default.property("init", import_jscodeshift2.default.identifier("fields"), opts.fields));
111429
111880
  }
111430
111881
  if (opts.filter !== undefined) {
111431
- props.push(import_jscodeshift.default.property("init", import_jscodeshift.default.identifier("filter"), opts.filter));
111882
+ props.push(import_jscodeshift2.default.property("init", import_jscodeshift2.default.identifier("filter"), opts.filter));
111432
111883
  }
111433
111884
  if (opts.sort !== undefined) {
111434
- props.push(import_jscodeshift.default.property("init", import_jscodeshift.default.identifier("sort"), opts.sort));
111885
+ props.push(import_jscodeshift2.default.property("init", import_jscodeshift2.default.identifier("sort"), opts.sort));
111435
111886
  }
111436
111887
  if (props.length === 0)
111437
111888
  return null;
111438
- return import_jscodeshift.default.objectExpression(props);
111889
+ return import_jscodeshift2.default.objectExpression(props);
111439
111890
  }
111440
111891
  function rewriteInsert(path, pbName, table, insert, flags, state) {
111441
111892
  if (consumesDataErrorEnvelope(path)) {
@@ -111451,7 +111902,7 @@ function rewriteInsert(path, pbName, table, insert, flags, state) {
111451
111902
  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.`));
111452
111903
  return;
111453
111904
  }
111454
- const replacement = import_jscodeshift.default.callExpression(import_jscodeshift.default.memberExpression(import_jscodeshift.default.callExpression(import_jscodeshift.default.memberExpression(import_jscodeshift.default.identifier(pbName), import_jscodeshift.default.identifier("collection")), [import_jscodeshift.default.literal(table)]), import_jscodeshift.default.identifier("create")), [arg]);
111905
+ 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]);
111455
111906
  applyRewrite(path, replacement, "rewritten", "from.insert", `from(${JSON.stringify(table)}).insert({...}) → pb.collection(...).create({...})`, flags, state);
111456
111907
  }
111457
111908
  function rewriteUpdate(path, pbName, table, steps, flags, state) {
@@ -111480,7 +111931,7 @@ function rewriteUpdate(path, pbName, table, steps, flags, state) {
111480
111931
  flags.push(makeFlag(path, "manual_review", "from.update", "update() called with no args — manual review."));
111481
111932
  return;
111482
111933
  }
111483
- const replacement = import_jscodeshift.default.callExpression(import_jscodeshift.default.memberExpression(import_jscodeshift.default.callExpression(import_jscodeshift.default.memberExpression(import_jscodeshift.default.identifier(pbName), import_jscodeshift.default.identifier("collection")), [import_jscodeshift.default.literal(table)]), import_jscodeshift.default.identifier("update")), [eqVal, updateArg]);
111934
+ 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]);
111484
111935
  applyRewrite(path, replacement, "rewritten", "from.update", `from(${JSON.stringify(table)}).update({...}).eq("id", v) → pb.collection(...).update(v, {...})`, flags, state);
111485
111936
  }
111486
111937
  function rewriteDelete(path, pbName, table, steps, flags, state) {
@@ -111503,11 +111954,11 @@ function rewriteDelete(path, pbName, table, steps, flags, state) {
111503
111954
  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.`));
111504
111955
  return;
111505
111956
  }
111506
- const replacement = import_jscodeshift.default.callExpression(import_jscodeshift.default.memberExpression(import_jscodeshift.default.callExpression(import_jscodeshift.default.memberExpression(import_jscodeshift.default.identifier(pbName), import_jscodeshift.default.identifier("collection")), [import_jscodeshift.default.literal(table)]), import_jscodeshift.default.identifier("delete")), [eqVal]);
111957
+ 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]);
111507
111958
  applyRewrite(path, replacement, "rewritten", "from.delete", `from(${JSON.stringify(table)}).delete().eq("id", v) → pb.collection(...).delete(v)`, flags, state);
111508
111959
  }
111509
111960
  function flagUnsupportedPatterns(root, supabaseNames, flags) {
111510
- root.find(import_jscodeshift.default.CallExpression).forEach((path) => {
111961
+ root.find(import_jscodeshift2.default.CallExpression).forEach((path) => {
111511
111962
  flagOneUnsupported(path, supabaseNames, flags);
111512
111963
  });
111513
111964
  }
@@ -111646,11 +112097,148 @@ function readFirstStringArg(call) {
111646
112097
  }
111647
112098
  return null;
111648
112099
  }
112100
+ var EMPTY_SCAN = {
112101
+ importsSupabase: false,
112102
+ authCalls: 0,
112103
+ fromCalls: 0,
112104
+ storage: 0,
112105
+ rpc: 0,
112106
+ realtime: 0,
112107
+ edgeFunctions: 0,
112108
+ usesPb: false,
112109
+ danglingPb: false
112110
+ };
112111
+ function scanSupabaseUsage(input) {
112112
+ const supabaseNames = new Set(input.supabaseIdentifiers ?? ["supabase"]);
112113
+ const pbName = input.pbIdentifier ?? "pb";
112114
+ const mentionsSupabase = sourceMentionsSupabase(input.source, supabaseNames);
112115
+ const mentionsPb = input.source.includes(pbName);
112116
+ if (!mentionsSupabase && !mentionsPb)
112117
+ return { ...EMPTY_SCAN };
112118
+ let root;
112119
+ try {
112120
+ root = tsx2(input.source);
112121
+ } catch (err) {
112122
+ return { ...EMPTY_SCAN, parseError: err instanceof Error ? err.message : String(err) };
112123
+ }
112124
+ const scan = { ...EMPTY_SCAN };
112125
+ scan.importsSupabase = importsSupabasePackage(root);
112126
+ root.find(import_jscodeshift2.default.CallExpression).forEach((path) => {
112127
+ const chainRoot = findChainRoot(path.node);
112128
+ if (chainRoot?.type !== "Identifier")
112129
+ return;
112130
+ if (!supabaseNames.has(chainRoot.name))
112131
+ return;
112132
+ const parent = path.parent?.node;
112133
+ if (parent?.type === "MemberExpression" && parent.object === path.node) {
112134
+ return;
112135
+ }
112136
+ const steps = readChainSteps(path.node);
112137
+ const first = steps[0];
112138
+ if (!first)
112139
+ return;
112140
+ switch (first.method) {
112141
+ case "auth":
112142
+ scan.authCalls += 1;
112143
+ break;
112144
+ case "from":
112145
+ scan.fromCalls += 1;
112146
+ break;
112147
+ case "storage":
112148
+ scan.storage += 1;
112149
+ break;
112150
+ case "rpc":
112151
+ scan.rpc += 1;
112152
+ break;
112153
+ case "channel":
112154
+ scan.realtime += 1;
112155
+ break;
112156
+ case "functions":
112157
+ if (steps[1]?.method === "invoke")
112158
+ scan.edgeFunctions += 1;
112159
+ break;
112160
+ }
112161
+ });
112162
+ const pb = analyzePbBinding(root, pbName);
112163
+ scan.usesPb = pb.usesPb;
112164
+ scan.danglingPb = pb.usesPb && !pb.declared;
112165
+ return scan;
112166
+ }
112167
+ function importsSupabasePackage(root) {
112168
+ let found = false;
112169
+ root.find(import_jscodeshift2.default.ImportDeclaration).forEach((p) => {
112170
+ const src = p.node.source.value;
112171
+ if (typeof src === "string" && src.startsWith("@supabase/"))
112172
+ found = true;
112173
+ });
112174
+ if (found)
112175
+ return true;
112176
+ root.find(import_jscodeshift2.default.CallExpression).forEach((p) => {
112177
+ const callee = p.node.callee;
112178
+ const isRequire = callee.type === "Identifier" && callee.name === "require";
112179
+ const isDynImport = callee.type === "Import";
112180
+ if (!isRequire && !isDynImport)
112181
+ return;
112182
+ const arg = p.node.arguments[0];
112183
+ if ((arg?.type === "Literal" || arg?.type === "StringLiteral") && typeof arg.value === "string" && arg.value.startsWith("@supabase/")) {
112184
+ found = true;
112185
+ }
112186
+ });
112187
+ return found;
112188
+ }
112189
+ function analyzePbBinding(root, pbName) {
112190
+ let declared = false;
112191
+ root.find(import_jscodeshift2.default.ImportDeclaration).forEach((p) => {
112192
+ for (const spec of p.node.specifiers ?? []) {
112193
+ if (spec.local?.name === pbName)
112194
+ declared = true;
112195
+ }
112196
+ });
112197
+ root.find(import_jscodeshift2.default.VariableDeclarator).forEach((p) => {
112198
+ const id = p.node.id;
112199
+ if (id.type === "Identifier" && id.name === pbName)
112200
+ declared = true;
112201
+ if (id.type === "ObjectPattern" && objectPatternBindsName(id, pbName)) {
112202
+ declared = true;
112203
+ }
112204
+ });
112205
+ const checkParams = (params) => {
112206
+ for (const param of params) {
112207
+ if (param.type === "Identifier" && param.name === pbName) {
112208
+ declared = true;
112209
+ }
112210
+ }
112211
+ };
112212
+ root.find(import_jscodeshift2.default.FunctionDeclaration).forEach((p) => {
112213
+ checkParams(p.node.params);
112214
+ });
112215
+ root.find(import_jscodeshift2.default.FunctionExpression).forEach((p) => {
112216
+ checkParams(p.node.params);
112217
+ });
112218
+ root.find(import_jscodeshift2.default.ArrowFunctionExpression).forEach((p) => {
112219
+ checkParams(p.node.params);
112220
+ });
112221
+ let usedAsObject = false;
112222
+ root.find(import_jscodeshift2.default.MemberExpression).forEach((p) => {
112223
+ const obj = p.node.object;
112224
+ if (obj.type === "Identifier" && obj.name === pbName)
112225
+ usedAsObject = true;
112226
+ });
112227
+ return { usesPb: usedAsObject, declared };
112228
+ }
112229
+ function objectPatternBindsName(pattern, name) {
112230
+ for (const prop of pattern.properties) {
112231
+ if ((prop.type === "Property" || prop.type === "ObjectProperty") && "value" in prop && prop.value.type === "Identifier" && prop.value.name === name) {
112232
+ return true;
112233
+ }
112234
+ }
112235
+ return false;
112236
+ }
111649
112237
  function findObjectProp(obj, name) {
111650
112238
  for (const prop of obj.properties) {
111651
112239
  if ((prop.type === "Property" || prop.type === "ObjectProperty") && "key" in prop && prop.key.type === "Identifier" && prop.key.name === name) {
111652
112240
  if (prop.shorthand === true) {
111653
- return import_jscodeshift.default.identifier(name);
112241
+ return import_jscodeshift2.default.identifier(name);
111654
112242
  }
111655
112243
  if ("value" in prop) {
111656
112244
  const val = prop.value;
@@ -111687,6 +112275,9 @@ function applyRewrite(path, replacement, kind, pattern, note, flags, state) {
111687
112275
  }
111688
112276
 
111689
112277
  // ../core/dist/commands/migrate-supabase-walker.js
112278
+ var import_ignore3 = __toESM(require_ignore(), 1);
112279
+ import { mkdir as mkdir2, readdir, readFile as readFile3, stat, writeFile as writeFile2 } from "node:fs/promises";
112280
+ import { dirname as dirname5, isAbsolute as isAbsolute3, join as join18, relative as relative4, resolve as resolve7, sep as sep4 } from "node:path";
111690
112281
  var REWRITABLE_EXTENSIONS = new Set([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"]);
111691
112282
  var DEFAULT_EXCLUDES = [
111692
112283
  "node_modules",
@@ -111707,15 +112298,16 @@ var DEFAULT_EXCLUDES = [
111707
112298
  "pb_migrations"
111708
112299
  ];
111709
112300
  async function walkSupabaseProject(input) {
111710
- const rootAbs = resolve6(input.rootDir);
112301
+ const rootAbs = resolve7(input.rootDir);
111711
112302
  const ig = import_ignore3.default().add(DEFAULT_EXCLUDES);
111712
112303
  if (input.extraExcludes && input.extraExcludes.length > 0) {
111713
112304
  ig.add(input.extraExcludes);
111714
112305
  }
111715
112306
  const files = [];
111716
112307
  const skipped = [];
112308
+ const pendingConfig = [];
111717
112309
  for await (const absPath of walkTree(rootAbs, rootAbs, ig)) {
111718
- const rel = relative3(rootAbs, absPath).split(sep3).join("/");
112310
+ const rel = relative4(rootAbs, absPath).split(sep4).join("/");
111719
112311
  const kind = classifyFile2(rel);
111720
112312
  if (kind === null)
111721
112313
  continue;
@@ -111759,11 +112351,38 @@ async function walkSupabaseProject(input) {
111759
112351
  });
111760
112352
  continue;
111761
112353
  }
111762
- const configResult = kind === "package_json" ? rewritePackageJson(source) : rewriteEnvFile(source);
112354
+ pendingConfig.push({ relativePath: rel, kind, source });
112355
+ }
112356
+ let supabaseUsageRemaining = 0;
112357
+ for (const file2 of files) {
112358
+ if (file2.kind !== "code")
112359
+ continue;
112360
+ const scan = scanSupabaseUsage({
112361
+ source: file2.rewritten,
112362
+ supabaseIdentifiers: input.supabaseIdentifiers
112363
+ });
112364
+ supabaseUsageRemaining += scan.authCalls + scan.storage + scan.rpc + scan.realtime + scan.edgeFunctions;
112365
+ if (scan.importsSupabase)
112366
+ supabaseUsageRemaining += 1;
112367
+ }
112368
+ const migrationComplete = supabaseUsageRemaining === 0;
112369
+ for (const cfg of pendingConfig) {
112370
+ if (!migrationComplete) {
112371
+ files.push({
112372
+ relativePath: cfg.relativePath,
112373
+ kind: cfg.kind,
112374
+ source: cfg.source,
112375
+ rewritten: cfg.source,
112376
+ changed: false,
112377
+ flags: []
112378
+ });
112379
+ continue;
112380
+ }
112381
+ const configResult = cfg.kind === "package_json" ? rewritePackageJson(cfg.source) : rewriteEnvFile(cfg.source);
111763
112382
  files.push({
111764
- relativePath: rel,
111765
- kind,
111766
- source,
112383
+ relativePath: cfg.relativePath,
112384
+ kind: cfg.kind,
112385
+ source: cfg.source,
111767
112386
  rewritten: configResult.rewritten,
111768
112387
  changed: configResult.changed,
111769
112388
  flags: configResult.flags
@@ -111796,7 +112415,9 @@ async function walkSupabaseProject(input) {
111796
112415
  changedFiles,
111797
112416
  flagCount,
111798
112417
  packageJsonChanged,
111799
- envFilesChanged
112418
+ envFilesChanged,
112419
+ migrationComplete,
112420
+ supabaseUsageRemaining
111800
112421
  }
111801
112422
  };
111802
112423
  }
@@ -111808,8 +112429,8 @@ async function* walkTree(dir, rootAbs, ig) {
111808
112429
  return;
111809
112430
  }
111810
112431
  for (const name of entries) {
111811
- const abs = join17(dir, name);
111812
- const rel = relative3(rootAbs, abs).split(sep3).join("/");
112432
+ const abs = join18(dir, name);
112433
+ const rel = relative4(rootAbs, abs).split(sep4).join("/");
111813
112434
  if (rel.length > 0 && ig.ignores(rel))
111814
112435
  continue;
111815
112436
  let st;
@@ -111958,38 +112579,420 @@ function extractPublicPrefix(key) {
111958
112579
  return "";
111959
112580
  }
111960
112581
  async function writeWalkResult(input) {
111961
- const targetAbs = resolve6(input.targetDir);
112582
+ const targetAbs = resolve7(input.targetDir);
111962
112583
  const changedOnly = input.changedOnly !== false;
111963
112584
  const written = [];
111964
112585
  for (const file2 of input.result.files) {
111965
112586
  if (changedOnly && !file2.changed)
111966
112587
  continue;
111967
- const abs = resolve6(targetAbs, file2.relativePath);
111968
- const rel = relative3(targetAbs, abs);
111969
- const isParentTraversal = rel === ".." || rel.startsWith(`..${sep3}`) || rel.startsWith("../");
111970
- if (rel.length === 0 || isParentTraversal || isAbsolute2(rel)) {
112588
+ const abs = resolve7(targetAbs, file2.relativePath);
112589
+ const rel = relative4(targetAbs, abs);
112590
+ const isParentTraversal = rel === ".." || rel.startsWith(`..${sep4}`) || rel.startsWith("../");
112591
+ if (rel.length === 0 || isParentTraversal || isAbsolute3(rel)) {
111971
112592
  throw new Error(`writeWalkResult refused path-traversing file "${file2.relativePath}" → "${abs}" (would escape targetDir "${targetAbs}").`);
111972
112593
  }
111973
- await mkdir2(dirname4(abs), { recursive: true });
112594
+ await mkdir2(dirname5(abs), { recursive: true });
111974
112595
  await writeFile2(abs, file2.rewritten, "utf8");
111975
112596
  written.push(file2.relativePath);
111976
112597
  }
111977
112598
  return { written };
111978
112599
  }
111979
112600
 
112601
+ // ../core/dist/commands/migrate-supabase-status.js
112602
+ var migrationStatusInputSchema = exports_external.object({
112603
+ rootDir: exports_external.string().optional().describe("Project root to scan. Relative paths resolve against ctx.cwd. Defaults to ctx.cwd."),
112604
+ 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."),
112605
+ 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`)."),
112606
+ supabaseIdentifiers: exports_external.array(exports_external.string()).optional().describe("Supabase client variable names to recognise (beyond `supabase`).")
112607
+ });
112608
+ function analyzeMigration(files, opts = {}) {
112609
+ const pbName = opts.pbIdentifier ?? "pb";
112610
+ const supabaseImportFiles = [];
112611
+ const danglingPbFiles = [];
112612
+ let authCalls = 0;
112613
+ let storage = 0;
112614
+ let rpc = 0;
112615
+ let realtime = 0;
112616
+ let edgeFunctions = 0;
112617
+ let anyPbUsage = false;
112618
+ let pocketbaseDepDeclared = false;
112619
+ let supabaseDepDeclared = false;
112620
+ let pocketbaseUrlEnv = false;
112621
+ let supabaseEnvPresent = false;
112622
+ for (const file2 of files) {
112623
+ if (file2.kind === "code") {
112624
+ const scan = scanSupabaseUsage({
112625
+ source: file2.source,
112626
+ supabaseIdentifiers: opts.supabaseIdentifiers,
112627
+ pbIdentifier: pbName
112628
+ });
112629
+ if (scan.importsSupabase)
112630
+ supabaseImportFiles.push(file2.relativePath);
112631
+ if (scan.danglingPb)
112632
+ danglingPbFiles.push(file2.relativePath);
112633
+ if (scan.usesPb)
112634
+ anyPbUsage = true;
112635
+ authCalls += scan.authCalls;
112636
+ storage += scan.storage;
112637
+ rpc += scan.rpc;
112638
+ realtime += scan.realtime;
112639
+ edgeFunctions += scan.edgeFunctions;
112640
+ continue;
112641
+ }
112642
+ if (file2.kind === "package_json") {
112643
+ const deps = readDeps(file2.source);
112644
+ if ("pocketbase" in deps)
112645
+ pocketbaseDepDeclared = true;
112646
+ if ("@supabase/supabase-js" in deps || "@supabase/ssr" in deps)
112647
+ supabaseDepDeclared = true;
112648
+ continue;
112649
+ }
112650
+ if (/^\s*[A-Z][A-Z0-9_]*POCKETBASE_URL\s*=/m.test(file2.source))
112651
+ pocketbaseUrlEnv = true;
112652
+ if (/^\s*[A-Z][A-Z0-9_]*SUPABASE[A-Z0-9_]*\s*=/m.test(file2.source))
112653
+ supabaseEnvPresent = true;
112654
+ }
112655
+ const remaining = supabaseImportFiles.length + authCalls + storage + rpc + realtime + edgeFunctions;
112656
+ const migrationComplete = remaining === 0;
112657
+ const checks3 = [];
112658
+ checks3.push({
112659
+ id: "supabaseImportsRemaining",
112660
+ label: "Supabase imports removed",
112661
+ status: supabaseImportFiles.length === 0 ? "pass" : "warn",
112662
+ count: supabaseImportFiles.length,
112663
+ 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.`,
112664
+ ...supabaseImportFiles.length > 0 ? { files: supabaseImportFiles } : {}
112665
+ });
112666
+ checks3.push({
112667
+ id: "undefinedPbReferences",
112668
+ label: "PocketBase client wired",
112669
+ status: danglingPbFiles.length === 0 ? "pass" : "fail",
112670
+ count: danglingPbFiles.length,
112671
+ 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.`,
112672
+ ...danglingPbFiles.length > 0 ? { files: danglingPbFiles } : {}
112673
+ });
112674
+ checks3.push(usageCheck("authCallsRemaining", "Auth calls migrated", authCalls, "supabase.auth.* call(s) still to map — see the auth recipes in REWRITE_NOTES.md."));
112675
+ checks3.push(usageCheck("storageUsage", "Storage migrated", storage, "supabase.storage.* call(s) remain — PocketBase models files as record fields; rewrite by hand."));
112676
+ checks3.push(usageCheck("rpcUsage", "RPC migrated", rpc, "supabase.rpc(...) call(s) remain — move the logic into app code or a PB hook."));
112677
+ checks3.push(usageCheck("realtimeUsage", "Realtime migrated", realtime, "supabase.channel(...) call(s) remain — PB realtime uses pb.collection(c).subscribe(); the event shape differs."));
112678
+ checks3.push(usageCheck("edgeFunctionUsage", "Edge functions migrated", edgeFunctions, "supabase.functions.invoke(...) call(s) remain — host the function elsewhere and fetch it."));
112679
+ checks3.push({
112680
+ id: "pocketbaseDepDeclared",
112681
+ label: "pocketbase dependency declared",
112682
+ status: pocketbaseDepDeclared ? "pass" : anyPbUsage ? "warn" : "n/a",
112683
+ count: 0,
112684
+ 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."
112685
+ });
112686
+ checks3.push(cleanupCheck({ migrationComplete, supabaseDepDeclared, remaining, anyPbUsage }));
112687
+ checks3.push({
112688
+ id: "envWired",
112689
+ label: "POCKETBASE_URL in env",
112690
+ status: pocketbaseUrlEnv ? "pass" : anyPbUsage ? "warn" : "n/a",
112691
+ count: 0,
112692
+ 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."
112693
+ });
112694
+ const rls = opts.rlsManualCount ?? null;
112695
+ checks3.push({
112696
+ id: "rlsRulesToWrite",
112697
+ label: "RLS → PB API rules",
112698
+ status: rls === null ? "n/a" : rls === 0 ? "pass" : "warn",
112699
+ count: rls ?? 0,
112700
+ 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.`
112701
+ });
112702
+ let supabaseEnvNote = "";
112703
+ if (!migrationComplete && !supabaseEnvPresent && supabaseDepDeclared) {
112704
+ supabaseEnvNote = " Note: Supabase calls remain but no SUPABASE_* env was found — make sure those keys are still set.";
112705
+ }
112706
+ if (supabaseEnvNote) {
112707
+ const envCheck = checks3.find((c) => c.id === "envWired");
112708
+ if (envCheck)
112709
+ envCheck.detail += supabaseEnvNote;
112710
+ }
112711
+ const state = deriveState(checks3, migrationComplete, anyPbUsage, remaining);
112712
+ return { checks: checks3, migrationComplete, state };
112713
+ }
112714
+ function usageCheck(id, label, count, remainingDetail) {
112715
+ return {
112716
+ id,
112717
+ label,
112718
+ status: count === 0 ? "pass" : "warn",
112719
+ count,
112720
+ detail: count === 0 ? "None remaining." : `${count} ${remainingDetail}`
112721
+ };
112722
+ }
112723
+ function cleanupCheck(args) {
112724
+ const base = { id: "supabaseCleanup", label: "Supabase removed", count: args.remaining };
112725
+ if (args.migrationComplete) {
112726
+ if (args.supabaseDepDeclared) {
112727
+ return {
112728
+ ...base,
112729
+ status: "warn",
112730
+ detail: "Migration looks complete — you can now drop @supabase/supabase-js and the Supabase env keys."
112731
+ };
112732
+ }
112733
+ return { ...base, status: "pass", detail: "Supabase fully removed." };
112734
+ }
112735
+ if (!args.supabaseDepDeclared && args.remaining > 0) {
112736
+ return {
112737
+ ...base,
112738
+ status: "fail",
112739
+ detail: `@supabase/supabase-js was dropped but ${args.remaining} Supabase reference(s) still need it — restore the dependency or finish migrating them.`
112740
+ };
112741
+ }
112742
+ return {
112743
+ ...base,
112744
+ status: "warn",
112745
+ 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.`
112746
+ };
112747
+ }
112748
+ function deriveState(checks3, migrationComplete, anyPbUsage, remaining) {
112749
+ if (checks3.some((c) => c.status === "fail"))
112750
+ return "broken";
112751
+ if (migrationComplete)
112752
+ return "complete";
112753
+ if (anyPbUsage)
112754
+ return "hybrid";
112755
+ return remaining > 0 ? "not_started" : "complete";
112756
+ }
112757
+ function readDeps(source) {
112758
+ let pkg;
112759
+ try {
112760
+ pkg = JSON.parse(source);
112761
+ } catch {
112762
+ return {};
112763
+ }
112764
+ const out = {};
112765
+ for (const section of [
112766
+ "dependencies",
112767
+ "devDependencies",
112768
+ "peerDependencies",
112769
+ "optionalDependencies"
112770
+ ]) {
112771
+ const deps = pkg[section];
112772
+ if (deps && typeof deps === "object" && !Array.isArray(deps)) {
112773
+ Object.assign(out, deps);
112774
+ }
112775
+ }
112776
+ return out;
112777
+ }
112778
+ var STATUS_GLYPH = {
112779
+ pass: "✓",
112780
+ fail: "✗",
112781
+ warn: "⚠",
112782
+ "n/a": "•"
112783
+ };
112784
+ function renderMigrationChecklist(checks3) {
112785
+ const lines = [];
112786
+ for (const check2 of checks3) {
112787
+ const glyph = STATUS_GLYPH[check2.status];
112788
+ const countSuffix = check2.count > 0 ? ` (${check2.count})` : "";
112789
+ lines.push(`${glyph} ${check2.label}${countSuffix} — ${check2.detail}`);
112790
+ if (check2.files && check2.files.length > 0) {
112791
+ for (const f of check2.files.slice(0, 10))
112792
+ lines.push(` - ${f}`);
112793
+ if (check2.files.length > 10)
112794
+ lines.push(` …and ${check2.files.length - 10} more`);
112795
+ }
112796
+ }
112797
+ return lines.join(`
112798
+ `);
112799
+ }
112800
+ var STATE_SUMMARY = {
112801
+ broken: "Migration is in a broken state — fix the ✗ items before deploying.",
112802
+ hybrid: "Hybrid migration — some calls are on PocketBase, some still on Supabase (both SDKs needed).",
112803
+ not_started: "Supabase is still in use — nothing migrated to PocketBase yet.",
112804
+ complete: "Migration looks complete — no Supabase usage remains."
112805
+ };
112806
+ async function migrationStatus(ctx, input) {
112807
+ const rootAbs = input.rootDir ? resolve8(ctx.cwd, input.rootDir) : resolve8(ctx.cwd);
112808
+ ctx.status(`Scanning ${relative5(ctx.cwd, rootAbs) || "."} for migration status...`);
112809
+ let files;
112810
+ try {
112811
+ const walk2 = await walkSupabaseProject({ rootDir: rootAbs });
112812
+ files = walk2.files.map((f) => ({
112813
+ relativePath: f.relativePath,
112814
+ kind: f.kind,
112815
+ source: f.source
112816
+ }));
112817
+ } catch (err) {
112818
+ return failure2(rootAbs, err);
112819
+ }
112820
+ const rlsManualCount = await readManualRlsCount(rootAbs);
112821
+ const analysis = analyzeMigration(files, {
112822
+ rlsManualCount,
112823
+ pbIdentifier: input.pbIdentifier,
112824
+ supabaseIdentifiers: input.supabaseIdentifiers
112825
+ });
112826
+ let build;
112827
+ if (input.build === true) {
112828
+ build = await runProjectBuild(rootAbs);
112829
+ }
112830
+ const checklist = renderMigrationChecklist(analysis.checks);
112831
+ const failing = analysis.checks.filter((c) => c.status === "fail");
112832
+ const warning = analysis.checks.filter((c) => c.status === "warn");
112833
+ const buildFailed = build?.ran === true && !build.passed;
112834
+ const allGreen = failing.length === 0 && warning.length === 0 && !buildFailed;
112835
+ const recovery = allGreen ? recoveryNone() : recoveryAsk({
112836
+ prompt: buildPrompt(analysis.state, failing, warning, build),
112837
+ reasonCode: "unknown"
112838
+ });
112839
+ const summary = `${STATE_SUMMARY[analysis.state]}${build ? ` Build: ${build.ran ? build.passed ? "passed" : "FAILED" : "skipped"}.` : ""}`;
112840
+ return {
112841
+ status: "ok",
112842
+ rootDir: rootAbs,
112843
+ state: analysis.state,
112844
+ migrationComplete: analysis.migrationComplete,
112845
+ checks: analysis.checks,
112846
+ ...build ? { build } : {},
112847
+ recovery,
112848
+ summary,
112849
+ checklist
112850
+ };
112851
+ }
112852
+ function buildPrompt(state, failing, warning, build) {
112853
+ const bits = [];
112854
+ if (failing.length > 0) {
112855
+ bits.push(`fix first: ${failing.map((c) => `${c.label} — ${c.detail}`).join("; ")}`);
112856
+ }
112857
+ if (warning.length > 0) {
112858
+ bits.push(`still to do: ${warning.map((c) => `${c.label} (${c.count || "n/a"})`).join(", ")}`);
112859
+ }
112860
+ if (build?.ran && !build.passed) {
112861
+ bits.push(`the build failed: ${build.detail}`);
112862
+ }
112863
+ const lead = state === "broken" ? "The migration is in a broken state." : "The migration isn't finished.";
112864
+ return `${lead} ${bits.join(". ")}. Work through migration-preview/REWRITE_NOTES.md, then re-run --status.`;
112865
+ }
112866
+ async function readManualRlsCount(rootAbs) {
112867
+ for (const dir of ["migration-preview", "."]) {
112868
+ try {
112869
+ const notes = await readFile4(join19(rootAbs, dir, "MIGRATION_NOTES.md"), "utf8");
112870
+ const m = notes.match(/\*\*RLS policies:\*\*\s*\d+\s*\((\d+)\s*need manual review\)/);
112871
+ if (m?.[1] !== undefined)
112872
+ return Number.parseInt(m[1], 10);
112873
+ return 0;
112874
+ } catch {}
112875
+ }
112876
+ return null;
112877
+ }
112878
+ async function runProjectBuild(rootAbs) {
112879
+ let hasBuildScript = false;
112880
+ try {
112881
+ const pkg = JSON.parse(await readFile4(join19(rootAbs, "package.json"), "utf8"));
112882
+ hasBuildScript = typeof pkg.scripts?.build === "string";
112883
+ } catch {
112884
+ return { ran: false, passed: false, detail: "No readable package.json — nothing to build." };
112885
+ }
112886
+ if (!hasBuildScript) {
112887
+ return { ran: false, passed: false, detail: "No `build` script in package.json." };
112888
+ }
112889
+ const pm = await detectPackageManager(rootAbs);
112890
+ const result = await spawnCapture(pm, ["run", "build"], rootAbs, 300000);
112891
+ if (result.timedOut) {
112892
+ return { ran: true, passed: false, detail: `\`${pm} run build\` timed out after 5 min.` };
112893
+ }
112894
+ if (result.spawnError) {
112895
+ return {
112896
+ ran: false,
112897
+ passed: false,
112898
+ detail: `Couldn't run \`${pm} run build\` (${result.spawnError}). Is ${pm} installed?`
112899
+ };
112900
+ }
112901
+ const passed = result.code === 0;
112902
+ const tail = lastLines(result.output, 12);
112903
+ return {
112904
+ ran: true,
112905
+ passed,
112906
+ detail: passed ? `\`${pm} run build\` succeeded.` : `\`${pm} run build\` exited ${result.code}.${tail ? `
112907
+ ${tail}` : ""}`
112908
+ };
112909
+ }
112910
+ async function detectPackageManager(rootAbs) {
112911
+ const has = async (name) => {
112912
+ try {
112913
+ await readFile4(join19(rootAbs, name), "utf8");
112914
+ return true;
112915
+ } catch {
112916
+ return false;
112917
+ }
112918
+ };
112919
+ if (await has("bun.lock") || await has("bun.lockb"))
112920
+ return "bun";
112921
+ if (await has("pnpm-lock.yaml"))
112922
+ return "pnpm";
112923
+ if (await has("yarn.lock"))
112924
+ return "yarn";
112925
+ return "npm";
112926
+ }
112927
+ function spawnCapture(cmd, args, cwd, timeoutMs) {
112928
+ return new Promise((resolve9) => {
112929
+ const child = import_cross_spawn.default(cmd, args, { cwd, stdio: ["ignore", "pipe", "pipe"] });
112930
+ let output = "";
112931
+ const onData = (chunk) => {
112932
+ output += chunk.toString();
112933
+ if (output.length > 64000)
112934
+ output = output.slice(-64000);
112935
+ };
112936
+ child.stdout?.on("data", onData);
112937
+ child.stderr?.on("data", onData);
112938
+ let timedOut = false;
112939
+ const timer = setTimeout(() => {
112940
+ timedOut = true;
112941
+ child.kill("SIGTERM");
112942
+ }, timeoutMs);
112943
+ child.on("error", (err) => {
112944
+ clearTimeout(timer);
112945
+ resolve9({ code: 1, output, timedOut, spawnError: err.message });
112946
+ });
112947
+ child.on("close", (code) => {
112948
+ clearTimeout(timer);
112949
+ resolve9({ code: code ?? 1, output, timedOut });
112950
+ });
112951
+ });
112952
+ }
112953
+ function lastLines(text, n) {
112954
+ const lines = text.split(/\r?\n/).filter((l) => l.trim().length > 0);
112955
+ return lines.slice(-n).join(`
112956
+ `);
112957
+ }
112958
+ function failure2(rootAbs, err) {
112959
+ const message = err instanceof Error ? err.message : String(err);
112960
+ return {
112961
+ status: "failed",
112962
+ rootDir: rootAbs,
112963
+ state: "broken",
112964
+ migrationComplete: false,
112965
+ checks: [],
112966
+ recovery: recoveryAsk({
112967
+ prompt: `Couldn't scan the project for migration status (${message}). Check the path exists and is readable, then re-run.`,
112968
+ reasonCode: "unknown",
112969
+ retryable: true
112970
+ }),
112971
+ summary: `Migration status scan failed: ${message}`,
112972
+ checklist: "",
112973
+ error: {
112974
+ code: "status_failed",
112975
+ title: "Migration status scan failed",
112976
+ explanation: message,
112977
+ suggestion: "Check the project path exists and is readable, then re-run."
112978
+ }
112979
+ };
112980
+ }
112981
+
111980
112982
  // ../core/dist/commands/migrate-supabase-rewrite.js
111981
112983
  var rewriteSupabaseClientInputSchema = exports_external.object({
111982
112984
  rootDir: exports_external.string().optional().describe("Project root to rewrite. Relative paths resolve against ctx.cwd. Defaults to ctx.cwd."),
111983
112985
  outputDir: exports_external.string().optional().describe("Where preview-mode writes the rewritten tree. Ignored when `apply` is true. Defaults to `<root>/migration-preview/rewritten`."),
111984
112986
  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."),
111985
112987
  pbIdentifier: exports_external.string().optional().describe("PocketBase client variable name to emit. Defaults to `pb`."),
111986
- supabaseIdentifiers: exports_external.array(exports_external.string()).optional().describe("Extra Supabase client variable names to recognise (beyond `supabase`).")
112988
+ supabaseIdentifiers: exports_external.array(exports_external.string()).optional().describe("Extra Supabase client variable names to recognise (beyond `supabase`)."),
112989
+ 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.")
111987
112990
  });
111988
112991
  async function rewriteSupabaseClient(ctx, input) {
111989
- const rootAbs = input.rootDir ? resolve7(ctx.cwd, input.rootDir) : resolve7(ctx.cwd);
112992
+ const rootAbs = input.rootDir ? resolve9(ctx.cwd, input.rootDir) : resolve9(ctx.cwd);
111990
112993
  const apply = input.apply === true;
111991
112994
  const mode = apply ? "apply" : "preview";
111992
- ctx.status(`Scanning ${relative4(ctx.cwd, rootAbs) || "."} for Supabase SDK calls...`);
112995
+ ctx.status(`Scanning ${relative6(ctx.cwd, rootAbs) || "."} for Supabase SDK calls...`);
111993
112996
  let walk2;
111994
112997
  try {
111995
112998
  walk2 = await walkSupabaseProject({
@@ -111998,7 +113001,7 @@ async function rewriteSupabaseClient(ctx, input) {
111998
113001
  supabaseIdentifiers: input.supabaseIdentifiers
111999
113002
  });
112000
113003
  } catch (err) {
112001
- return failure2(rootAbs, mode, err, `Couldn't scan ${relative4(ctx.cwd, rootAbs) || "."}: check the path exists and is readable, then re-run.`);
113004
+ return failure3(rootAbs, mode, err, `Couldn't scan ${relative6(ctx.cwd, rootAbs) || "."}: check the path exists and is readable, then re-run.`);
112002
113005
  }
112003
113006
  const changed = walk2.files.filter((f) => f.changed);
112004
113007
  const flags = collectManualFlags(walk2);
@@ -112015,15 +113018,32 @@ async function rewriteSupabaseClient(ctx, input) {
112015
113018
  flagsByPattern: {},
112016
113019
  packageJsonChanged: false,
112017
113020
  envFilesChanged: 0,
113021
+ clientModule: null,
112018
113022
  skipped: [],
112019
113023
  recovery: recoveryNone(),
112020
113024
  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.'
112021
113025
  };
112022
113026
  }
112023
- const reportNeeded = flags.length > 0 || walk2.skipped.length > 0;
112024
- const backupDir = apply && changed.length > 0 ? join18(rootAbs, "migration-preview", "backup") : null;
112025
- const rewriteTarget = apply ? rootAbs : input.outputDir ? resolve7(ctx.cwd, input.outputDir) : join18(rootAbs, "migration-preview", "rewritten");
113027
+ const hadRewrites = changed.length > 0;
113028
+ const scaffoldEnabled = input.scaffoldClient !== false && hadRewrites;
113029
+ const scaffold = scaffoldEnabled ? scaffoldPocketBaseClient({
113030
+ files: walk2.files,
113031
+ changedRelPaths: changed.map((f) => f.relativePath),
113032
+ pbIdentifier: input.pbIdentifier
113033
+ }) : null;
113034
+ if (scaffold) {
113035
+ for (const [rel, content] of scaffold.importInsertions) {
113036
+ const file2 = walk2.files.find((f) => f.relativePath === rel);
113037
+ if (file2)
113038
+ file2.rewritten = content;
113039
+ }
113040
+ flags.push(...scaffold.flags);
113041
+ }
113042
+ const reportNeeded = hadRewrites || flags.length > 0 || walk2.skipped.length > 0;
113043
+ const backupDir = apply && changed.length > 0 ? join20(rootAbs, "migration-preview", "backup") : null;
113044
+ const rewriteTarget = apply ? rootAbs : input.outputDir ? resolve9(ctx.cwd, input.outputDir) : join20(rootAbs, "migration-preview", "rewritten");
112026
113045
  const filesWritten = [];
113046
+ let clientModuleWritten = null;
112027
113047
  try {
112028
113048
  if (changed.length > 0) {
112029
113049
  if (apply && backupDir) {
@@ -112041,23 +113061,47 @@ async function rewriteSupabaseClient(ctx, input) {
112041
113061
  changedOnly: true
112042
113062
  });
112043
113063
  for (const rel of out.written) {
112044
- filesWritten.push(relative4(ctx.cwd, join18(rewriteTarget, rel)));
113064
+ filesWritten.push(relative6(ctx.cwd, join20(rewriteTarget, rel)));
113065
+ }
113066
+ if (scaffold?.clientModule) {
113067
+ const moduleAbs = join20(rewriteTarget, scaffold.clientModule.relativePath);
113068
+ await mkdir3(dirname6(moduleAbs), { recursive: true });
113069
+ await writeFile3(moduleAbs, scaffold.clientModule.content, "utf8");
113070
+ clientModuleWritten = relative6(ctx.cwd, moduleAbs).split(sep5).join("/");
113071
+ filesWritten.push(clientModuleWritten);
112045
113072
  }
112046
113073
  }
112047
113074
  if (reportNeeded) {
112048
- const reportAbs = join18(rootAbs, "migration-preview", "REWRITE_NOTES.md");
112049
- await mkdir3(dirname5(reportAbs), { recursive: true });
112050
- await writeFile3(reportAbs, renderReport({ flags, skipped: walk2.skipped }), "utf8");
112051
- filesWritten.push(relative4(ctx.cwd, reportAbs));
113075
+ const reportAbs = join20(rootAbs, "migration-preview", "REWRITE_NOTES.md");
113076
+ await mkdir3(dirname6(reportAbs), { recursive: true });
113077
+ const analysis = analyzeMigration(walk2.files.map((f) => ({
113078
+ relativePath: f.relativePath,
113079
+ kind: f.kind,
113080
+ source: f.rewritten
113081
+ })), { supabaseIdentifiers: input.supabaseIdentifiers, pbIdentifier: input.pbIdentifier });
113082
+ await writeFile3(reportAbs, renderReport({
113083
+ flags,
113084
+ skipped: walk2.skipped,
113085
+ hadRewrites,
113086
+ migrationComplete: walk2.summary.migrationComplete,
113087
+ supabaseUsageRemaining: walk2.summary.supabaseUsageRemaining,
113088
+ checklist: renderMigrationChecklist(analysis.checks),
113089
+ scaffoldedClient: scaffold?.clientModule?.relativePath ?? null,
113090
+ scaffoldSkippedExisting: scaffold?.skippedReason === "pb_client_exists"
113091
+ }), "utf8");
113092
+ filesWritten.push(relative6(ctx.cwd, reportAbs));
112052
113093
  }
112053
113094
  } catch (err) {
112054
- return failure2(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.");
113095
+ 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.");
112055
113096
  }
112056
113097
  const flagsByPattern = {};
112057
113098
  for (const flag of flags) {
112058
113099
  flagsByPattern[flag.pattern] = (flagsByPattern[flag.pattern] ?? 0) + 1;
112059
113100
  }
112060
- const recovery = reportNeeded ? recoveryAsk({ prompt: buildPrompt(flags, walk2.skipped.length), reasonCode: "unknown" }) : recoveryNone();
113101
+ const recovery = reportNeeded ? recoveryAsk({
113102
+ prompt: buildPrompt2(flags, walk2.skipped.length, hadRewrites, clientModuleWritten),
113103
+ reasonCode: "unknown"
113104
+ }) : recoveryNone();
112061
113105
  return {
112062
113106
  status: "ok",
112063
113107
  mode,
@@ -112070,11 +113114,21 @@ async function rewriteSupabaseClient(ctx, input) {
112070
113114
  flagsByPattern,
112071
113115
  packageJsonChanged: walk2.summary.packageJsonChanged,
112072
113116
  envFilesChanged: walk2.summary.envFilesChanged,
113117
+ clientModule: clientModuleWritten,
112073
113118
  skipped: walk2.skipped,
112074
113119
  recovery,
112075
- summary: renderSummary2({ mode, changed: changed.length, walk: walk2, flagCount: flags.length })
113120
+ summary: renderSummary2({
113121
+ mode,
113122
+ changed: changed.length,
113123
+ walk: walk2,
113124
+ flagCount: flags.length,
113125
+ clientModule: clientModuleWritten
113126
+ })
112076
113127
  };
112077
113128
  }
113129
+ function isHybrid(walk2) {
113130
+ return !walk2.summary.migrationComplete && walk2.summary.supabaseUsageRemaining > 0;
113131
+ }
112078
113132
  function collectManualFlags(walk2) {
112079
113133
  const out = [];
112080
113134
  for (const file2 of walk2.files) {
@@ -112093,10 +113147,15 @@ function collectManualFlags(walk2) {
112093
113147
  }
112094
113148
  return out;
112095
113149
  }
112096
- function buildPrompt(flags, skippedCount) {
113150
+ function buildPrompt2(flags, skippedCount, hadRewrites, clientModule) {
112097
113151
  const rewritten = flags.filter((f) => f.kind === "manual_review").length;
112098
113152
  const untouched = flags.filter((f) => f.kind === "unsupported").length;
112099
113153
  const bits = [];
113154
+ if (clientModule) {
113155
+ bits.push(`review the scaffolded PocketBase client at \`${clientModule}\``);
113156
+ } else if (hadRewrites) {
113157
+ bits.push("create the `pb` PocketBase client the rewritten code now uses (it isn't created for you)");
113158
+ }
112100
113159
  if (rewritten > 0) {
112101
113160
  bits.push(`${rewritten} rewritten to PocketBase but with semantics that differ from Supabase`);
112102
113161
  }
@@ -112106,7 +113165,7 @@ function buildPrompt(flags, skippedCount) {
112106
113165
  if (skippedCount > 0) {
112107
113166
  bits.push(`${skippedCount} file${skippedCount === 1 ? "" : "s"} couldn't be parsed`);
112108
113167
  }
112109
- return `Some locations need review: ${bits.join("; ")}. Each is listed with its file and line in migration-preview/REWRITE_NOTES.md — check them before deploying.`;
113168
+ return `Before deploying, work through migration-preview/REWRITE_NOTES.md: ${bits.join("; ")}.`;
112110
113169
  }
112111
113170
  function renderSummary2(args) {
112112
113171
  const parts = [];
@@ -112116,12 +113175,18 @@ function renderSummary2(args) {
112116
113175
  } else {
112117
113176
  parts.push("No files needed automatic rewriting.");
112118
113177
  }
113178
+ if (args.clientModule) {
113179
+ parts.push(`Scaffolded a PocketBase client at \`${args.clientModule}\` and imported it.`);
113180
+ }
112119
113181
  if (args.walk.summary.packageJsonChanged) {
112120
113182
  parts.push("`package.json` swapped `@supabase/supabase-js` → `pocketbase`.");
112121
113183
  }
112122
113184
  if (args.walk.summary.envFilesChanged > 0) {
112123
113185
  parts.push(`${args.walk.summary.envFilesChanged} .env file${args.walk.summary.envFilesChanged === 1 ? "" : "s"} stubbed with PocketBase keys.`);
112124
113186
  }
113187
+ if (isHybrid(args.walk)) {
113188
+ 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.`);
113189
+ }
112125
113190
  if (args.flagCount > 0) {
112126
113191
  parts.push(`${args.flagCount} pattern${args.flagCount === 1 ? "" : "s"} need manual review — see \`migration-preview/REWRITE_NOTES.md\`.`);
112127
113192
  }
@@ -112134,8 +113199,51 @@ function renderReport(args) {
112134
113199
  const lines = [];
112135
113200
  lines.push("# Supabase → PocketBase — review notes");
112136
113201
  lines.push("");
112137
- lines.push("The automated rewrite handled auth and CRUD. The locations below still need a human: some were rewritten but their semantics differ from Supabase, others have no PocketBase equivalent and were left untouched. There are no inline markers — work from this list.");
113202
+ 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.");
112138
113203
  lines.push("");
113204
+ if (args.checklist) {
113205
+ lines.push("## Status checklist");
113206
+ lines.push("");
113207
+ lines.push("Same scoreboard as `percher migrate-from-supabase --status`:");
113208
+ lines.push("");
113209
+ lines.push("```");
113210
+ lines.push(args.checklist);
113211
+ lines.push("```");
113212
+ lines.push("");
113213
+ }
113214
+ if (!args.migrationComplete && args.supabaseUsageRemaining > 0) {
113215
+ lines.push("## Hybrid state — Supabase kept on purpose");
113216
+ lines.push("");
113217
+ 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:`);
113218
+ lines.push("");
113219
+ 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.");
113220
+ lines.push("- your Supabase env vars (`SUPABASE_*` / `VITE_SUPABASE_*` / …) were **kept** — they're still needed by the calls below.");
113221
+ lines.push("");
113222
+ 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.");
113223
+ lines.push("");
113224
+ }
113225
+ if (args.scaffoldedClient) {
113226
+ lines.push("## PocketBase client (scaffolded for you)");
113227
+ lines.push("");
113228
+ 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.`);
113229
+ lines.push("");
113230
+ } else if (args.hadRewrites) {
113231
+ lines.push("## Wire the PocketBase client (required first)");
113232
+ lines.push("");
113233
+ 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.");
113234
+ lines.push("");
113235
+ lines.push("1. Replace your Supabase client setup with a PocketBase one, exported under the same name the rewrites use (`pb`):");
113236
+ lines.push("");
113237
+ lines.push("```js");
113238
+ lines.push('import PocketBase from "pocketbase";');
113239
+ lines.push("// Percher injects POCKETBASE_URL / VITE_POCKETBASE_URL at deploy time.");
113240
+ lines.push("export const pb = new PocketBase(import.meta.env.VITE_POCKETBASE_URL ?? process.env.POCKETBASE_URL);");
113241
+ lines.push("```");
113242
+ lines.push("");
113243
+ lines.push("2. Import `pb` in the rewritten files from wherever you export it.");
113244
+ lines.push("3. Remove the leftover `@supabase/*` imports (the `createClient(...)` setup, `@supabase/ssr` helpers, etc.) once nothing else needs them.");
113245
+ lines.push("");
113246
+ }
112139
113247
  const rewritten = args.flags.filter((f) => f.kind === "manual_review");
112140
113248
  const untouched = args.flags.filter((f) => f.kind === "unsupported");
112141
113249
  if (rewritten.length > 0) {
@@ -112152,6 +113260,9 @@ function renderReport(args) {
112152
113260
  lines.push("");
112153
113261
  appendFlagsByFile(lines, untouched);
112154
113262
  }
113263
+ const recipeLines = renderRecipesSection(args.flags.map((f) => f.pattern));
113264
+ for (const line of recipeLines)
113265
+ lines.push(line);
112155
113266
  if (args.skipped.length > 0) {
112156
113267
  lines.push("## Files that couldn't be parsed");
112157
113268
  lines.push("");
@@ -112182,7 +113293,7 @@ function appendFlagsByFile(lines, flags) {
112182
113293
  lines.push("");
112183
113294
  }
112184
113295
  }
112185
- function failure2(rootAbs, mode, err, suggestion) {
113296
+ function failure3(rootAbs, mode, err, suggestion) {
112186
113297
  const message = err instanceof Error ? err.message : String(err);
112187
113298
  return {
112188
113299
  status: "failed",
@@ -112196,6 +113307,7 @@ function failure2(rootAbs, mode, err, suggestion) {
112196
113307
  flagsByPattern: {},
112197
113308
  packageJsonChanged: false,
112198
113309
  envFilesChanged: 0,
113310
+ clientModule: null,
112199
113311
  skipped: [],
112200
113312
  recovery: recoveryAsk({
112201
113313
  prompt: `${suggestion} (${message})`,
@@ -112213,7 +113325,7 @@ function failure2(rootAbs, mode, err, suggestion) {
112213
113325
  }
112214
113326
  // ../core/dist/commands/migrate-supabase-schema.js
112215
113327
  import { mkdir as mkdir4, writeFile as writeFile4 } from "node:fs/promises";
112216
- import { isAbsolute as isAbsolute3, join as join19, relative as relative5, resolve as resolve8 } from "node:path";
113328
+ import { isAbsolute as isAbsolute4, join as join21, relative as relative7, resolve as resolve10 } from "node:path";
112217
113329
 
112218
113330
  // ../core/dist/commands/migrate-supabase-scripts.js
112219
113331
  function generateDataImportScripts(preview) {
@@ -112661,7 +113773,7 @@ var migrateSupabaseSchemaInputSchema = exports_external.object({
112661
113773
  });
112662
113774
  async function migrateSupabaseSchema(ctx, input) {
112663
113775
  const outputDirAbs = resolveOutputDir(ctx.cwd, input.outputDir);
112664
- const outputDirRel = relative5(ctx.cwd, outputDirAbs) || ".";
113776
+ const outputDirRel = relative7(ctx.cwd, outputDirAbs) || ".";
112665
113777
  ctx.status(`Inspecting Supabase project ${input.projectRef}...`);
112666
113778
  const inspection = await inspectSupabase(ctx, {
112667
113779
  projectRef: input.projectRef,
@@ -112725,28 +113837,28 @@ async function migrateSupabaseSchema(ctx, input) {
112725
113837
  }
112726
113838
  function resolveOutputDir(cwd, requested) {
112727
113839
  const raw = requested ?? "./migration-preview";
112728
- return isAbsolute3(raw) ? raw : resolve8(cwd, raw);
113840
+ return isAbsolute4(raw) ? raw : resolve10(cwd, raw);
112729
113841
  }
112730
113842
  async function writePreviewFiles(ctx, outputDir, preview) {
112731
113843
  await mkdir4(outputDir, { recursive: true });
112732
113844
  const schemaJson = renderSchemaJson(preview);
112733
113845
  const notesMd = renderMigrationNotes(preview);
112734
113846
  const scripts = generateDataImportScripts(preview);
112735
- const schemaPath = join19(outputDir, "pb_schema.json");
112736
- const notesPath = join19(outputDir, "MIGRATION_NOTES.md");
112737
- const migratePath = join19(outputDir, "pb_migrate.js");
112738
- const storagePath = join19(outputDir, "pb_migrate_storage.js");
113847
+ const schemaPath = join21(outputDir, "pb_schema.json");
113848
+ const notesPath = join21(outputDir, "MIGRATION_NOTES.md");
113849
+ const migratePath = join21(outputDir, "pb_migrate.js");
113850
+ const storagePath = join21(outputDir, "pb_migrate_storage.js");
112739
113851
  await writeFile4(schemaPath, schemaJson, "utf8");
112740
113852
  await writeFile4(notesPath, notesMd, "utf8");
112741
113853
  await writeFile4(migratePath, scripts.pbMigrate, "utf8");
112742
113854
  const written = [
112743
- relative5(ctx.cwd, schemaPath),
112744
- relative5(ctx.cwd, notesPath),
112745
- relative5(ctx.cwd, migratePath)
113855
+ relative7(ctx.cwd, schemaPath),
113856
+ relative7(ctx.cwd, notesPath),
113857
+ relative7(ctx.cwd, migratePath)
112746
113858
  ];
112747
113859
  if (scripts.pbMigrateStorage !== null) {
112748
113860
  await writeFile4(storagePath, scripts.pbMigrateStorage, "utf8");
112749
- written.push(relative5(ctx.cwd, storagePath));
113861
+ written.push(relative7(ctx.cwd, storagePath));
112750
113862
  }
112751
113863
  return written;
112752
113864
  }
@@ -112961,8 +114073,8 @@ async function previewBranchShow(ctx, input = {}) {
112961
114073
  };
112962
114074
  }
112963
114075
  // ../core/dist/commands/publish.js
112964
- import { existsSync as existsSync14 } from "node:fs";
112965
- import { join as join22 } from "node:path";
114076
+ import { existsSync as existsSync15 } from "node:fs";
114077
+ import { join as join24 } from "node:path";
112966
114078
 
112967
114079
  // ../shared/dist/pow.js
112968
114080
  import { createHash as createHash3 } from "node:crypto";
@@ -113339,7 +114451,7 @@ async function runDeployWithRetry(opts) {
113339
114451
 
113340
114452
  // ../core/dist/commands/env-scan.js
113341
114453
  import { readdirSync as readdirSync3, readFileSync as readFileSync10, statSync as statSync3 } from "node:fs";
113342
- import { join as join20 } from "node:path";
114454
+ import { join as join22 } from "node:path";
113343
114455
  var SOURCE_EXTS = new Set([
113344
114456
  ".ts",
113345
114457
  ".tsx",
@@ -113376,7 +114488,7 @@ function scanForMissingBuildEnvRefs(cwd, existingKeys) {
113376
114488
  continue;
113377
114489
  let content;
113378
114490
  try {
113379
- content = readFileSync10(join20(cwd, rel), "utf8");
114491
+ content = readFileSync10(join22(cwd, rel), "utf8");
113380
114492
  } catch {
113381
114493
  continue;
113382
114494
  }
@@ -113408,7 +114520,7 @@ function* walkDir(dir, base) {
113408
114520
  for (const name of entries) {
113409
114521
  if (SKIP_DIRS.has(name))
113410
114522
  continue;
113411
- const full = join20(dir, name);
114523
+ const full = join22(dir, name);
113412
114524
  let st;
113413
114525
  try {
113414
114526
  st = statSync3(full);
@@ -113768,19 +114880,19 @@ function titleFromCode(code) {
113768
114880
  }
113769
114881
 
113770
114882
  // ../core/dist/commands/publish-node.js
113771
- import { existsSync as existsSync13, readFileSync as readFileSync11 } from "node:fs";
113772
- import { join as join21 } from "node:path";
114883
+ import { existsSync as existsSync14, readFileSync as readFileSync11 } from "node:fs";
114884
+ import { join as join23 } from "node:path";
113773
114885
  function resolveNodeVersion(cwd) {
113774
- const nvmrc = join21(cwd, ".nvmrc");
113775
- if (existsSync13(nvmrc)) {
114886
+ const nvmrc = join23(cwd, ".nvmrc");
114887
+ if (existsSync14(nvmrc)) {
113776
114888
  try {
113777
114889
  const v = readFileSync11(nvmrc, "utf8").trim();
113778
114890
  if (v)
113779
114891
  return { value: v, source: ".nvmrc" };
113780
114892
  } catch {}
113781
114893
  }
113782
- const pkgPath = join21(cwd, "package.json");
113783
- if (!existsSync13(pkgPath))
114894
+ const pkgPath = join23(cwd, "package.json");
114895
+ if (!existsSync14(pkgPath))
113784
114896
  return null;
113785
114897
  try {
113786
114898
  const pkg = JSON.parse(readFileSync11(pkgPath, "utf8"));
@@ -113805,7 +114917,7 @@ var publishInputSchema = exports_external.object({
113805
114917
  var SUSPICIOUS_BYTES = 50 * 1024 * 1024;
113806
114918
  var SUSPICIOUS_FILES = 1e4;
113807
114919
  function tomlPathFor2(cwd) {
113808
- return join22(cwd, "percher.toml");
114920
+ return join24(cwd, "percher.toml");
113809
114921
  }
113810
114922
  async function buildReplacedResult2(opts) {
113811
114923
  const { ctx, app, deployment, tarball, cwd } = opts;
@@ -114470,8 +115582,8 @@ async function handleAnonymousPublish(ctx, config2, input, tarball) {
114470
115582
  };
114471
115583
  }
114472
115584
  async function loadOrGenerate(ctx) {
114473
- const tomlPath = join22(ctx.cwd, "percher.toml");
114474
- if (!existsSync14(tomlPath)) {
115585
+ const tomlPath = join24(ctx.cwd, "percher.toml");
115586
+ if (!existsSync15(tomlPath)) {
114475
115587
  ctx.status("No percher.toml found — detecting framework...");
114476
115588
  await init(ctx);
114477
115589
  }
@@ -114520,8 +115632,8 @@ function emitPreflight(ctx, config2, tarball) {
114520
115632
  }
114521
115633
  }
114522
115634
  // ../core/dist/commands/push.js
114523
- import { existsSync as existsSync15 } from "node:fs";
114524
- import { join as join23 } from "node:path";
115635
+ import { existsSync as existsSync16 } from "node:fs";
115636
+ import { join as join25 } from "node:path";
114525
115637
  var pushInputSchema = exports_external.object({
114526
115638
  dryRun: exports_external.boolean().optional(),
114527
115639
  force: exports_external.boolean().optional(),
@@ -114532,8 +115644,8 @@ var SUSPICIOUS_BYTES2 = 50 * 1024 * 1024;
114532
115644
  var SUSPICIOUS_FILES2 = 1e4;
114533
115645
  var PLACEHOLDER_PREFIXES = ["add-your-", "your-key-here"];
114534
115646
  async function loadOrGenerate2(ctx) {
114535
- const tomlPath = join23(ctx.cwd, "percher.toml");
114536
- if (!existsSync15(tomlPath)) {
115647
+ const tomlPath = join25(ctx.cwd, "percher.toml");
115648
+ if (!existsSync16(tomlPath)) {
114537
115649
  ctx.status("No percher.toml found — detecting framework...");
114538
115650
  const result = await init(ctx);
114539
115651
  const answer = await ctx.prompt(`Generated percher.toml for ${result.detected?.framework ?? result.detected?.runtime ?? "node"}. Continue? [Y/n]`, { default: "y" });
@@ -114644,7 +115756,7 @@ async function push(ctx, input = {}, internals = {}) {
114644
115756
  fileCount: tarball.fileCount,
114645
115757
  recovery: RECOVERY_NONE,
114646
115758
  summary: `Dry run for ${config2.app.name}: ${tarball.fileCount} files, ${(tarball.bytes / 1024).toFixed(1)} KB — no deploy performed.`,
114647
- configPath: join23(ctx.cwd, "percher.toml"),
115759
+ configPath: join25(ctx.cwd, "percher.toml"),
114648
115760
  bundle: { fileCount: tarball.fileCount, bytes: tarball.bytes }
114649
115761
  };
114650
115762
  }
@@ -114827,7 +115939,7 @@ ${deployment.errorMessage}` : "";
114827
115939
  fileCount: tarball.fileCount,
114828
115940
  recovery: RECOVERY_NONE,
114829
115941
  summary,
114830
- configPath: join23(ctx.cwd, "percher.toml"),
115942
+ configPath: join25(ctx.cwd, "percher.toml"),
114831
115943
  bundle: { fileCount: tarball.fileCount, bytes: tarball.bytes }
114832
115944
  };
114833
115945
  }
@@ -115156,8 +116268,8 @@ function failureResult(error48) {
115156
116268
  };
115157
116269
  }
115158
116270
  // ../core/dist/commands/rename.js
115159
- import { existsSync as existsSync16, readFileSync as readFileSync12, writeFileSync as writeFileSync8 } from "node:fs";
115160
- import { join as join24 } from "node:path";
116271
+ import { existsSync as existsSync17, readFileSync as readFileSync12, writeFileSync as writeFileSync9 } from "node:fs";
116272
+ import { join as join26 } from "node:path";
115161
116273
  var renameInputSchema = exports_external.object({
115162
116274
  app: exports_external.string().optional(),
115163
116275
  name: exports_external.string().min(3).max(40)
@@ -115177,8 +116289,8 @@ async function rename2(ctx, input) {
115177
116289
  };
115178
116290
  }
115179
116291
  function updateLocalTomlName(cwd, oldName, newName) {
115180
- const p = join24(cwd, "percher.toml");
115181
- if (!existsSync16(p))
116292
+ const p = join26(cwd, "percher.toml");
116293
+ if (!existsSync17(p))
115182
116294
  return false;
115183
116295
  try {
115184
116296
  const src = readFileSync12(p, "utf8");
@@ -115187,25 +116299,25 @@ function updateLocalTomlName(cwd, oldName, newName) {
115187
116299
  const next = src.replace(new RegExp(`(name\\s*=\\s*")${oldName}(")`), `$1${newName}$2`);
115188
116300
  if (next === src || parse5(next).app.name !== newName)
115189
116301
  return false;
115190
- writeFileSync8(p, next);
116302
+ writeFileSync9(p, next);
115191
116303
  return true;
115192
116304
  } catch {
115193
116305
  return false;
115194
116306
  }
115195
116307
  }
115196
116308
  // ../core/dist/commands/reproduce.js
115197
- import { mkdtempSync, writeFileSync as writeFileSync9 } from "node:fs";
116309
+ import { mkdtempSync, writeFileSync as writeFileSync10 } from "node:fs";
115198
116310
  import { tmpdir } from "node:os";
115199
- import { join as join25 } from "node:path";
115200
- var import_cross_spawn = __toESM(require_cross_spawn(), 1);
116311
+ import { join as join27 } from "node:path";
116312
+ var import_cross_spawn2 = __toESM(require_cross_spawn(), 1);
115201
116313
  function runProcessExit(cmd, args, opts = {}) {
115202
- return new Promise((resolve9, reject) => {
115203
- const child = import_cross_spawn.default(cmd, args, {
116314
+ return new Promise((resolve11, reject) => {
116315
+ const child = import_cross_spawn2.default(cmd, args, {
115204
116316
  cwd: opts.cwd,
115205
116317
  stdio: opts.inherit ? "inherit" : "ignore"
115206
116318
  });
115207
116319
  child.on("error", reject);
115208
- child.on("close", (code) => resolve9(code ?? 1));
116320
+ child.on("close", (code) => resolve11(code ?? 1));
115209
116321
  });
115210
116322
  }
115211
116323
  var reproduceInputSchema = exports_external.object({
@@ -115291,9 +116403,9 @@ async function reproduce(ctx, input) {
115291
116403
  const envMap = await ctx.client.env.list(app.id);
115292
116404
  currentAppEnvKeys = Object.keys(envMap).sort();
115293
116405
  } catch {}
115294
- const tmpDir = mkdtempSync(join25(tmpdir(), `percher-reproduce-${input.deployId}-`));
115295
- const tarballPath = join25(tmpDir, "source.tar.gz");
115296
- writeFileSync9(tarballPath, bytes);
116406
+ const tmpDir = mkdtempSync(join27(tmpdir(), `percher-reproduce-${input.deployId}-`));
116407
+ const tarballPath = join27(tmpDir, "source.tar.gz");
116408
+ writeFileSync10(tarballPath, bytes);
115297
116409
  let extracted = false;
115298
116410
  try {
115299
116411
  extracted = await runProcessExit("tar", ["-xzf", tarballPath, "-C", tmpDir]) === 0;
@@ -115730,7 +116842,6 @@ var PLAN_CATALOG = {
115730
116842
  priceEur: 0,
115731
116843
  limits: {
115732
116844
  apps: 3,
115733
- deploysPerMonth: 50,
115734
116845
  deploysPerHour: 12,
115735
116846
  memory: "256mb",
115736
116847
  cpu: 0.25,
@@ -115762,7 +116873,6 @@ var PLAN_CATALOG = {
115762
116873
  priceEur: 3,
115763
116874
  limits: {
115764
116875
  apps: 10,
115765
- deploysPerMonth: 200,
115766
116876
  deploysPerHour: 30,
115767
116877
  memory: "512mb",
115768
116878
  cpu: 0.25,
@@ -115794,7 +116904,6 @@ var PLAN_CATALOG = {
115794
116904
  priceEur: 12,
115795
116905
  limits: {
115796
116906
  apps: 20,
115797
- deploysPerMonth: 500,
115798
116907
  deploysPerHour: 60,
115799
116908
  memory: "1gb",
115800
116909
  cpu: 0.5,
@@ -115826,7 +116935,6 @@ var PLAN_CATALOG = {
115826
116935
  priceEur: 29,
115827
116936
  limits: {
115828
116937
  apps: 40,
115829
- deploysPerMonth: "unlimited",
115830
116938
  deploysPerHour: 120,
115831
116939
  memory: "1gb",
115832
116940
  cpu: 1,
@@ -115859,7 +116967,6 @@ var PLAN_CATALOG = {
115859
116967
  hidden: true,
115860
116968
  limits: {
115861
116969
  apps: 1,
115862
- deploysPerMonth: 20,
115863
116970
  deploysPerHour: 6,
115864
116971
  memory: "128mb",
115865
116972
  cpu: 0.25,
@@ -116551,6 +117658,36 @@ function registerAppsCommands(cli, ctx) {
116551
117658
  await writeLine(ctx, `${import_picocolors4.default.green("✓")} wrote ${file2}`);
116552
117659
  }
116553
117660
  });
117661
+ cli.command("appstore-kit", "Write app-store starter files (PWA manifest, TWA/Capacitor, asset links)").option("--name <name>", "App name (defaults to percher.toml / directory)").option("--url <url>", "App URL (defaults to https://<name>.percher.run)").option("--package <pkg>", "Android package name for assetlinks.json").option("--fingerprint <sha256>", "Signing-cert SHA-256 for assetlinks.json").option("--team-id <id>", "Apple Team ID for apple-app-site-association").option("--bundle-id <id>", "Apple bundle ID for apple-app-site-association").option("--out <dir>", "Output directory (defaults to the current directory)").option("--force", "Overwrite files that already exist").action(async (options) => {
117662
+ const result = await appstoreKit(ctx, {
117663
+ name: options.name,
117664
+ url: options.url,
117665
+ packageName: options.package,
117666
+ fingerprint: options.fingerprint,
117667
+ teamId: options.teamId,
117668
+ bundleId: options.bundleId,
117669
+ outDir: options.out,
117670
+ force: options.force
117671
+ });
117672
+ for (const file2 of result.written) {
117673
+ await writeLine(ctx, `${import_picocolors4.default.green("✓")} wrote ${file2}`);
117674
+ }
117675
+ for (const file2 of result.skipped) {
117676
+ await writeLine(ctx, `${import_picocolors4.default.dim("•")} skipped ${file2} (exists — pass --force to overwrite)`);
117677
+ }
117678
+ await writeLine(ctx, "");
117679
+ await writeLine(ctx, `${import_picocolors4.default.bold("Make it an installable PWA:")} link the manifest from your HTML`);
117680
+ await writeLine(ctx, ` <link rel="manifest" href="/manifest.json">`);
117681
+ await writeLine(ctx, "and register the service worker from your app entry:");
117682
+ await writeLine(ctx, result.swRegistration);
117683
+ await writeLine(ctx, "");
117684
+ await writeLine(ctx, `${import_picocolors4.default.bold("Wrap for Google Play (TWA):")}`);
117685
+ await writeLine(ctx, result.bubblewrapCommand);
117686
+ await writeLine(ctx, "");
117687
+ await writeLine(ctx, `The two ${import_picocolors4.default.dim(".well-known")} files are trust assertions for your origin — add real values`);
117688
+ await writeLine(ctx, `after you sign the apps, then serve them yourself or let Percher serve them from the`);
117689
+ await writeLine(ctx, "App store kit at https://percher.app. Full guide: /docs/app-stores");
117690
+ });
116554
117691
  cli.command("publish", "Publish this project to Percher (recommended deploy command)").option("--force", "Skip size warnings").option("--preview", "Deploy as preview (does not replace the live version)").option("-m, --message <msg>", "Deploy note (visible in deploy history)").option("--dry-run", "Show what would be deployed (file count, bytes) without uploading").option("--no-cache", "Skip image-cache lookup and force a fresh build (use when you suspect cached image is stale)").option("--anonymous", "Publish without an account — a 72h sandbox you can claim later (where enabled)").action(async (options) => {
116555
117692
  const { detectCiBranchMessage: detectCiBranchMessage2 } = await Promise.resolve().then(() => exports_ci_env);
116556
117693
  let messageOverride = options.message;
@@ -116632,8 +117769,8 @@ function registerAppsCommands(cli, ctx) {
116632
117769
  deployId,
116633
117770
  timeoutSeconds: Math.min(Math.ceil(remainingMs / 1000), 30)
116634
117771
  }, { signal: callController.signal }),
116635
- new Promise((resolve9) => {
116636
- raceTimer = setTimeout(() => resolve9(null), remainingMs);
117772
+ new Promise((resolve11) => {
117773
+ raceTimer = setTimeout(() => resolve11(null), remainingMs);
116637
117774
  })
116638
117775
  ]);
116639
117776
  } finally {
@@ -117172,7 +118309,7 @@ function registerEnvCommands(cli, ctx) {
117172
118309
  if (action === "set") {
117173
118310
  const { resolveEnvSetInputs: resolveEnvSetInputs2, EnvSetInputError: EnvSetInputError2 } = await Promise.resolve().then(() => (init_env_set_input(), exports_env_set_input));
117174
118311
  const { promptHidden: promptHidden2 } = await Promise.resolve().then(() => (init_prompt_hidden(), exports_prompt_hidden));
117175
- const { readFile: readFile4 } = await import("node:fs/promises");
118312
+ const { readFile: readFile5 } = await import("node:fs/promises");
117176
118313
  try {
117177
118314
  const values = await resolveEnvSetInputs2({
117178
118315
  args,
@@ -117184,7 +118321,7 @@ function registerEnvCommands(cli, ctx) {
117184
118321
  chunks.push(c);
117185
118322
  return Buffer.concat(chunks).toString("utf8");
117186
118323
  },
117187
- readFile: async (p) => readFile4(p, "utf8"),
118324
+ readFile: async (p) => readFile5(p, "utf8"),
117188
118325
  promptHidden: promptHidden2
117189
118326
  });
117190
118327
  await envSet(ctx, { app: options.app, values });
@@ -117298,7 +118435,24 @@ function registerGithubCommands(cli, ctx) {
117298
118435
  // src/commands/migrate.ts
117299
118436
  var import_picocolors11 = __toESM(require_picocolors(), 1);
117300
118437
  function registerMigrateCommands(cli, ctx) {
117301
- 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("--json", "Output the structured result as JSON").action(async (options) => {
118438
+ 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) => {
118439
+ if (options.status) {
118440
+ const result2 = await migrationStatus(ctx, {
118441
+ rootDir: options.root,
118442
+ build: options.build === true,
118443
+ pbIdentifier: options.pbIdentifier
118444
+ });
118445
+ if (options.json) {
118446
+ await writeLine(ctx, JSON.stringify(result2, null, 2));
118447
+ if (result2.status === "failed")
118448
+ throw new SilentExitError(1);
118449
+ return;
118450
+ }
118451
+ await renderStatusHuman(ctx, result2);
118452
+ if (result2.status === "failed")
118453
+ throw new SilentExitError(1);
118454
+ return;
118455
+ }
117302
118456
  const projectRef = options.project;
117303
118457
  const token = options.token ?? ctx.env.SUPABASE_ACCESS_TOKEN;
117304
118458
  if (options.apply && !options.rewriteClient) {
@@ -117335,7 +118489,8 @@ function registerMigrateCommands(cli, ctx) {
117335
118489
  if (options.rewriteClient && result.status === "ok") {
117336
118490
  rewrite = await rewriteSupabaseClient(ctx, {
117337
118491
  rootDir: options.root,
117338
- apply: options.apply === true
118492
+ apply: options.apply === true,
118493
+ scaffoldClient: options.scaffoldClient !== false
117339
118494
  });
117340
118495
  }
117341
118496
  if (options.json) {
@@ -117489,6 +118644,37 @@ ${result.skipped.length} file(s) couldn't be parsed and were skipped — listed
117489
118644
  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."));
117490
118645
  }
117491
118646
  }
118647
+ async function renderStatusHuman(ctx, result) {
118648
+ if (result.status === "failed") {
118649
+ const err = result.error;
118650
+ await writeLine(ctx, `${import_picocolors11.default.red("✗")} ${err?.title ?? "Migration status scan failed"}`);
118651
+ if (err?.explanation)
118652
+ await writeLine(ctx, ` ${err.explanation}`);
118653
+ if (err?.suggestion)
118654
+ await writeLine(ctx, import_picocolors11.default.dim(` ${err.suggestion}`));
118655
+ return;
118656
+ }
118657
+ await writeLine(ctx, import_picocolors11.default.bold("Migration status"));
118658
+ await writeLine(ctx, "");
118659
+ for (const check2 of result.checks) {
118660
+ 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("•");
118661
+ const count = check2.count > 0 ? import_picocolors11.default.dim(` (${check2.count})`) : "";
118662
+ await writeLine(ctx, ` ${mark} ${check2.label}${count} ${import_picocolors11.default.dim(`— ${check2.detail}`)}`);
118663
+ for (const file2 of (check2.files ?? []).slice(0, 10)) {
118664
+ await writeLine(ctx, import_picocolors11.default.dim(` - ${file2}`));
118665
+ }
118666
+ if ((check2.files?.length ?? 0) > 10) {
118667
+ await writeLine(ctx, import_picocolors11.default.dim(` …and ${(check2.files?.length ?? 0) - 10} more`));
118668
+ }
118669
+ }
118670
+ if (result.build) {
118671
+ await writeLine(ctx, "");
118672
+ const mark = !result.build.ran ? import_picocolors11.default.dim("•") : result.build.passed ? import_picocolors11.default.green("✓") : import_picocolors11.default.red("✗");
118673
+ await writeLine(ctx, ` ${mark} Build ${import_picocolors11.default.dim(`— ${result.build.detail}`)}`);
118674
+ }
118675
+ await writeLine(ctx, "");
118676
+ await writeLine(ctx, import_picocolors11.default.dim(result.summary));
118677
+ }
117492
118678
 
117493
118679
  // src/commands/sharing.ts
117494
118680
  var import_picocolors12 = __toESM(require_picocolors(), 1);
@@ -117828,7 +119014,7 @@ async function renderError(stderr, error48) {
117828
119014
  // package.json
117829
119015
  var package_default = {
117830
119016
  name: "percher",
117831
- version: "0.5.7",
119017
+ version: "0.5.9",
117832
119018
  description: "CLI for the Percher hosting platform — publish apps with one command",
117833
119019
  type: "module",
117834
119020
  bin: {
@@ -117909,18 +119095,18 @@ async function showTelemetryNotice() {
117909
119095
  if (isDisabled())
117910
119096
  return;
117911
119097
  const { homedir: homedir2 } = await import("node:os");
117912
- const { existsSync: existsSync17, mkdirSync: mkdirSync6, writeFileSync: writeFileSync10 } = await import("node:fs");
117913
- const { join: join26 } = await import("node:path");
117914
- const configDir = join26(homedir2(), ".percher");
117915
- const markerFile = join26(configDir, ".telemetry-notice-shown");
117916
- if (existsSync17(markerFile))
119098
+ const { existsSync: existsSync18, mkdirSync: mkdirSync7, writeFileSync: writeFileSync11 } = await import("node:fs");
119099
+ const { join: join28 } = await import("node:path");
119100
+ const configDir = join28(homedir2(), ".percher");
119101
+ const markerFile = join28(configDir, ".telemetry-notice-shown");
119102
+ if (existsSync18(markerFile))
117917
119103
  return;
117918
119104
  console.log("Percher sends non-account-linked usage stats (command, result, error type, OS, Bun version).");
117919
119105
  console.log(`Disable with PERCHER_NO_TELEMETRY=1
117920
119106
  `);
117921
119107
  try {
117922
- mkdirSync6(configDir, { recursive: true });
117923
- writeFileSync10(markerFile, new Date().toISOString());
119108
+ mkdirSync7(configDir, { recursive: true });
119109
+ writeFileSync11(markerFile, new Date().toISOString());
117924
119110
  } catch {}
117925
119111
  }
117926
119112