@patchstack/connect 0.5.23 → 0.5.25

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.
package/dist/cli.js CHANGED
@@ -3,7 +3,7 @@
3
3
  // src/cli.ts
4
4
  import { readFileSync as readFileSync19 } from "fs";
5
5
  import path16 from "path";
6
- import { createRequire as createRequire2 } from "module";
6
+ import { createRequire as createRequire3 } from "module";
7
7
 
8
8
  // src/safe-file.ts
9
9
  import {
@@ -3179,7 +3179,7 @@ function ensureSourceMarker(cwd, shell, framework, checksum = null) {
3179
3179
  }
3180
3180
 
3181
3181
  // src/guide.ts
3182
- import { existsSync as existsSync12, readFileSync as readFileSync11, readdirSync as readdirSync5, statSync as statSync5 } from "fs";
3182
+ import { existsSync as existsSync12, readFileSync as readFileSync11, readdirSync as readdirSync6, statSync as statSync5 } from "fs";
3183
3183
  import path12 from "path";
3184
3184
 
3185
3185
  // src/architecture.ts
@@ -3815,8 +3815,8 @@ function staticSignals(cwd, ts) {
3815
3815
  signals.push({ signal: "static-generator", source: "astro (no SSR adapter)" });
3816
3816
  }
3817
3817
  if (deps["next"] !== void 0) {
3818
- const exported = nextExportsStatically(cwd, manifest, ts);
3819
- if (exported !== null) signals.push({ signal: "static-generator", source: `next: ${exported}` });
3818
+ const exported2 = nextExportsStatically(cwd, manifest, ts);
3819
+ if (exported2 !== null) signals.push({ signal: "static-generator", source: `next: ${exported2}` });
3820
3820
  }
3821
3821
  return signals;
3822
3822
  }
@@ -3937,12 +3937,12 @@ function serverEntries(cwd, manifest) {
3937
3937
  if (!main2.startsWith("..")) candidates.add(main2);
3938
3938
  }
3939
3939
  const found = [];
3940
- for (const relative8 of candidates) {
3941
- const file = path10.join(cwd, relative8);
3940
+ for (const relative9 of candidates) {
3941
+ const file = path10.join(cwd, relative9);
3942
3942
  try {
3943
3943
  if (!existsSync2(file) || !statSync4(file).isFile()) continue;
3944
3944
  const text = readFileSync6(file, "utf8").slice(0, MAX_ENTRY_BYTES);
3945
- if (SERVING_CALL.test(text)) found.push(relative8);
3945
+ if (SERVING_CALL.test(text)) found.push(relative9);
3946
3946
  } catch {
3947
3947
  }
3948
3948
  }
@@ -4272,90 +4272,459 @@ var tanstackSupabaseAdapter = {
4272
4272
  };
4273
4273
 
4274
4274
  // src/protect/install/adapters/next.ts
4275
- import { existsSync as existsSync5 } from "fs";
4275
+ import { existsSync as existsSync5, lstatSync as lstatSync2, readdirSync as readdirSync3 } from "fs";
4276
+ import { dirname as dirname3, join as join8, relative as relative3 } from "path";
4277
+
4278
+ // src/protect/install/adapters/next-source.ts
4279
+ import { createRequire } from "module";
4276
4280
  import { join as join7 } from "path";
4281
+ var NEXT_MARKER = "// #region patchstack-next-composed";
4282
+ var ROUTE_MARKER = "// #region patchstack-next-route";
4283
+ var METHODS = /* @__PURE__ */ new Set(["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"]);
4284
+ function nextCompiler(cwd) {
4285
+ for (const base of [join7(cwd, "package.json"), import.meta.url]) {
4286
+ try {
4287
+ return createRequire(base)("typescript");
4288
+ } catch {
4289
+ }
4290
+ }
4291
+ return null;
4292
+ }
4293
+ function parse(ts, file, source) {
4294
+ const sf = ts.createSourceFile(file, source, ts.ScriptTarget.Latest, true);
4295
+ return sf.parseDiagnostics.length ? null : sf;
4296
+ }
4297
+ function exported(ts, node) {
4298
+ return ts.canHaveModifiers(node) && !!ts.getModifiers(node)?.some((m) => m.kind === ts.SyntaxKind.ExportKeyword);
4299
+ }
4300
+ function apply(source, edits) {
4301
+ for (const edit of edits.sort((a, b) => b.start - a.start)) {
4302
+ source = source.slice(0, edit.start) + edit.text + source.slice(edit.end);
4303
+ }
4304
+ return source;
4305
+ }
4306
+ function handlers(ts, sf, names) {
4307
+ const out = [];
4308
+ for (const s of sf.statements) {
4309
+ if (!exported(ts, s)) continue;
4310
+ if (ts.isFunctionDeclaration(s) && s.name && names.has(s.name.text)) out.push(s);
4311
+ if (ts.isVariableStatement(s)) {
4312
+ for (const d of s.declarationList.declarations) {
4313
+ if (ts.isIdentifier(d.name) && names.has(d.name.text) && d.initializer && (ts.isArrowFunction(d.initializer) || ts.isFunctionExpression(d.initializer))) out.push(d.initializer);
4314
+ }
4315
+ }
4316
+ }
4317
+ return out;
4318
+ }
4319
+ function methodExportCount(ts, sf) {
4320
+ return sf.statements.filter((s) => exported(ts, s)).flatMap((s) => {
4321
+ if (ts.isFunctionDeclaration(s)) return s.name ? [s.name.text] : [];
4322
+ if (ts.isVariableStatement(s)) return s.declarationList.declarations.map((d) => d.name.getText(sf));
4323
+ return [];
4324
+ }).filter((n) => METHODS.has(n)).length;
4325
+ }
4326
+ function standardNextRouting(ts, file, source) {
4327
+ const sf = parse(ts, file, source);
4328
+ if (!sf) return false;
4329
+ const objects = /* @__PURE__ */ new Map();
4330
+ let target;
4331
+ for (const s of sf.statements) {
4332
+ if (ts.isImportDeclaration(s) && s.importClause?.isTypeOnly) continue;
4333
+ if (ts.isVariableStatement(s) && s.declarationList.flags & ts.NodeFlags.Const) {
4334
+ for (const d of s.declarationList.declarations) {
4335
+ if (!ts.isIdentifier(d.name) || !d.initializer) return false;
4336
+ objects.set(d.name.text, d.initializer);
4337
+ }
4338
+ } else if (ts.isExportAssignment(s) && !s.isExportEquals && !target) target = s.expression;
4339
+ else return false;
4340
+ }
4341
+ const unwrap = (expr) => {
4342
+ while (ts.isAsExpression(expr) || ts.isSatisfiesExpression(expr) || ts.isParenthesizedExpression(expr)) expr = expr.expression;
4343
+ return expr;
4344
+ };
4345
+ if (!target) return false;
4346
+ target = unwrap(target);
4347
+ if (ts.isIdentifier(target)) target = objects.get(target.text);
4348
+ if (!target) return false;
4349
+ target = unwrap(target);
4350
+ if (!ts.isObjectLiteralExpression(target)) return false;
4351
+ const literal = (node) => {
4352
+ const expr = unwrap(node);
4353
+ if (ts.isStringLiteral(expr) || ts.isNumericLiteral(expr) || [ts.SyntaxKind.TrueKeyword, ts.SyntaxKind.FalseKeyword, ts.SyntaxKind.NullKeyword].includes(expr.kind)) return true;
4354
+ if (ts.isArrayLiteralExpression(expr)) return expr.elements.every(literal);
4355
+ if (ts.isObjectLiteralExpression(expr)) return expr.properties.every((p) => ts.isPropertyAssignment(p) && (ts.isIdentifier(p.name) || ts.isStringLiteral(p.name)) && literal(p.initializer));
4356
+ return false;
4357
+ };
4358
+ if (!literal(target) || ![...objects.values()].every(literal)) return false;
4359
+ return target.properties.every((p) => p.name && !["basePath", "i18n", "skipMiddlewareUrlNormalize", "pageExtensions", "__proto__"].includes(
4360
+ ts.isIdentifier(p.name) || ts.isStringLiteral(p.name) ? p.name.text : ""
4361
+ ));
4362
+ }
4363
+ function matcherRegex(value) {
4364
+ if (value === "/:path*") return "^/";
4365
+ if (!/^\/[\w-]+(?:\/[\w-]+)*(?:\/:\w+\*)?$/.test(value)) return null;
4366
+ const catchAll = /\/:\w+\*$/.test(value);
4367
+ const prefix = value.replace(/\/:\w+\*$/, "");
4368
+ return `^(?:/_next/data/[^/]+)?${prefix}${catchAll ? "(?:/.*)?" : ""}(?:\\.json)?/?$`;
4369
+ }
4370
+ function middlewareScope(ts, sf) {
4371
+ const configs = sf.statements.filter((s) => ts.isVariableStatement(s) && exported(ts, s)).flatMap((s) => [...s.declarationList.declarations]).filter((d) => ts.isIdentifier(d.name) && d.name.text === "config");
4372
+ if (!configs.length) {
4373
+ if (sf.statements.some((s) => ts.isExportDeclaration(s))) return null;
4374
+ return { tests: [], edits: [] };
4375
+ }
4376
+ const config = configs[0]?.initializer;
4377
+ if (configs.length !== 1 || !config || !ts.isObjectLiteralExpression(config)) return null;
4378
+ if (config.properties.some((p) => !ts.isPropertyAssignment(p) || !ts.isIdentifier(p.name))) return null;
4379
+ const matcher = config.properties.find((p) => p.name?.getText(sf) === "matcher");
4380
+ if (!matcher) return { tests: [], edits: [] };
4381
+ const values = ts.isArrayLiteralExpression(matcher.initializer) ? [...matcher.initializer.elements] : [matcher.initializer];
4382
+ if (!values.length || !values.every((v) => ts.isStringLiteral(v))) return null;
4383
+ const tests = values.map((v) => matcherRegex(v.text));
4384
+ if (tests.some((v) => v === null)) return null;
4385
+ return {
4386
+ tests,
4387
+ edits: [{ start: matcher.initializer.getStart(sf), end: matcher.initializer.end, text: '"/:path*"' }]
4388
+ };
4389
+ }
4390
+ function requestName(ts, fn) {
4391
+ const param = fn.parameters[0];
4392
+ if (!param) return "psRequest";
4393
+ if (!ts.isIdentifier(param.name) || param.dotDotDotToken || param.initializer || param.questionToken) return null;
4394
+ return param.name.text;
4395
+ }
4396
+ function requestParameter(fn, file) {
4397
+ return fn.parameters.length ? [] : [{
4398
+ start: fn.parameters.pos,
4399
+ end: fn.parameters.pos,
4400
+ text: file.endsWith(".ts") ? "psRequest: Request" : "psRequest"
4401
+ }];
4402
+ }
4403
+ function importPosition(ts, sf) {
4404
+ let position = 0;
4405
+ for (const statement of sf.statements) {
4406
+ if (!ts.isExpressionStatement(statement) || !ts.isStringLiteral(statement.expression)) break;
4407
+ position = statement.end;
4408
+ }
4409
+ return position;
4410
+ }
4411
+ function prelude(request, marker) {
4412
+ return `
4413
+ ${marker}
4414
+ const psProtection = await getPatchstackProtection();
4415
+ const psBlocked = psProtection && await psProtection.fetchGuard()(${request});
4416
+ if (psBlocked) return psBlocked;
4417
+ // #endregion
4418
+ `;
4419
+ }
4420
+ function composeNextMiddleware(ts, file, source, guardImport) {
4421
+ const sf = parse(ts, file, source);
4422
+ if (!sf || /\b(?:psProtection|psBlocked|psRequest|getPatchstackProtection)\b/.test(source)) return null;
4423
+ const found = handlers(ts, sf, /* @__PURE__ */ new Set(["middleware"]));
4424
+ if (found.length !== 1 || sf.statements.some((s) => ts.isExportAssignment(s) || ts.isExportDeclaration(s))) return null;
4425
+ const fn = found[0];
4426
+ const request = requestName(ts, fn);
4427
+ const scope = middlewareScope(ts, sf);
4428
+ if (!request || !scope || !fn.body || !ts.isBlock(fn.body) || fn.asteriskToken || fn.type) return null;
4429
+ const edits = [...scope.edits, ...requestParameter(fn, file)];
4430
+ const isAsync = fn.modifiers?.some((m) => m.kind === ts.SyntaxKind.AsyncKeyword);
4431
+ if (!isAsync) {
4432
+ const start = ts.isFunctionDeclaration(fn) ? fn.getChildren(sf).find((n) => n.kind === ts.SyntaxKind.FunctionKeyword).getStart(sf) : fn.getStart(sf);
4433
+ edits.push({ start, end: start, text: "async " });
4434
+ }
4435
+ const scopeCheck = scope.tests.length ? ` if (!${JSON.stringify(scope.tests)}.some(pattern => new RegExp(pattern).test(new URL(${request}.url).pathname))) return;
4436
+ ` : "";
4437
+ edits.push({ start: fn.body.getStart(sf) + 1, end: fn.body.getStart(sf) + 1, text: prelude(request, NEXT_MARKER) + scopeCheck });
4438
+ const position = importPosition(ts, sf);
4439
+ edits.push({ start: position, end: position, text: `
4440
+ import { getPatchstackProtection } from ${JSON.stringify(guardImport)};
4441
+ ` });
4442
+ return apply(source, edits);
4443
+ }
4444
+ function composeNextRoute(ts, file, source, guardImport) {
4445
+ const sf = parse(ts, file, source);
4446
+ if (!sf || /\b(?:psProtection|psBlocked|psRequest|getPatchstackProtection|screenPatchstackResponse)\b/.test(source)) return null;
4447
+ const found = handlers(ts, sf, METHODS);
4448
+ if (!found.length || sf.statements.some((s) => ts.isExportDeclaration(s) || ts.isExportAssignment(s))) return null;
4449
+ if (methodExportCount(ts, sf) !== found.length) return null;
4450
+ const edits = [];
4451
+ for (const fn of found) {
4452
+ const request = requestName(ts, fn);
4453
+ if (!request || !fn.body || !ts.isBlock(fn.body) || fn.asteriskToken || fn.type || !fn.modifiers?.some((m) => m.kind === ts.SyntaxKind.AsyncKeyword)) return null;
4454
+ const returns = [];
4455
+ const visit = (node) => {
4456
+ if (ts.isFunctionLike(node)) return;
4457
+ if (ts.isReturnStatement(node)) returns.push(node);
4458
+ ts.forEachChild(node, visit);
4459
+ };
4460
+ visit(fn.body);
4461
+ if (!returns.length || returns.some((r) => !r.expression)) return null;
4462
+ for (const r of returns) {
4463
+ const expr = r.expression;
4464
+ edits.push({
4465
+ start: expr.getStart(sf),
4466
+ end: expr.end,
4467
+ text: `screenPatchstackResponse((${expr.getText(sf)}), ${request}, psProtection)`
4468
+ });
4469
+ }
4470
+ edits.push(...requestParameter(fn, file));
4471
+ edits.push({ start: fn.body.getStart(sf) + 1, end: fn.body.getStart(sf) + 1, text: prelude(request, ROUTE_MARKER) });
4472
+ }
4473
+ const position = importPosition(ts, sf);
4474
+ edits.push({ start: position, end: position, text: `
4475
+ import { getPatchstackProtection, screenPatchstackResponse } from ${JSON.stringify(guardImport)};
4476
+ ` });
4477
+ return apply(source, edits);
4478
+ }
4479
+ function nextSourceWired(ts, file, source, guardImport, route = false) {
4480
+ const sf = parse(ts, file, source);
4481
+ if (!sf) return false;
4482
+ const imported = sf.statements.some((s) => ts.isImportDeclaration(s) && ts.isStringLiteral(s.moduleSpecifier) && s.moduleSpecifier.text === guardImport && s.importClause?.namedBindings && ts.isNamedImports(s.importClause.namedBindings) && s.importClause.namedBindings.elements.some((e) => !e.propertyName && e.name.text === "getPatchstackProtection"));
4483
+ if (!imported) return false;
4484
+ if (route && !sf.statements.some((s) => ts.isImportDeclaration(s) && ts.isStringLiteral(s.moduleSpecifier) && s.moduleSpecifier.text === guardImport && s.importClause?.namedBindings && ts.isNamedImports(s.importClause.namedBindings) && s.importClause.namedBindings.elements.some((e) => !e.propertyName && e.name.text === "screenPatchstackResponse"))) return false;
4485
+ const found = handlers(ts, sf, route ? METHODS : /* @__PURE__ */ new Set(["middleware"]));
4486
+ if (!found.length || sf.statements.some((s) => ts.isExportDeclaration(s) || ts.isExportAssignment(s))) return false;
4487
+ if (route && methodExportCount(ts, sf) !== found.length) return false;
4488
+ const compact = (text) => text.replace(/\s+/g, "");
4489
+ for (const fn of found) {
4490
+ const request = requestName(ts, fn);
4491
+ if (!request || !fn.body || !ts.isBlock(fn.body)) return false;
4492
+ const head = fn.body.statements.slice(0, 3).map((s) => s.getText(sf)).join("");
4493
+ const expected = `const psProtection = await getPatchstackProtection();
4494
+ const psBlocked = psProtection && await psProtection.fetchGuard()(${request});
4495
+ if (psBlocked) return psBlocked;`;
4496
+ if (compact(head) !== compact(expected)) return false;
4497
+ if (route) {
4498
+ let covered = true;
4499
+ const visit = (node) => {
4500
+ if (ts.isFunctionLike(node)) return;
4501
+ if (ts.isReturnStatement(node) && node.expression?.getText(sf) !== "psBlocked") {
4502
+ const expr = node.expression;
4503
+ if (!expr || !ts.isCallExpression(expr) || expr.expression.getText(sf) !== "screenPatchstackResponse" || expr.arguments[1]?.getText(sf) !== request || expr.arguments[2]?.getText(sf) !== "psProtection") covered = false;
4504
+ }
4505
+ ts.forEachChild(node, visit);
4506
+ };
4507
+ visit(fn.body);
4508
+ if (!covered) return false;
4509
+ }
4510
+ }
4511
+ if (!route) {
4512
+ const scope = middlewareScope(ts, sf);
4513
+ if (!scope || scope.tests.some((test) => test !== "^/")) return false;
4514
+ }
4515
+ return true;
4516
+ }
4517
+
4518
+ // src/protect/install/adapters/next.ts
4277
4519
  function middlewareInfo(cwd) {
4278
4520
  const candidates = ["middleware.ts", "middleware.js", "src/middleware.ts", "src/middleware.js"];
4279
- for (const rel of candidates) {
4280
- if (existsSync5(join7(cwd, rel))) return { relDir: rel.includes("/") ? "src" : ".", relFile: rel, exists: true };
4521
+ const relFile = candidates.find((rel) => existsSync5(join8(cwd, rel))) ?? (existsSync5(join8(cwd, "src")) ? "src/middleware.ts" : "middleware.ts");
4522
+ return { relFile, relDir: dirname3(relFile), exists: existsSync5(join8(cwd, relFile)) };
4523
+ }
4524
+ function proxyFiles(cwd) {
4525
+ return ["proxy.ts", "proxy.js", "src/proxy.ts", "src/proxy.js"].filter((file) => existsSync5(join8(cwd, file)));
4526
+ }
4527
+ function paths(cwd) {
4528
+ const mw = middlewareInfo(cwd);
4529
+ const ext = mw.relFile.endsWith(".js") ? "js" : "ts";
4530
+ return { ...mw, rules: join8(mw.relDir, "patchstack.rules.json"), guard: join8(mw.relDir, `patchstack.next.${ext}`) };
4531
+ }
4532
+ function importFrom(file, guard) {
4533
+ const rel = relative3(dirname3(file), guard).replace(/\\/g, "/").replace(/\.ts$/, "");
4534
+ return rel.startsWith(".") ? rel : `./${rel}`;
4535
+ }
4536
+ function routes(cwd) {
4537
+ const files = [];
4538
+ let incomplete = false;
4539
+ let visited = 0;
4540
+ const walk2 = (rel) => {
4541
+ if (++visited > 5e3) {
4542
+ incomplete = true;
4543
+ return;
4544
+ }
4545
+ const full = join8(cwd, rel);
4546
+ if (lstatSync2(full).isSymbolicLink()) {
4547
+ incomplete = true;
4548
+ return;
4549
+ }
4550
+ for (const entry of readdirSync3(full, { withFileTypes: true })) {
4551
+ if (entry.name.startsWith("_") || entry.name.startsWith(".") || entry.name === "node_modules") continue;
4552
+ if (entry.isSymbolicLink()) {
4553
+ incomplete = true;
4554
+ continue;
4555
+ }
4556
+ const child = join8(rel, entry.name);
4557
+ if (entry.isDirectory()) walk2(child);
4558
+ else if (entry.isFile() && /^route\.(?:tsx?|jsx?)$/.test(entry.name)) files.push(child);
4559
+ }
4560
+ };
4561
+ for (const root of ["app", "src/app"]) {
4562
+ if (!existsSync5(join8(cwd, root))) continue;
4563
+ if (root.startsWith("src/") && lstatSync2(join8(cwd, "src")).isSymbolicLink()) {
4564
+ incomplete = true;
4565
+ continue;
4566
+ }
4567
+ try {
4568
+ walk2(root);
4569
+ } catch {
4570
+ incomplete = true;
4571
+ }
4281
4572
  }
4282
- const useSrc = existsSync5(join7(cwd, "src"));
4283
- return { relDir: useSrc ? "src" : ".", relFile: useSrc ? "src/middleware.ts" : "middleware.ts", exists: false };
4573
+ return { files: files.sort(), incomplete };
4284
4574
  }
4285
- function detect2(cwd) {
4286
- return hasDependency(cwd, "next");
4575
+ function customRouting(cwd, ts) {
4576
+ return ["js", "mjs", "ts", "cjs"].some((ext) => {
4577
+ const file = join8(cwd, `next.config.${ext}`);
4578
+ return existsSync5(file) && !standardNextRouting(ts, file, read(file));
4579
+ });
4287
4580
  }
4288
- function rulesFile(relDir) {
4289
- return relDir === "." ? "patchstack.rules.json" : `${relDir}/patchstack.rules.json`;
4581
+ function sharedGuardPresent(file) {
4582
+ if (!existsSync5(file)) return false;
4583
+ const source = read(file);
4584
+ return source.includes("export async function getPatchstackProtection") && source.includes("export async function screenPatchstackResponse") && source.includes('import { createProtection } from "@patchstack/connect/protect"');
4290
4585
  }
4291
4586
  function wire2(cwd, opts) {
4587
+ const proxies = proxyFiles(cwd);
4588
+ if (proxies.length) {
4589
+ log(`left ${proxies.join(", ")} untouched: Next.js proxy integration requires manual wiring. Do not add middleware alongside a proxy; protect --check reports this gap.`);
4590
+ return { ok: false, changed: [] };
4591
+ }
4292
4592
  const templates = templatesDir();
4293
- const mw = middlewareInfo(cwd);
4294
- const dir = join7(cwd, mw.relDir === "." ? "" : mw.relDir);
4295
- ensureProjectDirectorySync(cwd, dir);
4296
- const rulesDst = join7(dir, "patchstack.rules.json");
4593
+ const mw = paths(cwd);
4594
+ ensureProjectDirectorySync(cwd, join8(cwd, mw.relDir));
4297
4595
  const changed = [];
4298
- if (opts.demo || !existsSync5(rulesDst)) {
4299
- copyProjectFileSync(cwd, join7(templates, opts.demo ? "demo-rules.json" : "rules.json"), rulesDst);
4300
- changed.push(rulesFile(mw.relDir));
4301
- }
4302
- const mwPath = join7(cwd, mw.relFile);
4303
- const existing = mw.exists ? read(mwPath) : "";
4304
- if (mw.exists && existing.includes("patchstack-next")) {
4305
- log(`${mw.relFile} already has the Patchstack middleware \u2014 left as-is`);
4306
- return { ok: true, changed };
4596
+ if (opts.demo || !existsSync5(join8(cwd, mw.rules))) {
4597
+ copyProjectFileSync(cwd, join8(templates, opts.demo ? "demo-rules.json" : "rules.json"), join8(cwd, mw.rules));
4598
+ changed.push(mw.rules);
4599
+ }
4600
+ const ts = nextCompiler(cwd);
4601
+ const guardPath = join8(cwd, mw.guard);
4602
+ const guardConflict = existsSync5(guardPath) && !sharedGuardPresent(guardPath);
4603
+ const ensureGuard = () => {
4604
+ if (existsSync5(guardPath)) return;
4605
+ const source = read(join8(templates, "next-guard.ts"));
4606
+ writeProjectFileSync(cwd, guardPath, mw.guard.endsWith(".js") ? ts.transpileModule(source, { compilerOptions: { target: ts.ScriptTarget.ES2022, module: ts.ModuleKind.ESNext } }).outputText : source);
4607
+ if (!opts.demo) bakeSiteUuid(cwd, mw.guard);
4608
+ changed.push(mw.guard);
4609
+ };
4610
+ const existing = mw.exists ? read(join8(cwd, mw.relFile)) : "";
4611
+ if (!mw.exists) {
4612
+ copyProjectFileSync(cwd, join8(templates, "next-middleware.ts"), join8(cwd, mw.relFile));
4613
+ if (!opts.demo) bakeSiteUuid(cwd, mw.relFile);
4614
+ changed.push(mw.relFile);
4615
+ log(`scaffolded ${mw.relFile} (request-phase guard)`);
4616
+ } else if (existing.includes(NEXT_MARKER) || existing.includes("#region patchstack-next (")) {
4617
+ log(`${mw.relFile} already has a Patchstack guard \u2014 left as-is`);
4618
+ if (ts && existing.includes(NEXT_MARKER)) ensureGuard();
4619
+ } else {
4620
+ const composed = ts && !guardConflict && !customRouting(cwd, ts) && composeNextMiddleware(ts, mw.relFile, existing, importFrom(mw.relFile, mw.guard));
4621
+ if (composed) {
4622
+ ensureGuard();
4623
+ writeProjectFileSync(cwd, join8(cwd, mw.relFile), composed);
4624
+ changed.push(mw.relFile);
4625
+ log(`composed ${mw.relFile}: request guard first; existing middleware keeps its original matcher scope`);
4626
+ } else {
4627
+ log(`left ${mw.relFile} untouched: middleware/export/matcher shape needs manual integration${ts ? "" : " (install typescript to enable source-aware composition)"}. Add a guard before application middleware and preserve its routing scope; protect --check reports this gap.`);
4628
+ }
4307
4629
  }
4308
- if (mw.exists) {
4309
- log(
4310
- `existing ${mw.relFile} left untouched \u2014 scaffolded ${rulesFile(mw.relDir)}; add the guard to your middleware: import { createProtection } from "@patchstack/connect/protect", run fetchGuard() on the request, and return the block Response. Then: npx patchstack-connect protect --check`
4311
- );
4312
- return { ok: true, changed };
4630
+ const inventory = routes(cwd);
4631
+ for (const file of inventory.files) {
4632
+ const source = read(join8(cwd, file));
4633
+ if (source.includes(ROUTE_MARKER)) {
4634
+ if (ts) ensureGuard();
4635
+ continue;
4636
+ }
4637
+ const composed = ts && !guardConflict && /\.(?:ts|js)$/.test(file) && composeNextRoute(ts, file, source, importFrom(file, mw.guard));
4638
+ if (composed) {
4639
+ ensureGuard();
4640
+ writeProjectFileSync(cwd, join8(cwd, file), composed);
4641
+ changed.push(file);
4642
+ log(`wired ${file} (request checks + response filtering)`);
4643
+ } else {
4644
+ log(`left ${file} untouched: wrap its request and final Response manually; protect --check reports this response-filtering gap.`);
4645
+ }
4313
4646
  }
4314
- copyProjectFileSync(cwd, join7(templates, "next-middleware.ts"), mwPath);
4315
- if (!opts.demo) bakeSiteUuid(cwd, mw.relFile);
4316
- changed.push(mw.relFile);
4317
- log(`scaffolded ${mw.relFile} (Patchstack middleware)`);
4647
+ if (guardConflict) log(`${mw.guard} already exists but is not a recognized helper \u2014 left untouched; resolve the filename conflict before integrating handlers.`);
4648
+ if (inventory.incomplete) log("App Router inventory was incomplete \u2014 review skipped paths manually.");
4649
+ log("Next middleware cannot inspect downstream response bodies. Route-handler filtering does not cover rendered pages, Server Actions, or Pages API routes. Keep Next.js patched: a middleware bypass also bypasses a middleware guard.");
4318
4650
  return { ok: true, changed: [...new Set(changed)] };
4319
4651
  }
4320
4652
  function verify2(cwd) {
4321
- const mw = middlewareInfo(cwd);
4322
- const present2 = mw.exists && read(join7(cwd, mw.relFile)).includes("patchstack-next");
4323
- const rulesPresent = existsSync5(join7(cwd, rulesFile(mw.relDir)));
4653
+ const proxies = proxyFiles(cwd);
4654
+ if (proxies.length) return {
4655
+ wired: false,
4656
+ checks: [{
4657
+ label: "Next.js proxy wiring requires manual verification",
4658
+ ok: false,
4659
+ hint: `review ${proxies.join(", ")}; automatic proxy integration is not supported. Next.js cannot use middleware and proxy together.`
4660
+ }]
4661
+ };
4662
+ const mw = paths(cwd);
4663
+ const ts = nextCompiler(cwd);
4664
+ const source = mw.exists ? read(join8(cwd, mw.relFile)) : "";
4665
+ const shared = sharedGuardPresent(join8(cwd, mw.guard));
4666
+ const legacy = source.includes("#region patchstack-next (") && source.includes("await protection.fetchGuard()(request)") && source.includes("if (blocked) return blocked") && source.includes('matcher: "/:path*"');
4667
+ const composed = ts && shared && !customRouting(cwd, ts) && nextSourceWired(ts, mw.relFile, source, importFrom(mw.relFile, mw.guard));
4668
+ const present2 = !!(legacy || composed);
4669
+ const rulesPresent = existsSync5(join8(cwd, mw.rules));
4670
+ const inventory = routes(cwd);
4671
+ const missing = inventory.files.filter((file) => !(ts && shared && nextSourceWired(ts, file, read(join8(cwd, file)), importFrom(file, mw.guard), true)));
4324
4672
  return {
4325
- wired: present2 && rulesPresent,
4673
+ wired: present2 && rulesPresent && missing.length === 0 && !inventory.incomplete,
4326
4674
  checks: [
4327
- { label: "Patchstack middleware present", ok: present2, hint: `run \`patchstack-connect protect\` (writes ${mw.relFile})` },
4328
- { label: "rules co-located with the middleware", ok: rulesPresent, hint: "run `patchstack-connect protect`" }
4675
+ {
4676
+ label: "Next middleware request guard has a catch-all matcher",
4677
+ ok: present2,
4678
+ hint: `run \`patchstack-connect protect\`; review any unsupported middleware shape in ${mw.relFile}`
4679
+ },
4680
+ { label: "fallback rules co-located with the guard", ok: rulesPresent, hint: "run `patchstack-connect protect`" },
4681
+ {
4682
+ label: `App Router request/response wiring: ${inventory.files.length - missing.length}/${inventory.files.length} route files`,
4683
+ ok: missing.length === 0 && !inventory.incomplete,
4684
+ hint: `run protect again after adding routes; manually integrate unsupported handlers: ${missing.join(", ") || "inventory incomplete"}`
4685
+ },
4686
+ {
4687
+ label: "rendered pages, Server Actions and Pages API response filtering are not verified",
4688
+ ok: true,
4689
+ unverifiable: true,
4690
+ hint: "middleware cannot screen the downstream response; use a supported server boundary or add response filtering to those handlers"
4691
+ },
4692
+ {
4693
+ label: "live rule delivery and enforcement are not established by source inspection",
4694
+ ok: true,
4695
+ unverifiable: true,
4696
+ hint: "inspect the running guard\u2019s ruleSource and mode; a request reaching middleware does not prove rules were fetched, accepted, or enforced. Framework middleware bypasses require a patched Next.js or upstream protection."
4697
+ }
4329
4698
  ]
4330
4699
  };
4331
4700
  }
4332
4701
  var nextAdapter = {
4333
4702
  name: "nextjs",
4334
4703
  label: "Next.js",
4335
- detect: detect2,
4704
+ detect: (cwd) => hasDependency(cwd, "next"),
4336
4705
  wire: wire2,
4337
4706
  verify: verify2
4338
4707
  };
4339
4708
 
4340
4709
  // src/protect/install/seam.ts
4341
4710
  import { existsSync as existsSync6 } from "fs";
4342
- import { join as join8, dirname as dirname3 } from "path";
4711
+ import { join as join9, dirname as dirname4 } from "path";
4343
4712
  function rulesRel(seamRel) {
4344
- const d = dirname3(seamRel);
4713
+ const d = dirname4(seamRel);
4345
4714
  return (d === "." ? "patchstack.rules.json" : `${d}/patchstack.rules.json`).replace(/\\/g, "/");
4346
4715
  }
4347
4716
  function wireSeam(cwd, opts, spec) {
4348
4717
  const templates = templatesDir();
4349
- const existing = spec.candidates.find((c) => existsSync6(join8(cwd, c)));
4718
+ const existing = spec.candidates.find((c) => existsSync6(join9(cwd, c)));
4350
4719
  const seamRel = existing ?? spec.target;
4351
- ensureProjectDirectorySync(cwd, dirname3(join8(cwd, seamRel)));
4352
- const rulesDst = join8(cwd, rulesRel(seamRel));
4720
+ ensureProjectDirectorySync(cwd, dirname4(join9(cwd, seamRel)));
4721
+ const rulesDst = join9(cwd, rulesRel(seamRel));
4353
4722
  const changed = [];
4354
4723
  if (opts.demo || !existsSync6(rulesDst)) {
4355
- copyProjectFileSync(cwd, join8(templates, opts.demo ? "demo-rules.json" : "rules.json"), rulesDst);
4724
+ copyProjectFileSync(cwd, join9(templates, opts.demo ? "demo-rules.json" : "rules.json"), rulesDst);
4356
4725
  changed.push(rulesRel(seamRel));
4357
4726
  }
4358
- const current = existing ? read(join8(cwd, existing)) : "";
4727
+ const current = existing ? read(join9(cwd, existing)) : "";
4359
4728
  if (existing && current.includes(spec.marker)) {
4360
4729
  log(`${existing} already has the Patchstack guard \u2014 left as-is`);
4361
4730
  return { ok: true, changed };
@@ -4364,17 +4733,17 @@ function wireSeam(cwd, opts, spec) {
4364
4733
  log(`existing ${existing} left untouched \u2014 scaffolded ${rulesRel(seamRel)}; ${spec.planHint}`);
4365
4734
  return { ok: true, changed };
4366
4735
  }
4367
- copyProjectFileSync(cwd, join8(templates, spec.templateName), join8(cwd, seamRel));
4736
+ copyProjectFileSync(cwd, join9(templates, spec.templateName), join9(cwd, seamRel));
4368
4737
  if (!opts.demo) bakeSiteUuid(cwd, seamRel);
4369
4738
  changed.push(seamRel);
4370
4739
  log(`scaffolded ${seamRel}`);
4371
4740
  return { ok: true, changed: [...new Set(changed)] };
4372
4741
  }
4373
4742
  function verifySeam(cwd, spec) {
4374
- const existing = spec.candidates.find((c) => existsSync6(join8(cwd, c)));
4743
+ const existing = spec.candidates.find((c) => existsSync6(join9(cwd, c)));
4375
4744
  const seamRel = existing ?? spec.target;
4376
- const present2 = existing ? read(join8(cwd, existing)).includes(spec.marker) : false;
4377
- const rulesPresent = existsSync6(join8(cwd, rulesRel(seamRel)));
4745
+ const present2 = existing ? read(join9(cwd, existing)).includes(spec.marker) : false;
4746
+ const rulesPresent = existsSync6(join9(cwd, rulesRel(seamRel)));
4378
4747
  return {
4379
4748
  wired: present2 && rulesPresent,
4380
4749
  checks: [
@@ -4393,7 +4762,7 @@ var SPEC = {
4393
4762
  planHint: 'add the guard to your `handle` (compose with `sequence()` from "@sveltejs/kit/hooks"), then: npx patchstack-connect protect --check',
4394
4763
  seamLabel: "SvelteKit server hook"
4395
4764
  };
4396
- function detect3(cwd) {
4765
+ function detect2(cwd) {
4397
4766
  return hasDependency(cwd, "@sveltejs/kit");
4398
4767
  }
4399
4768
  function wire3(cwd, opts) {
@@ -4405,7 +4774,7 @@ function verify3(cwd) {
4405
4774
  var sveltekitAdapter = {
4406
4775
  name: "sveltekit",
4407
4776
  label: "SvelteKit",
4408
- detect: detect3,
4777
+ detect: detect2,
4409
4778
  wire: wire3,
4410
4779
  verify: verify3
4411
4780
  };
@@ -4419,7 +4788,7 @@ var SPEC2 = {
4419
4788
  planHint: 'add the guard to your `onRequest` (compose with `sequence()` from "astro:middleware"), then: npx patchstack-connect protect --check',
4420
4789
  seamLabel: "Astro middleware"
4421
4790
  };
4422
- function detect4(cwd) {
4791
+ function detect3(cwd) {
4423
4792
  return hasDependency(cwd, "astro");
4424
4793
  }
4425
4794
  function wire4(cwd, opts) {
@@ -4431,7 +4800,7 @@ function verify4(cwd) {
4431
4800
  var astroAdapter = {
4432
4801
  name: "astro",
4433
4802
  label: "Astro",
4434
- detect: detect4,
4803
+ detect: detect3,
4435
4804
  wire: wire4,
4436
4805
  verify: verify4
4437
4806
  };
@@ -4445,7 +4814,7 @@ var SPEC3 = {
4445
4814
  planHint: "add a `server/middleware/` handler that runs the guard, then: npx patchstack-connect protect --check",
4446
4815
  seamLabel: "Nuxt server middleware"
4447
4816
  };
4448
- function detect5(cwd) {
4817
+ function detect4(cwd) {
4449
4818
  return hasDependency(cwd, "nuxt");
4450
4819
  }
4451
4820
  function wire5(cwd, opts) {
@@ -4457,14 +4826,14 @@ function verify5(cwd) {
4457
4826
  var nuxtAdapter = {
4458
4827
  name: "nuxt",
4459
4828
  label: "Nuxt",
4460
- detect: detect5,
4829
+ detect: detect4,
4461
4830
  wire: wire5,
4462
4831
  verify: verify5
4463
4832
  };
4464
4833
 
4465
4834
  // src/protect/install/find-app.ts
4466
- import { readFileSync as readFileSync8, readdirSync as readdirSync3, lstatSync as lstatSync2 } from "fs";
4467
- import { join as join9, relative as relative3, dirname as dirname4 } from "path";
4835
+ import { readFileSync as readFileSync8, readdirSync as readdirSync4, lstatSync as lstatSync3 } from "fs";
4836
+ import { join as join10, relative as relative4, dirname as dirname5 } from "path";
4468
4837
  var SKIP_DIRS2 = /* @__PURE__ */ new Set([
4469
4838
  "node_modules",
4470
4839
  "patchstack",
@@ -4490,16 +4859,16 @@ function findAppInstance(cwd, re) {
4490
4859
  if (depth > MAX_DEPTH) return;
4491
4860
  let entries;
4492
4861
  try {
4493
- entries = readdirSync3(dir).sort();
4862
+ entries = readdirSync4(dir).sort();
4494
4863
  } catch {
4495
4864
  return;
4496
4865
  }
4497
4866
  for (const name of entries) {
4498
4867
  if (SKIP_DIRS2.has(name) || name.startsWith(".")) continue;
4499
- const p = join9(dir, name);
4868
+ const p = join10(dir, name);
4500
4869
  let st;
4501
4870
  try {
4502
- st = lstatSync2(p);
4871
+ st = lstatSync3(p);
4503
4872
  } catch {
4504
4873
  continue;
4505
4874
  }
@@ -4516,7 +4885,7 @@ function findAppInstance(cwd, re) {
4516
4885
  if (!m) continue;
4517
4886
  const appVar = m[1];
4518
4887
  found.push({
4519
- relPath: relative3(cwd, p).replace(/\\/g, "/"),
4888
+ relPath: relative4(cwd, p).replace(/\\/g, "/"),
4520
4889
  appVar,
4521
4890
  listens: listensOn(src, appVar)
4522
4891
  });
@@ -4552,17 +4921,17 @@ function entryRank(relPath) {
4552
4921
  return index === -1 ? ENTRY_NAMES.length : index;
4553
4922
  }
4554
4923
  function declaredEntries(cwd) {
4555
- const paths = /* @__PURE__ */ new Set();
4924
+ const paths2 = /* @__PURE__ */ new Set();
4556
4925
  let pkg;
4557
4926
  try {
4558
- pkg = JSON.parse(readFileSync8(join9(cwd, "package.json"), "utf8"));
4927
+ pkg = JSON.parse(readFileSync8(join10(cwd, "package.json"), "utf8"));
4559
4928
  } catch {
4560
- return paths;
4929
+ return paths2;
4561
4930
  }
4562
4931
  const add = (value) => {
4563
4932
  if (typeof value !== "string") return;
4564
4933
  for (const match of value.matchAll(/[\w./@-]+\.(?:ts|js|mjs|cjs)/g)) {
4565
- paths.add(match[0].replace(/^\.\//, ""));
4934
+ paths2.add(match[0].replace(/^\.\//, ""));
4566
4935
  }
4567
4936
  };
4568
4937
  add(pkg.main);
@@ -4571,10 +4940,10 @@ function declaredEntries(cwd) {
4571
4940
  if (typeof scripts === "object" && scripts !== null) {
4572
4941
  for (const name of ["start", "serve", "dev"]) add(scripts[name]);
4573
4942
  }
4574
- return paths;
4943
+ return paths2;
4575
4944
  }
4576
4945
  function importSpecifier(fromRel, toRel, preserveExtension = false) {
4577
- let spec = relative3(dirname4(fromRel), toRel).replace(/\\/g, "/");
4946
+ let spec = relative4(dirname5(fromRel), toRel).replace(/\\/g, "/");
4578
4947
  if (!preserveExtension) spec = spec.replace(/\.(?:ts|js)$/, "");
4579
4948
  if (!spec.startsWith(".")) spec = `./${spec}`;
4580
4949
  return spec;
@@ -4582,16 +4951,16 @@ function importSpecifier(fromRel, toRel, preserveExtension = false) {
4582
4951
 
4583
4952
  // src/protect/install/register.ts
4584
4953
  import { existsSync as existsSync9 } from "fs";
4585
- import { join as join12, resolve as resolve3 } from "path";
4954
+ import { join as join13, resolve as resolve3 } from "path";
4586
4955
 
4587
4956
  // src/protect/install/generic.ts
4588
- import { readFileSync as readFileSync9, existsSync as existsSync8, readdirSync as readdirSync4, lstatSync as lstatSync3 } from "fs";
4589
- import { join as join11, dirname as dirname6 } from "path";
4957
+ import { readFileSync as readFileSync9, existsSync as existsSync8, readdirSync as readdirSync5, lstatSync as lstatSync4 } from "fs";
4958
+ import { join as join12, dirname as dirname7 } from "path";
4590
4959
 
4591
4960
  // src/protect/install/source-scope.ts
4592
4961
  import { execFileSync } from "child_process";
4593
4962
  import { existsSync as existsSync7 } from "fs";
4594
- import { dirname as dirname5, join as join10, resolve as resolve2 } from "path";
4963
+ import { dirname as dirname6, join as join11, resolve as resolve2 } from "path";
4595
4964
 
4596
4965
  // src/protect/install/node-flags.ts
4597
4966
  var flagName = (token) => token.split("=")[0];
@@ -4880,9 +5249,9 @@ function moduleKindOf(filePath, packageIsModule) {
4880
5249
  return packageIsModule ? "esm" : "cjs";
4881
5250
  }
4882
5251
  function resolvesToGuardModule(specifier, query) {
4883
- const resolved = resolve2(dirname5(query.fromFile), specifier);
4884
- if (withoutModuleExtension(resolved) !== join10(query.guardDir, "guard")) return false;
4885
- const existing = GUARD_FILENAMES.filter((name) => existsSync7(join10(query.guardDir, name)));
5252
+ const resolved = resolve2(dirname6(query.fromFile), specifier);
5253
+ if (withoutModuleExtension(resolved) !== join11(query.guardDir, "guard")) return false;
5254
+ const existing = GUARD_FILENAMES.filter((name) => existsSync7(join11(query.guardDir, name)));
4886
5255
  if (existing.length === 0) return false;
4887
5256
  const extension = /(\.[A-Za-z0-9]+)$/.exec(specifier)?.[1] ?? "";
4888
5257
  if (!query.strictExtensions) return true;
@@ -4901,16 +5270,16 @@ function withoutModuleExtension(filePath) {
4901
5270
  // src/protect/install/generic.ts
4902
5271
  function packageIsEsm(cwd) {
4903
5272
  try {
4904
- return JSON.parse(read(join11(cwd, "package.json"))).type === "module";
5273
+ return JSON.parse(read(join12(cwd, "package.json"))).type === "module";
4905
5274
  } catch {
4906
5275
  return false;
4907
5276
  }
4908
5277
  }
4909
5278
  function genericDir(cwd) {
4910
- return existsSync8(join11(cwd, "src")) ? "src/patchstack" : "patchstack";
5279
+ return existsSync8(join12(cwd, "src")) ? "src/patchstack" : "patchstack";
4911
5280
  }
4912
5281
  function hasTypeScript(cwd) {
4913
- return existsSync8(join11(cwd, "tsconfig.json")) || candidateEntries(cwd).some((entry) => /\.tsx?$/.test(entry));
5282
+ return existsSync8(join12(cwd, "tsconfig.json")) || candidateEntries(cwd).some((entry) => /\.tsx?$/.test(entry));
4914
5283
  }
4915
5284
  function genericGuardTarget(cwd) {
4916
5285
  if (hasTypeScript(cwd)) {
@@ -4924,7 +5293,7 @@ function genericGuardTarget(cwd) {
4924
5293
  function genericScaffoldFiles(cwd) {
4925
5294
  const dir = genericDir(cwd);
4926
5295
  const candidates = ["guard.ts", "guard.js", "guard.cjs", "rules.json"];
4927
- return candidates.map((file) => `${dir}/${file}`).filter((relative8) => existsSync8(join11(cwd, relative8)));
5296
+ return candidates.map((file) => `${dir}/${file}`).filter((relative9) => existsSync8(join12(cwd, relative9)));
4928
5297
  }
4929
5298
  function scaffoldGeneric(cwd, opts, guardTemplate, guardFile) {
4930
5299
  const target = genericGuardTarget(cwd);
@@ -4932,15 +5301,15 @@ function scaffoldGeneric(cwd, opts, guardTemplate, guardFile) {
4932
5301
  guardFile ??= target.file;
4933
5302
  const templates = templatesDir();
4934
5303
  const dir = genericDir(cwd);
4935
- const dst = join11(cwd, dir);
5304
+ const dst = join12(cwd, dir);
4936
5305
  ensureProjectDirectorySync(cwd, dst);
4937
- copyProjectFileSync(cwd, join11(templates, guardTemplate), join11(dst, guardFile));
5306
+ copyProjectFileSync(cwd, join12(templates, guardTemplate), join12(dst, guardFile));
4938
5307
  const guardRel = `${dir}/${guardFile}`;
4939
5308
  const changed = [guardRel];
4940
5309
  if (!opts.demo) bakeSiteUuid(cwd, guardRel);
4941
- const rulesDst = join11(dst, "rules.json");
5310
+ const rulesDst = join12(dst, "rules.json");
4942
5311
  if (opts.demo || !existsSync8(rulesDst)) {
4943
- copyProjectFileSync(cwd, join11(templates, opts.demo ? "demo-rules.json" : "rules.json"), rulesDst);
5312
+ copyProjectFileSync(cwd, join12(templates, opts.demo ? "demo-rules.json" : "rules.json"), rulesDst);
4944
5313
  changed.push(`${dir}/rules.json`);
4945
5314
  }
4946
5315
  return { changed, dir };
@@ -4961,10 +5330,10 @@ function candidateEntries(cwd) {
4961
5330
  "app.ts",
4962
5331
  "app.js"
4963
5332
  ];
4964
- const hits = names.filter((n) => existsSync8(join11(cwd, n)));
5333
+ const hits = names.filter((n) => existsSync8(join12(cwd, n)));
4965
5334
  try {
4966
- const pkg = JSON.parse(read(join11(cwd, "package.json")));
4967
- if (typeof pkg.main === "string" && existsSync8(join11(cwd, pkg.main))) hits.push(pkg.main);
5335
+ const pkg = JSON.parse(read(join12(cwd, "package.json")));
5336
+ if (typeof pkg.main === "string" && existsSync8(join12(cwd, pkg.main))) hits.push(pkg.main);
4968
5337
  } catch {
4969
5338
  }
4970
5339
  return [...new Set(hits)];
@@ -5038,8 +5407,8 @@ function boundNames(declaration) {
5038
5407
  const braced = /\{([^}]*)\}/.exec(clause)?.[1];
5039
5408
  if (braced !== void 0) {
5040
5409
  for (const part of braced.split(",")) {
5041
- const [exported, local] = splitBinding(part);
5042
- if (!isGuardExport(exported)) continue;
5410
+ const [exported2, local] = splitBinding(part);
5411
+ if (!isGuardExport(exported2)) continue;
5043
5412
  if (/^[A-Za-z_$][\w$]*$/.test(local)) direct.push(local);
5044
5413
  }
5045
5414
  }
@@ -5055,8 +5424,8 @@ function splitBinding(part) {
5055
5424
  const name = part.trim();
5056
5425
  return [name, name];
5057
5426
  }
5058
- const [exported, ...rest] = part.split(separator);
5059
- return [(exported ?? "").trim(), (rest.join(separator) ?? "").trim()];
5427
+ const [exported2, ...rest] = part.split(separator);
5428
+ return [(exported2 ?? "").trim(), (rest.join(separator) ?? "").trim()];
5060
5429
  }
5061
5430
  function isGuardExport(name) {
5062
5431
  return GUARD_EXPORTS.includes(name);
@@ -5067,9 +5436,9 @@ function escapeForRegExp(value) {
5067
5436
  function genericVerify(cwd) {
5068
5437
  const dir = genericDir(cwd);
5069
5438
  const target = genericGuardTarget(cwd);
5070
- const present2 = GUARD_FILENAMES.find((name) => existsSync8(join11(cwd, dir, name)));
5439
+ const present2 = GUARD_FILENAMES.find((name) => existsSync8(join12(cwd, dir, name)));
5071
5440
  const scaffolded = present2 !== void 0;
5072
- const imported = scaffolded && guardIsImported(cwd, join11(cwd, dir, present2));
5441
+ const imported = scaffolded && guardIsImported(cwd, join12(cwd, dir, present2));
5073
5442
  return {
5074
5443
  wired: scaffolded && imported,
5075
5444
  checks: [
@@ -5103,25 +5472,25 @@ var NON_RUNTIME_DIRS = /* @__PURE__ */ new Set([
5103
5472
  "__mocks__"
5104
5473
  ]);
5105
5474
  function guardIsImported(cwd, guardPath) {
5106
- const guardDir = dirname6(guardPath);
5475
+ const guardDir = dirname7(guardPath);
5107
5476
  const packageIsModule = packageIsEsm(cwd);
5108
- const root = existsSync8(join11(cwd, "src")) ? join11(cwd, "src") : cwd;
5477
+ const root = existsSync8(join12(cwd, "src")) ? join12(cwd, "src") : cwd;
5109
5478
  let found = false;
5110
5479
  const walk2 = (d, depth) => {
5111
5480
  if (found || depth > 8) return;
5112
5481
  let entries;
5113
5482
  try {
5114
- entries = readdirSync4(d);
5483
+ entries = readdirSync5(d);
5115
5484
  } catch {
5116
5485
  return;
5117
5486
  }
5118
5487
  for (const name of entries) {
5119
5488
  if (found) return;
5120
5489
  if (NON_RUNTIME_DIRS.has(name) || name.startsWith(".")) continue;
5121
- const p = join11(d, name);
5490
+ const p = join12(d, name);
5122
5491
  let st;
5123
5492
  try {
5124
- st = lstatSync3(p);
5493
+ st = lstatSync4(p);
5125
5494
  } catch {
5126
5495
  continue;
5127
5496
  }
@@ -5177,7 +5546,7 @@ function guardTarget(cwd, entryRel, spec) {
5177
5546
  }
5178
5547
  function packageType(cwd) {
5179
5548
  try {
5180
- return JSON.parse(read(join12(cwd, "package.json"))).type;
5549
+ return JSON.parse(read(join13(cwd, "package.json"))).type;
5181
5550
  } catch {
5182
5551
  return void 0;
5183
5552
  }
@@ -5213,8 +5582,8 @@ function bindsGuard(line, maskedLine, importName, call, fileRel, guard) {
5213
5582
  }
5214
5583
  function namesGuardModule(specifier, fileRel, guard) {
5215
5584
  return resolvesToGuardModule(specifier, {
5216
- fromFile: join12(guard.cwd, fileRel),
5217
- guardDir: resolve3(join12(guard.cwd, guard.guardDir)),
5585
+ fromFile: join13(guard.cwd, fileRel),
5586
+ guardDir: resolve3(join13(guard.cwd, guard.guardDir)),
5218
5587
  kind: moduleKindOf(fileRel, packageType(guard.cwd) === "module"),
5219
5588
  strictExtensions: true
5220
5589
  });
@@ -5233,7 +5602,7 @@ function wireRegister(cwd, opts, spec) {
5233
5602
  }
5234
5603
  const target = guardTarget(cwd, entry.relPath, spec);
5235
5604
  const { changed, dir } = scaffoldGeneric(cwd, opts, target.template, target.file);
5236
- const p = join12(cwd, entry.relPath);
5605
+ const p = join13(cwd, entry.relPath);
5237
5606
  const s = read(p);
5238
5607
  const state = wiringState(s, spec, entry.appVar, entry.relPath, { cwd, guardDir: dir });
5239
5608
  if (state.importAtTopLevel && state.callInAppScope) {
@@ -5303,17 +5672,17 @@ function firstStatementLine(lines) {
5303
5672
  return i;
5304
5673
  }
5305
5674
  function serverIsGuarded(cwd, spec, server, guardDir) {
5306
- const source = read(join12(cwd, server.relPath));
5675
+ const source = read(join13(cwd, server.relPath));
5307
5676
  const state = wiringState(source, spec, server.appVar, server.relPath, { cwd, guardDir });
5308
5677
  if (!state.importAtTopLevel || !state.callInAppScope || !state.ordered) return false;
5309
5678
  return !spec.callAfter || routesBefore(source, server.appVar, state.callIndex).length === 0;
5310
5679
  }
5311
5680
  function verifyRegister(cwd, spec) {
5312
- const dir = existsSync9(join12(cwd, "src")) ? "src/patchstack" : "patchstack";
5681
+ const dir = existsSync9(join13(cwd, "src")) ? "src/patchstack" : "patchstack";
5313
5682
  const entry = findAppInstance(cwd, spec.appRe);
5314
5683
  const target = entry ? guardTarget(cwd, entry.relPath, spec) : null;
5315
- const scaffolded = target ? existsSync9(join12(cwd, dir, target.file)) : false;
5316
- const entrySource = entry ? read(join12(cwd, entry.relPath)) : "";
5684
+ const scaffolded = target ? existsSync9(join13(cwd, dir, target.file)) : false;
5685
+ const entrySource = entry ? read(join13(cwd, entry.relPath)) : "";
5317
5686
  const state = entry ? wiringState(entrySource, spec, entry.appVar, entry.relPath, { cwd, guardDir: dir }) : { importAtTopLevel: false, callInAppScope: false, ordered: false, callIndex: -1, appIndex: -1 };
5318
5687
  const wired = state.importAtTopLevel && state.callInAppScope && state.ordered;
5319
5688
  const early = spec.callAfter && entry ? routesBefore(entrySource, entry.appVar, state.callIndex) : [];
@@ -5404,7 +5773,7 @@ var expressAdapter = {
5404
5773
 
5405
5774
  // src/protect/install/reporting.ts
5406
5775
  import { existsSync as existsSync10 } from "fs";
5407
- import { join as join13 } from "path";
5776
+ import { join as join14 } from "path";
5408
5777
 
5409
5778
  // src/protect/reporting-state.js
5410
5779
  var REPORTING_STATES = Object.freeze([
@@ -5462,7 +5831,7 @@ function explainReportingState(state) {
5462
5831
 
5463
5832
  // src/protect/install/reporting.ts
5464
5833
  function siteIdentity(cwd, env) {
5465
- const rc = join13(cwd, ".patchstackrc.json");
5834
+ const rc = join14(cwd, ".patchstackrc.json");
5466
5835
  let recorded;
5467
5836
  if (existsSync10(rc)) {
5468
5837
  try {
@@ -5559,7 +5928,7 @@ function runProtect(cwd, opts = {}) {
5559
5928
  return { status: "scaffolded", adapter: "generic", changed: [], plan: "" };
5560
5929
  }
5561
5930
  }
5562
- var RUNTIMES_WITHOUT_CONFIG_FILE = /* @__PURE__ */ new Set(["next", "sveltekit", "astro", "nuxt", "generic"]);
5931
+ var RUNTIMES_WITHOUT_CONFIG_FILE = /* @__PURE__ */ new Set(["nextjs", "sveltekit", "astro", "nuxt", "generic"]);
5563
5932
  function credentialNote(cwd, adapterName) {
5564
5933
  if (!RUNTIMES_WITHOUT_CONFIG_FILE.has(adapterName)) return [];
5565
5934
  const localHint = hasResolvableCredential(cwd) ? "a credential is configured here; set the same one in your deployment" : "no credential found here either \u2014 run `npx @patchstack/connect scan` to provision one";
@@ -5929,7 +6298,7 @@ function findWidgetMarker(cwd, siteUuid) {
5929
6298
  }
5930
6299
  let entries;
5931
6300
  try {
5932
- entries = readdirSync5(dir, { withFileTypes: true });
6301
+ entries = readdirSync6(dir, { withFileTypes: true });
5933
6302
  } catch {
5934
6303
  return;
5935
6304
  }
@@ -5997,7 +6366,7 @@ function findAstroDocumentLayout(cwd) {
5997
6366
  const dir = path12.join("src", "layouts");
5998
6367
  let names;
5999
6368
  try {
6000
- names = readdirSync5(path12.join(cwd, dir)).filter((name) => name.endsWith(".astro")).sort();
6369
+ names = readdirSync6(path12.join(cwd, dir)).filter((name) => name.endsWith(".astro")).sort();
6001
6370
  } catch {
6002
6371
  return null;
6003
6372
  }
@@ -6543,11 +6912,11 @@ async function claim2(config, onPrompt, deps = {}) {
6543
6912
  }
6544
6913
 
6545
6914
  // src/protect/install/runtime/check.ts
6546
- import { relative as relative4 } from "path";
6915
+ import { relative as relative5 } from "path";
6547
6916
 
6548
6917
  // src/protect/install/runtime/entry.ts
6549
6918
  import { existsSync as existsSync13, readFileSync as readFileSync13, realpathSync as realpathSync4, statSync as statSync6 } from "fs";
6550
- import { join as join14, resolve as resolve4, sep as sep2 } from "path";
6919
+ import { join as join15, resolve as resolve4, sep as sep2 } from "path";
6551
6920
  var CONVENTIONAL = [
6552
6921
  "server.js",
6553
6922
  "server.mjs",
@@ -6573,7 +6942,7 @@ var CONVENTIONAL = [
6573
6942
  var LOADABLE = /\.(?:js|mjs|cjs)$/;
6574
6943
  function readPackage2(cwd) {
6575
6944
  try {
6576
- const parsed = JSON.parse(readFileSync13(join14(cwd, "package.json"), "utf8"));
6945
+ const parsed = JSON.parse(readFileSync13(join15(cwd, "package.json"), "utf8"));
6577
6946
  return parsed !== null && typeof parsed === "object" ? parsed : null;
6578
6947
  } catch {
6579
6948
  return null;
@@ -6643,7 +7012,7 @@ function resolveEntry(cwd) {
6643
7012
  }
6644
7013
  return {
6645
7014
  kind: "unavailable",
6646
- reason: existsSync13(join14(cwd, "package.json")) ? 'no directly loadable entry was found \u2014 declare one as a "start" script of the form `node <file>`, or run the check against a built output' : "there is no package.json here"
7015
+ reason: existsSync13(join15(cwd, "package.json")) ? 'no directly loadable entry was found \u2014 declare one as a "start" script of the form `node <file>`, or run the check against a built output' : "there is no package.json here"
6647
7016
  };
6648
7017
  }
6649
7018
 
@@ -6994,7 +7363,7 @@ async function runRuntimeCheck(cwd, options = {}) {
6994
7363
  settleMs: options.settleMs,
6995
7364
  platform: options.platform
6996
7365
  });
6997
- return { ...result, entry: { file: relative4(cwd, entry.file).replace(/\\/g, "/"), from: entry.from } };
7366
+ return { ...result, entry: { file: relative5(cwd, entry.file).replace(/\\/g, "/"), from: entry.from } };
6998
7367
  }
6999
7368
  function runtimeExitCode(report) {
7000
7369
  if (report.outcome === "proven") return 0;
@@ -7028,12 +7397,12 @@ function formatRuntimeCheck(report) {
7028
7397
  import path14 from "path";
7029
7398
 
7030
7399
  // src/map/ts-loader.ts
7031
- import { createRequire } from "module";
7400
+ import { createRequire as createRequire2 } from "module";
7032
7401
  import { pathToFileURL } from "url";
7033
- import { join as join15 } from "path";
7402
+ import { join as join16 } from "path";
7034
7403
  async function loadTypeScript(cwd) {
7035
7404
  try {
7036
- const req = createRequire(pathToFileURL(join15(cwd, "package.json")));
7405
+ const req = createRequire2(pathToFileURL(join16(cwd, "package.json")));
7037
7406
  const resolved = req.resolve("typescript");
7038
7407
  const mod = await import(pathToFileURL(resolved).href);
7039
7408
  return mod.default ?? mod;
@@ -7050,7 +7419,7 @@ async function loadTypeScript(cwd) {
7050
7419
  // src/map/extract.ts
7051
7420
  import { readFileSync as readFileSync16, realpathSync as realpathSync6 } from "fs";
7052
7421
  import { createHash as createHash5 } from "crypto";
7053
- import { relative as relative6 } from "path";
7422
+ import { relative as relative7 } from "path";
7054
7423
 
7055
7424
  // src/map/bindings.ts
7056
7425
  import { builtinModules } from "module";
@@ -7407,14 +7776,14 @@ function directSinks(node, ts, bindings, ctx) {
7407
7776
  const root = base ? rootIdentifier(base, ts) : void 0;
7408
7777
  if (!root) return {};
7409
7778
  const spec = bindings.resolve(root);
7410
- const relative8 = spec !== void 0 && (spec.startsWith(".") || spec.startsWith("/"));
7779
+ const relative9 = spec !== void 0 && (spec.startsWith(".") || spec.startsWith("/"));
7411
7780
  const pkg = npmPackageOf(spec);
7412
7781
  if (pkg) return { pkg, root, spec };
7413
- if (relative8 && ctx && spec) {
7782
+ if (relative9 && ctx && spec) {
7414
7783
  const viaModule = ctx.graph.importedBinding(ctx.file, spec, bindings.exportNameOf(root) ?? root);
7415
7784
  if (viaModule) return { pkg: viaModule.package, root, spec };
7416
7785
  }
7417
- return { local: bindings.locals.has(root), root, spec, relative: relative8 };
7786
+ return { local: bindings.locals.has(root), root, spec, relative: relative9 };
7418
7787
  };
7419
7788
  const attributionOf = (b, pkg) => b.pkg ? "import" : pkg ? "inferred" : void 0;
7420
7789
  const dbApi = (pkg, attribution) => {
@@ -8704,7 +9073,7 @@ function withNote(doc) {
8704
9073
 
8705
9074
  // src/map/module-graph.ts
8706
9075
  import { readFileSync as readFileSync14, realpathSync as realpathSync5, statSync as statSync7 } from "fs";
8707
- import { dirname as dirname8, join as join16, relative as relative5, resolve as resolvePath } from "path";
9076
+ import { dirname as dirname9, join as join17, relative as relative6, resolve as resolvePath } from "path";
8708
9077
  var RESOLVE_EXTS = [".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs"];
8709
9078
  function createModuleGraph(ts, opts) {
8710
9079
  const cache = /* @__PURE__ */ new Map();
@@ -8746,7 +9115,7 @@ function createModuleGraph(ts, opts) {
8746
9115
  for (const callee of mod.calleesOf.get(exportName) ?? []) {
8747
9116
  for (const s of mod.fnSinks.get(callee) ?? []) collected.push(s);
8748
9117
  }
8749
- const rel = relative5(opts.cwd, target);
9118
+ const rel = relative6(opts.cwd, target);
8750
9119
  return collected.map((s) => ({ ...s, file: rel }));
8751
9120
  },
8752
9121
  // A different question about the same module: not "what sinks are in there" but "what does this
@@ -8772,7 +9141,7 @@ function createModuleGraph(ts, opts) {
8772
9141
  }
8773
9142
  function resolveRelativeModule(fromFile, spec) {
8774
9143
  if (!spec.startsWith(".")) return void 0;
8775
- const dir = dirname8(fromFile);
9144
+ const dir = dirname9(fromFile);
8776
9145
  const base = resolvePath(dir, spec);
8777
9146
  const candidates = [];
8778
9147
  const jsLike = /\.(js|jsx|mjs|cjs)$/.exec(base);
@@ -8782,7 +9151,7 @@ function resolveRelativeModule(fromFile, spec) {
8782
9151
  }
8783
9152
  candidates.push(base);
8784
9153
  for (const e of RESOLVE_EXTS) candidates.push(base + e);
8785
- for (const e of RESOLVE_EXTS) candidates.push(join16(base, "index" + e));
9154
+ for (const e of RESOLVE_EXTS) candidates.push(join17(base, "index" + e));
8786
9155
  for (const c of candidates) {
8787
9156
  try {
8788
9157
  if (statSync7(c).isFile()) return c;
@@ -9072,7 +9441,7 @@ function handlerEntry(name, kindLabel, params, body, ts, localSinks, bindings, c
9072
9441
 
9073
9442
  // src/map/imports.ts
9074
9443
  import { readFileSync as readFileSync15 } from "fs";
9075
- import { join as join17 } from "path";
9444
+ import { join as join18 } from "path";
9076
9445
  var MAX_SITES2 = 5;
9077
9446
  var NPM_NAME = /^(?:@[^/@\s~][^/@\s]*\/)?[^/@\s.~][^/@\s]*$/;
9078
9447
  function isNpmPackageName(pkg) {
@@ -9081,15 +9450,15 @@ function isNpmPackageName(pkg) {
9081
9450
  function readPathAliases(cwd) {
9082
9451
  const aliases = [];
9083
9452
  for (const name of ["tsconfig.json", "jsconfig.json"]) {
9084
- let paths;
9453
+ let paths2;
9085
9454
  try {
9086
- const raw = readFileSync15(join17(cwd, name), "utf8");
9455
+ const raw = readFileSync15(join18(cwd, name), "utf8");
9087
9456
  const parsed = JSON.parse(stripJsonComments(raw));
9088
- paths = parsed.compilerOptions?.paths;
9457
+ paths2 = parsed.compilerOptions?.paths;
9089
9458
  } catch {
9090
9459
  continue;
9091
9460
  }
9092
- for (const key of Object.keys(paths ?? {})) {
9461
+ for (const key of Object.keys(paths2 ?? {})) {
9093
9462
  if (key.startsWith(".")) continue;
9094
9463
  if (key.endsWith("*")) aliases.push({ prefix: key.slice(0, -1), wildcard: true });
9095
9464
  else aliases.push({ prefix: key, wildcard: false });
@@ -9355,7 +9724,7 @@ async function extractInputMap(cwd, ts, options = {}) {
9355
9724
  for (const file of files) {
9356
9725
  try {
9357
9726
  const text = readFileSync16(file, "utf8");
9358
- const relFile = relative6(cwd, file);
9727
+ const relFile = relative7(cwd, file);
9359
9728
  sourceBytes += text.length;
9360
9729
  if (isComponentFile(file)) {
9361
9730
  componentFiles++;
@@ -9424,7 +9793,7 @@ async function extractInputMap(cwd, ts, options = {}) {
9424
9793
  }
9425
9794
  } catch (e) {
9426
9795
  if (typeof process !== "undefined" && process.env?.PS_MAP_DEBUG) console.error("[patchstack] map error", file, e);
9427
- failed.push(relative6(cwd, file));
9796
+ failed.push(relative7(cwd, file));
9428
9797
  }
9429
9798
  }
9430
9799
  let hopParsed = 0;
@@ -9435,7 +9804,7 @@ async function extractInputMap(cwd, ts, options = {}) {
9435
9804
  const text = readFileSync16(target, "utf8");
9436
9805
  const sf = ts.createSourceFile(target, text, ts.ScriptTarget.Latest, true, guessScriptKind(ts, target));
9437
9806
  const bindings = buildModuleBindings(sf, ts);
9438
- const called = collectInvocations(sf, ts, bindings, { file: target, owner: relative6(cwd, target), graph });
9807
+ const called = collectInvocations(sf, ts, bindings, { file: target, owner: relative7(cwd, target), graph });
9439
9808
  invocations.add(called.invocations);
9440
9809
  calls.total += called.counts.total;
9441
9810
  calls.dependency += called.counts.dependency;
@@ -9481,7 +9850,7 @@ async function extractInputMap(cwd, ts, options = {}) {
9481
9850
  if (endpoints.length === 0) notes.push("No recognized server-side entry points found under the analyzed roots.");
9482
9851
  const importList = imports.list();
9483
9852
  const unmodelled = importList.filter((d) => d.recognizedSinkKinds.length === 0).length;
9484
- const skippedDirsWithSource = stats.skippedWithSource.map((d) => relative6(cwd, d));
9853
+ const skippedDirsWithSource = stats.skippedWithSource.map((d) => relative7(cwd, d));
9485
9854
  const importCoverageGaps = {
9486
9855
  unreadableFiles: failed.length,
9487
9856
  unscannableFiles: importScanFailures,
@@ -9595,8 +9964,8 @@ function getStringFlag(flags, name) {
9595
9964
  }
9596
9965
 
9597
9966
  // src/build-stamp.ts
9598
- import { lstatSync as lstatSync4, readFileSync as readFileSync17, readdirSync as readdirSync6, realpathSync as realpathSync7 } from "fs";
9599
- import { join as join18, relative as relative7, sep as sep3 } from "path";
9967
+ import { lstatSync as lstatSync5, readFileSync as readFileSync17, readdirSync as readdirSync7, realpathSync as realpathSync7 } from "fs";
9968
+ import { join as join19, relative as relative8, sep as sep3 } from "path";
9600
9969
  var RULES_FILE_NAMES = /* @__PURE__ */ new Set(["rules.json", "patchstack.rules.json"]);
9601
9970
  var SKIP_DIRECTORIES = /* @__PURE__ */ new Set(["node_modules", "dist", "build", "out", "coverage", "tmp", "vendor"]);
9602
9971
  var MAX_DEPTH2 = 6;
@@ -9608,15 +9977,15 @@ function guardImportsRulesFile(dir, rulesName) {
9608
9977
  const importsRules = new RegExp(`(?:\\bfrom\\s*|\\brequire\\s*\\(\\s*|\\bnew\\s+URL\\s*\\(\\s*)${quotedRules}`);
9609
9978
  let siblings;
9610
9979
  try {
9611
- siblings = readdirSync6(dir);
9980
+ siblings = readdirSync7(dir);
9612
9981
  } catch {
9613
9982
  return false;
9614
9983
  }
9615
9984
  for (const name of siblings) {
9616
9985
  if (!GUARD_SOURCE.test(name)) continue;
9617
- const path17 = join18(dir, name);
9986
+ const path17 = join19(dir, name);
9618
9987
  try {
9619
- const entry = lstatSync4(path17);
9988
+ const entry = lstatSync5(path17);
9620
9989
  if (!entry.isFile() || entry.isSymbolicLink() || entry.size > MAX_GUARD_SOURCE_BYTES) continue;
9621
9990
  const source = stripComments(readFileSync17(path17, "utf8"));
9622
9991
  if (source.includes("@patchstack/connect/protect") && importsRules.test(source)) return true;
@@ -9651,16 +10020,16 @@ function findRulesFile(cwd) {
9651
10020
  if (depth > MAX_DEPTH2 || found.length > 8) return;
9652
10021
  let entries;
9653
10022
  try {
9654
- entries = readdirSync6(dir);
10023
+ entries = readdirSync7(dir);
9655
10024
  } catch {
9656
10025
  return;
9657
10026
  }
9658
10027
  for (const name of entries) {
9659
10028
  if (name.startsWith(".")) continue;
9660
- const path17 = join18(dir, name);
10029
+ const path17 = join19(dir, name);
9661
10030
  let entry;
9662
10031
  try {
9663
- entry = lstatSync4(path17);
10032
+ entry = lstatSync5(path17);
9664
10033
  } catch {
9665
10034
  continue;
9666
10035
  }
@@ -9680,9 +10049,9 @@ function findRulesFile(cwd) {
9680
10049
  }
9681
10050
  };
9682
10051
  walk2(cwd, 0);
9683
- if (found.length > 1) return { kind: "ambiguous", paths: found.map((p) => relative7(cwd, p)) };
10052
+ if (found.length > 1) return { kind: "ambiguous", paths: found.map((p) => relative8(cwd, p)) };
9684
10053
  if (found.length === 1) return { kind: "one", path: found[0] };
9685
- if (unreadable.length > 0) return { kind: "unreadable", paths: unreadable.map((p) => relative7(cwd, p)) };
10054
+ if (unreadable.length > 0) return { kind: "unreadable", paths: unreadable.map((p) => relative8(cwd, p)) };
9686
10055
  return { kind: "none" };
9687
10056
  }
9688
10057
  function detectIndent(text) {
@@ -9703,7 +10072,7 @@ function applyBuildStamp(cwd, id) {
9703
10072
  reason: `more than one candidate guard rules file (${location.paths.join(", ")}) \u2014 none was stamped`
9704
10073
  };
9705
10074
  }
9706
- const file = relative7(cwd, location.path);
10075
+ const file = relative8(cwd, location.path);
9707
10076
  let text;
9708
10077
  try {
9709
10078
  text = readFileSync17(location.path, "utf8");
@@ -11142,7 +11511,7 @@ async function runMarkBuild(args) {
11142
11511
  }
11143
11512
  function packageVersion() {
11144
11513
  try {
11145
- const require2 = createRequire2(import.meta.url);
11514
+ const require2 = createRequire3(import.meta.url);
11146
11515
  const manifest = require2("../package.json");
11147
11516
  return typeof manifest.version === "string" && manifest.version.length > 0 ? manifest.version : "unknown";
11148
11517
  } catch {