@patchstack/connect 0.3.16 → 0.3.17

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
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/cli.ts
4
- import { readFileSync as readFileSync5, writeFileSync as writeFileSync4 } from "fs";
4
+ import { readFileSync as readFileSync7, writeFileSync as writeFileSync7 } from "fs";
5
5
 
6
6
  // src/parsers/index.ts
7
7
  import { access } from "fs/promises";
@@ -1661,16 +1661,65 @@ function renderGuideChecklist(state, useColor) {
1661
1661
  return lines.join("\n");
1662
1662
  }
1663
1663
 
1664
- // src/protect/install.ts
1665
- import { readFileSync as readFileSync3, writeFileSync as writeFileSync2, existsSync as existsSync4, mkdirSync, copyFileSync } from "fs";
1664
+ // src/protect/install/util.ts
1665
+ import { readFileSync as readFileSync3, existsSync as existsSync4, writeFileSync as writeFileSync2 } from "fs";
1666
1666
  import { join, dirname } from "path";
1667
1667
  import { fileURLToPath } from "url";
1668
- var HERE = dirname(fileURLToPath(import.meta.url));
1669
- var TEMPLATES = [join(HERE, "protect", "templates"), join(HERE, "templates")].find((p) => existsSync4(p)) ?? join(HERE, "protect", "templates");
1670
- var APP = process.cwd();
1671
- var PS_DIR = join(APP, "src/integrations/patchstack");
1672
1668
  var read = (p) => readFileSync3(p, "utf8");
1673
1669
  var log = (msg) => console.log(`patchstack protect: ${msg}`);
1670
+ function hasDependency(cwd, name) {
1671
+ try {
1672
+ const pkg = JSON.parse(read(join(cwd, "package.json")));
1673
+ return Boolean({ ...pkg.dependencies, ...pkg.devDependencies }[name]);
1674
+ } catch {
1675
+ return false;
1676
+ }
1677
+ }
1678
+ var SITE_UUID_PLACEHOLDER = "__PATCHSTACK_SITE_UUID__";
1679
+ var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
1680
+ function bakeSiteUuid(cwd, guardRelPath) {
1681
+ const rc = join(cwd, ".patchstackrc.json");
1682
+ if (!existsSync4(rc)) {
1683
+ log("no .patchstackrc.json \u2014 guard uses PATCHSTACK_SITE_UUID env or the bundled fallback");
1684
+ return false;
1685
+ }
1686
+ let uuid;
1687
+ try {
1688
+ uuid = JSON.parse(read(rc)).siteUuid;
1689
+ } catch {
1690
+ log(".patchstackrc.json unreadable \u2014 skipping site-UUID bake");
1691
+ return false;
1692
+ }
1693
+ if (typeof uuid !== "string" || !UUID_RE.test(uuid)) {
1694
+ log(".patchstackrc.json siteUuid missing or malformed \u2014 guard uses PATCHSTACK_SITE_UUID env or the bundled fallback");
1695
+ return false;
1696
+ }
1697
+ const guardPath = join(cwd, guardRelPath);
1698
+ if (!existsSync4(guardPath)) return false;
1699
+ const source = read(guardPath);
1700
+ if (!source.includes(SITE_UUID_PLACEHOLDER)) {
1701
+ log(`${guardRelPath} site UUID already baked`);
1702
+ return false;
1703
+ }
1704
+ writeFileSync2(guardPath, source.replace(SITE_UUID_PLACEHOLDER, uuid));
1705
+ log(`baked site UUID into ${guardRelPath} \u2014 live rules from the Patchstack API`);
1706
+ return true;
1707
+ }
1708
+ var HERE = dirname(fileURLToPath(import.meta.url));
1709
+ function templatesDir() {
1710
+ const builtLayout = join(HERE, "protect", "templates");
1711
+ const candidates = [
1712
+ builtLayout,
1713
+ join(HERE, "..", "templates"),
1714
+ // source: src/protect/install/ → src/protect/templates
1715
+ join(HERE, "templates")
1716
+ ];
1717
+ return candidates.find((p) => existsSync4(p)) ?? builtLayout;
1718
+ }
1719
+
1720
+ // src/protect/install/adapters/tanstack-supabase.ts
1721
+ import { writeFileSync as writeFileSync3, existsSync as existsSync5, mkdirSync, copyFileSync } from "fs";
1722
+ import { join as join2 } from "path";
1674
1723
  var CLIENT_TUNNEL = [
1675
1724
  "",
1676
1725
  " // PATCHSTACK: in the browser, tunnel Supabase traffic through the app's own server guard",
@@ -1684,101 +1733,127 @@ var CLIENT_TUNNEL = [
1684
1733
  " }",
1685
1734
  ""
1686
1735
  ].join("\n");
1687
- var START_IMPORTS = [
1688
- 'import { getRequest } from "@tanstack/react-start/server";',
1689
- 'import { GUARD_PATH, handleGuardRequest, inspectServerFn, screenResponse } from "@/integrations/patchstack/guard";'
1690
- ].join("\n");
1691
- var REQUEST_MIDDLEWARE_DEF = [
1692
- "",
1693
- "// Patchstack guard (browser tunnel): intercept tunneled Supabase traffic before anything else,",
1694
- "// then screen the outgoing response (SSR HTML / data) for leaked secrets & PII.",
1736
+ var GUARD_IMPORT = 'import { GUARD_PATH, handleGuardRequest, inspectServerFn, screenResponse, guardRequest } from "@/integrations/patchstack/guard";';
1737
+ var GUARD_IMPORT_RE = /import \{[^}]*\} from "@\/integrations\/patchstack\/guard";/;
1738
+ var START_IMPORTS = ['import { getRequest } from "@tanstack/react-start/server";', GUARD_IMPORT].join("\n");
1739
+ var REQUEST_MIDDLEWARE_BLOCK = [
1740
+ "// #region patchstack-guard (managed by patchstack-connect protect \u2014 do not edit)",
1741
+ "// Browser\u2192Supabase tunnel + response screening; optional route WAF via PATCHSTACK_ROUTE_WAF=1.",
1695
1742
  "const patchstackGuard = createMiddleware().server(async ({ next }) => {",
1696
1743
  " const request = getRequest();",
1697
1744
  " if (request) {",
1698
1745
  " const { pathname } = new URL(request.url);",
1699
1746
  " if (pathname === GUARD_PATH) return handleGuardRequest(request);",
1747
+ ' if (process.env.PATCHSTACK_ROUTE_WAF === "1") {',
1748
+ " const blocked = await guardRequest(request);",
1749
+ " if (blocked) return blocked;",
1750
+ " }",
1700
1751
  " }",
1701
1752
  " return screenResponse(await next());",
1702
1753
  "});",
1703
- ""
1754
+ "// #endregion patchstack-guard"
1704
1755
  ].join("\n");
1705
- var FUNCTION_MIDDLEWARE_DEF = [
1706
- "",
1707
- "// Patchstack guard (server functions): inspect server-fn args before they reach the database,",
1708
- "// covering apps that mutate via TanStack server functions (which bypass the browser tunnel).",
1756
+ var FUNCTION_MIDDLEWARE_BLOCK = [
1757
+ "// #region patchstack-function-guard (managed by patchstack-connect protect \u2014 do not edit)",
1758
+ "// Inspect server-function args before they reach the database.",
1709
1759
  'const patchstackFunctionGuard = createMiddleware({ type: "function" }).server(async ({ next, data }) => {',
1710
1760
  " const blocked = await inspectServerFn(data);",
1711
1761
  " if (blocked) throw new Error(blocked.message);",
1712
1762
  " return next();",
1713
1763
  "});",
1714
- ""
1764
+ "// #endregion patchstack-function-guard"
1715
1765
  ].join("\n");
1716
- function detectSupportedStack(cwd) {
1717
- const pkgPath = join(cwd, "package.json");
1718
- if (!existsSync4(pkgPath)) return false;
1719
- const pkg = JSON.parse(read(pkgPath));
1720
- const deps = { ...pkg.dependencies, ...pkg.devDependencies };
1721
- return Boolean(deps["@tanstack/react-start"]) && existsSync4(join(cwd, "src/start.ts")) && existsSync4(join(cwd, "src/integrations/supabase/client.ts"));
1722
- }
1723
- function scaffold(cwd) {
1724
- const dst = join(cwd, "src/integrations/patchstack");
1725
- mkdirSync(dst, { recursive: true });
1726
- copyFileSync(join(TEMPLATES, "guard.ts"), join(dst, "guard.ts"));
1727
- copyFileSync(join(TEMPLATES, "rules.json"), join(dst, "rules.json"));
1728
- log("scaffolded guard.ts + rules.json");
1729
- }
1730
- function bakeSiteUuid(cwd) {
1731
- const rc = join(cwd, ".patchstackrc.json");
1732
- if (!existsSync4(rc)) return log("no .patchstackrc.json \u2014 guard uses PATCHSTACK_SITE_UUID env or the bundled fallback");
1733
- let uuid;
1766
+ function reconcileBlock(s, region, block, legacyConst, insertBefore) {
1767
+ const lines = s.split("\n");
1768
+ const startMarker = `// #region ${region} `;
1769
+ const endMarker = `// #endregion ${region}`;
1770
+ const si = lines.findIndex((l) => l.includes(startMarker));
1771
+ if (si !== -1) {
1772
+ const ei = lines.findIndex((l, i) => i > si && l.trim() === endMarker);
1773
+ if (ei !== -1) {
1774
+ lines.splice(si, ei - si + 1, ...block.split("\n"));
1775
+ return lines.join("\n");
1776
+ }
1777
+ }
1778
+ const ci = lines.findIndex((l) => l.includes(legacyConst));
1779
+ if (ci !== -1) {
1780
+ const close = lines.findIndex((l, i) => i >= ci && l.trim() === "});");
1781
+ if (close !== -1) {
1782
+ let start = ci;
1783
+ while (start > 0 && (lines[start - 1] ?? "").trim().startsWith("//")) start--;
1784
+ lines.splice(start, close - start + 1, ...block.split("\n"));
1785
+ return lines.join("\n");
1786
+ }
1787
+ }
1788
+ return s.replace(insertBefore, block + "\n\n" + insertBefore);
1789
+ }
1790
+ function detect(cwd) {
1791
+ const pkgPath = join2(cwd, "package.json");
1792
+ if (!existsSync5(pkgPath)) return false;
1793
+ let pkg;
1734
1794
  try {
1735
- uuid = JSON.parse(read(rc)).siteUuid;
1795
+ pkg = JSON.parse(read(pkgPath));
1736
1796
  } catch {
1737
- return log(".patchstackrc.json unreadable \u2014 skipping site-UUID bake");
1797
+ return false;
1738
1798
  }
1739
- if (!uuid || !/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(uuid)) {
1740
- return log(".patchstackrc.json siteUuid missing or malformed \u2014 guard uses PATCHSTACK_SITE_UUID env or the bundled fallback");
1799
+ const deps = { ...pkg.dependencies, ...pkg.devDependencies };
1800
+ return Boolean(deps["@tanstack/react-start"]) && existsSync5(join2(cwd, "src/start.ts")) && existsSync5(join2(cwd, "src/integrations/supabase/client.ts"));
1801
+ }
1802
+ var GUARD_FILE = "src/integrations/patchstack/guard.ts";
1803
+ function scaffold(cwd, opts) {
1804
+ const templates = templatesDir();
1805
+ const dst = join2(cwd, "src/integrations/patchstack");
1806
+ mkdirSync(dst, { recursive: true });
1807
+ copyFileSync(join2(templates, "guard.ts"), join2(dst, "guard.ts"));
1808
+ const changed = [GUARD_FILE];
1809
+ const rulesDst = join2(dst, "rules.json");
1810
+ if (opts.demo) {
1811
+ copyFileSync(join2(templates, "demo-rules.json"), rulesDst);
1812
+ changed.push("src/integrations/patchstack/rules.json");
1813
+ log("scaffolded guard.ts + rules.json (demo sample rule set)");
1814
+ } else if (!existsSync5(rulesDst)) {
1815
+ copyFileSync(join2(templates, "rules.json"), rulesDst);
1816
+ changed.push("src/integrations/patchstack/rules.json");
1817
+ log("scaffolded guard.ts + rules.json (starter rules)");
1818
+ } else {
1819
+ log("scaffolded guard.ts (kept existing rules.json)");
1741
1820
  }
1742
- const p = join(cwd, "src/integrations/patchstack/guard.ts");
1743
- if (!existsSync4(p)) return;
1744
- const s = read(p);
1745
- if (!s.includes("__PATCHSTACK_SITE_UUID__")) return log("guard.ts site UUID already baked");
1746
- writeFileSync2(p, s.replace("__PATCHSTACK_SITE_UUID__", uuid));
1747
- log("baked site UUID into guard.ts \u2014 live rules from the Patchstack API");
1821
+ return changed;
1748
1822
  }
1749
1823
  function patchClient(cwd) {
1750
- const p = join(cwd, "src/integrations/supabase/client.ts");
1751
- let s = read(p);
1752
- if (s.includes("x-ps-target")) return log("client.ts already wired");
1824
+ const p = join2(cwd, "src/integrations/supabase/client.ts");
1825
+ const s = read(p);
1826
+ if (s.includes("x-ps-target")) {
1827
+ log("client.ts already wired");
1828
+ return false;
1829
+ }
1753
1830
  const anchor = "headers.set('apikey', supabaseKey);";
1754
- if (!s.includes(anchor)) return log("client.ts anchor not found \u2014 skipping (template changed?)");
1755
- writeFileSync2(p, s.replace(anchor, anchor + "\n" + CLIENT_TUNNEL));
1831
+ if (!s.includes(anchor)) {
1832
+ log("client.ts anchor not found \u2014 skipping (template changed?)");
1833
+ return false;
1834
+ }
1835
+ writeFileSync3(p, s.replace(anchor, anchor + "\n" + CLIENT_TUNNEL));
1756
1836
  log("patched client.ts (tunnel Supabase through the guard)");
1837
+ return true;
1757
1838
  }
1758
1839
  function patchStart(cwd) {
1759
- const p = join(cwd, "src/start.ts");
1840
+ const p = join2(cwd, "src/start.ts");
1760
1841
  let s = read(p);
1761
1842
  const importAnchor = 'import { createStart, createMiddleware } from "@tanstack/react-start";';
1762
1843
  const exportAnchor = "export const startInstance";
1763
1844
  const rmAnchor = "requestMiddleware: [";
1764
1845
  if (!s.includes(importAnchor) || !s.includes(exportAnchor)) {
1765
- return log("start.ts anchors not found \u2014 skipping (template changed?)");
1846
+ log("start.ts anchors not found \u2014 skipping (template changed?)");
1847
+ return false;
1766
1848
  }
1767
1849
  const original = s;
1768
- if (!s.includes("@/integrations/patchstack/guard")) {
1850
+ if (GUARD_IMPORT_RE.test(s)) {
1851
+ s = s.replace(GUARD_IMPORT_RE, GUARD_IMPORT);
1852
+ } else {
1769
1853
  s = s.replace(importAnchor, importAnchor + "\n" + START_IMPORTS);
1770
- } else if (!s.includes("inspectServerFn")) {
1771
- s = s.replace(
1772
- 'import { GUARD_PATH, handleGuardRequest } from "@/integrations/patchstack/guard";',
1773
- 'import { GUARD_PATH, handleGuardRequest, inspectServerFn } from "@/integrations/patchstack/guard";'
1774
- );
1775
- }
1776
- if (!s.includes("const patchstackGuard =")) {
1777
- s = s.replace(exportAnchor, REQUEST_MIDDLEWARE_DEF + "\n" + exportAnchor);
1778
- }
1779
- if (!s.includes("const patchstackFunctionGuard =")) {
1780
- s = s.replace(exportAnchor, FUNCTION_MIDDLEWARE_DEF + "\n" + exportAnchor);
1781
1854
  }
1855
+ s = reconcileBlock(s, "patchstack-guard", REQUEST_MIDDLEWARE_BLOCK, "const patchstackGuard =", exportAnchor);
1856
+ s = reconcileBlock(s, "patchstack-function-guard", FUNCTION_MIDDLEWARE_BLOCK, "const patchstackFunctionGuard =", exportAnchor);
1782
1857
  if (s.includes(rmAnchor) && !s.includes("requestMiddleware: [patchstackGuard")) {
1783
1858
  s = s.replace(rmAnchor, rmAnchor + "patchstackGuard, ");
1784
1859
  }
@@ -1790,24 +1865,516 @@ function patchStart(cwd) {
1790
1865
  s = s.replace(rmAnchor, "functionMiddleware: [patchstackFunctionGuard],\n " + rmAnchor);
1791
1866
  }
1792
1867
  }
1793
- if (s === original) return log("start.ts already wired");
1794
- writeFileSync2(p, s);
1868
+ if (s === original) {
1869
+ log("start.ts already wired");
1870
+ return false;
1871
+ }
1872
+ writeFileSync3(p, s);
1795
1873
  log("patched start.ts (guard registered as request + function middleware)");
1874
+ return true;
1875
+ }
1876
+ function wire(cwd, opts) {
1877
+ const changed = scaffold(cwd, opts);
1878
+ if (!opts.demo && bakeSiteUuid(cwd, GUARD_FILE)) changed.push(GUARD_FILE);
1879
+ if (patchClient(cwd)) changed.push("src/integrations/supabase/client.ts");
1880
+ if (patchStart(cwd)) changed.push("src/start.ts");
1881
+ log(
1882
+ opts.demo ? "done \u2014 guard wired with the demo sample rules (blocks by default). Set PATCHSTACK_MODE=dry-run for log-only." : "done \u2014 guard wired and always-on (blocks by default). Set PATCHSTACK_MODE=dry-run for log-only."
1883
+ );
1884
+ return { ok: true, changed: [...new Set(changed)] };
1885
+ }
1886
+ function verify(cwd) {
1887
+ const guardPath = join2(cwd, GUARD_FILE);
1888
+ const clientPath = join2(cwd, "src/integrations/supabase/client.ts");
1889
+ const startPath = join2(cwd, "src/start.ts");
1890
+ const guard = existsSync5(guardPath) ? read(guardPath) : "";
1891
+ const client = existsSync5(clientPath) ? read(clientPath) : "";
1892
+ const start = existsSync5(startPath) ? read(startPath) : "";
1893
+ const checks = [
1894
+ { label: "guard.ts scaffolded", ok: guard.length > 0, hint: "run `patchstack-connect protect`" },
1895
+ { label: "Supabase client tunnels through the guard", ok: client.includes("x-ps-target"), hint: "run `patchstack-connect protect` to re-patch src/integrations/supabase/client.ts" },
1896
+ { label: "request middleware defined + registered", ok: start.includes("const patchstackGuard =") && start.includes("requestMiddleware: [patchstackGuard"), hint: "run `patchstack-connect protect` to re-patch src/start.ts" },
1897
+ { label: "server-function middleware defined + registered", ok: start.includes("const patchstackFunctionGuard =") && start.includes("functionMiddleware: [patchstackFunctionGuard"), hint: "run `patchstack-connect protect` to re-patch src/start.ts" }
1898
+ ];
1899
+ return { wired: checks.every((c) => c.ok), checks };
1900
+ }
1901
+ var tanstackSupabaseAdapter = {
1902
+ name: "tanstack-supabase",
1903
+ label: "TanStack Start + Supabase",
1904
+ detect,
1905
+ wire,
1906
+ verify
1907
+ };
1908
+
1909
+ // src/protect/install/adapters/next.ts
1910
+ import { existsSync as existsSync6, mkdirSync as mkdirSync2, copyFileSync as copyFileSync2 } from "fs";
1911
+ import { join as join3 } from "path";
1912
+ function hasNextDep(cwd) {
1913
+ try {
1914
+ const pkg = JSON.parse(read(join3(cwd, "package.json")));
1915
+ return Boolean({ ...pkg.dependencies, ...pkg.devDependencies }.next);
1916
+ } catch {
1917
+ return false;
1918
+ }
1796
1919
  }
1797
- function runProtect(cwd) {
1798
- if (!detectSupportedStack(cwd)) {
1799
- log("runtime protection currently supports TanStack Start + Supabase apps; stack not detected \u2014 skipping.");
1800
- return;
1920
+ function middlewareInfo(cwd) {
1921
+ const candidates = ["middleware.ts", "middleware.js", "src/middleware.ts", "src/middleware.js"];
1922
+ for (const rel of candidates) {
1923
+ if (existsSync6(join3(cwd, rel))) return { relDir: rel.includes("/") ? "src" : ".", relFile: rel, exists: true };
1924
+ }
1925
+ const useSrc = existsSync6(join3(cwd, "src"));
1926
+ return { relDir: useSrc ? "src" : ".", relFile: useSrc ? "src/middleware.ts" : "middleware.ts", exists: false };
1927
+ }
1928
+ function detect2(cwd) {
1929
+ return hasNextDep(cwd);
1930
+ }
1931
+ function rulesFile(relDir) {
1932
+ return relDir === "." ? "patchstack.rules.json" : `${relDir}/patchstack.rules.json`;
1933
+ }
1934
+ function wire2(cwd, opts) {
1935
+ const templates = templatesDir();
1936
+ const mw = middlewareInfo(cwd);
1937
+ const dir = join3(cwd, mw.relDir === "." ? "" : mw.relDir);
1938
+ mkdirSync2(dir, { recursive: true });
1939
+ const rulesDst = join3(dir, "patchstack.rules.json");
1940
+ const changed = [];
1941
+ if (opts.demo || !existsSync6(rulesDst)) {
1942
+ copyFileSync2(join3(templates, opts.demo ? "demo-rules.json" : "rules.json"), rulesDst);
1943
+ changed.push(rulesFile(mw.relDir));
1944
+ }
1945
+ const mwPath = join3(cwd, mw.relFile);
1946
+ const existing = mw.exists ? read(mwPath) : "";
1947
+ if (mw.exists && !existing.includes("patchstack-next")) {
1948
+ log(
1949
+ `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`
1950
+ );
1951
+ return { ok: true, changed };
1952
+ }
1953
+ copyFileSync2(join3(templates, "next-middleware.ts"), mwPath);
1954
+ if (!opts.demo) bakeSiteUuid(cwd, mw.relFile);
1955
+ changed.push(mw.relFile);
1956
+ log(mw.exists ? `refreshed ${mw.relFile} (Patchstack middleware)` : `scaffolded ${mw.relFile} (Patchstack middleware)`);
1957
+ return { ok: true, changed: [...new Set(changed)] };
1958
+ }
1959
+ function verify2(cwd) {
1960
+ const mw = middlewareInfo(cwd);
1961
+ const present = mw.exists && read(join3(cwd, mw.relFile)).includes("patchstack-next");
1962
+ const rulesPresent = existsSync6(join3(cwd, rulesFile(mw.relDir)));
1963
+ return {
1964
+ wired: present && rulesPresent,
1965
+ checks: [
1966
+ { label: "Patchstack middleware present", ok: present, hint: `run \`patchstack-connect protect\` (writes ${mw.relFile})` },
1967
+ { label: "rules co-located with the middleware", ok: rulesPresent, hint: "run `patchstack-connect protect`" }
1968
+ ]
1969
+ };
1970
+ }
1971
+ var nextAdapter = {
1972
+ name: "nextjs",
1973
+ label: "Next.js",
1974
+ detect: detect2,
1975
+ wire: wire2,
1976
+ verify: verify2
1977
+ };
1978
+
1979
+ // src/protect/install/adapters/sveltekit.ts
1980
+ import { join as join5 } from "path";
1981
+
1982
+ // src/protect/install/seam.ts
1983
+ import { existsSync as existsSync7, mkdirSync as mkdirSync3, copyFileSync as copyFileSync3 } from "fs";
1984
+ import { join as join4, dirname as dirname2 } from "path";
1985
+ function rulesRel(seamRel) {
1986
+ const d = dirname2(seamRel);
1987
+ return (d === "." ? "patchstack.rules.json" : `${d}/patchstack.rules.json`).replace(/\\/g, "/");
1988
+ }
1989
+ function wireSeam(cwd, opts, spec) {
1990
+ const templates = templatesDir();
1991
+ const existing = spec.candidates.find((c) => existsSync7(join4(cwd, c)));
1992
+ const seamRel = existing ?? spec.target;
1993
+ mkdirSync3(dirname2(join4(cwd, seamRel)), { recursive: true });
1994
+ const rulesDst = join4(cwd, rulesRel(seamRel));
1995
+ const changed = [];
1996
+ if (opts.demo || !existsSync7(rulesDst)) {
1997
+ copyFileSync3(join4(templates, opts.demo ? "demo-rules.json" : "rules.json"), rulesDst);
1998
+ changed.push(rulesRel(seamRel));
1999
+ }
2000
+ const current = existing ? read(join4(cwd, existing)) : "";
2001
+ if (existing && !current.includes(spec.marker)) {
2002
+ log(`existing ${existing} left untouched \u2014 scaffolded ${rulesRel(seamRel)}; ${spec.planHint}`);
2003
+ return { ok: true, changed };
2004
+ }
2005
+ copyFileSync3(join4(templates, spec.templateName), join4(cwd, seamRel));
2006
+ if (!opts.demo) bakeSiteUuid(cwd, seamRel);
2007
+ changed.push(seamRel);
2008
+ log(existing ? `refreshed ${seamRel}` : `scaffolded ${seamRel}`);
2009
+ return { ok: true, changed: [...new Set(changed)] };
2010
+ }
2011
+ function verifySeam(cwd, spec) {
2012
+ const existing = spec.candidates.find((c) => existsSync7(join4(cwd, c)));
2013
+ const seamRel = existing ?? spec.target;
2014
+ const present = existing ? read(join4(cwd, existing)).includes(spec.marker) : false;
2015
+ const rulesPresent = existsSync7(join4(cwd, rulesRel(seamRel)));
2016
+ return {
2017
+ wired: present && rulesPresent,
2018
+ checks: [
2019
+ { label: `${spec.seamLabel} present`, ok: present, hint: `run \`patchstack-connect protect\` (writes ${spec.target})` },
2020
+ { label: "rules co-located with the guard", ok: rulesPresent, hint: "run `patchstack-connect protect`" }
2021
+ ]
2022
+ };
2023
+ }
2024
+
2025
+ // src/protect/install/adapters/sveltekit.ts
2026
+ var SPEC = {
2027
+ templateName: "sveltekit-hooks.ts",
2028
+ candidates: ["src/hooks.server.ts", "src/hooks.server.js"],
2029
+ target: "src/hooks.server.ts",
2030
+ marker: "patchstack-sveltekit",
2031
+ planHint: 'add the guard to your `handle` (compose with `sequence()` from "@sveltejs/kit/hooks"), then: npx patchstack-connect protect --check',
2032
+ seamLabel: "SvelteKit server hook"
2033
+ };
2034
+ function detect3(cwd) {
2035
+ try {
2036
+ const pkg = JSON.parse(read(join5(cwd, "package.json")));
2037
+ return Boolean({ ...pkg.dependencies, ...pkg.devDependencies }["@sveltejs/kit"]);
2038
+ } catch {
2039
+ return false;
1801
2040
  }
1802
- scaffold(cwd);
1803
- bakeSiteUuid(cwd);
1804
- patchClient(cwd);
1805
- patchStart(cwd);
1806
- log("done \u2014 guard wired and always-on (blocks by default). Set PATCHSTACK_MODE=dry-run for log-only.");
2041
+ }
2042
+ function wire3(cwd, opts) {
2043
+ return wireSeam(cwd, opts, SPEC);
2044
+ }
2045
+ function verify3(cwd) {
2046
+ return verifySeam(cwd, SPEC);
2047
+ }
2048
+ var sveltekitAdapter = {
2049
+ name: "sveltekit",
2050
+ label: "SvelteKit",
2051
+ detect: detect3,
2052
+ wire: wire3,
2053
+ verify: verify3
2054
+ };
2055
+
2056
+ // src/protect/install/adapters/astro.ts
2057
+ import { join as join6 } from "path";
2058
+ var SPEC2 = {
2059
+ templateName: "astro-middleware.ts",
2060
+ candidates: ["src/middleware.ts", "src/middleware.js", "src/middleware/index.ts", "src/middleware/index.js"],
2061
+ target: "src/middleware.ts",
2062
+ marker: "patchstack-astro",
2063
+ planHint: 'add the guard to your `onRequest` (compose with `sequence()` from "astro:middleware"), then: npx patchstack-connect protect --check',
2064
+ seamLabel: "Astro middleware"
2065
+ };
2066
+ function detect4(cwd) {
2067
+ try {
2068
+ const pkg = JSON.parse(read(join6(cwd, "package.json")));
2069
+ return Boolean({ ...pkg.dependencies, ...pkg.devDependencies }.astro);
2070
+ } catch {
2071
+ return false;
2072
+ }
2073
+ }
2074
+ function wire4(cwd, opts) {
2075
+ return wireSeam(cwd, opts, SPEC2);
2076
+ }
2077
+ function verify4(cwd) {
2078
+ return verifySeam(cwd, SPEC2);
2079
+ }
2080
+ var astroAdapter = {
2081
+ name: "astro",
2082
+ label: "Astro",
2083
+ detect: detect4,
2084
+ wire: wire4,
2085
+ verify: verify4
2086
+ };
2087
+
2088
+ // src/protect/install/find-app.ts
2089
+ import { readFileSync as readFileSync4, existsSync as existsSync8, readdirSync as readdirSync3, statSync as statSync3 } from "fs";
2090
+ import { join as join7, relative, dirname as dirname3 } from "path";
2091
+ function findAppInstance(cwd, re) {
2092
+ const root = existsSync8(join7(cwd, "src")) ? join7(cwd, "src") : cwd;
2093
+ let hit = null;
2094
+ const walk2 = (dir) => {
2095
+ if (hit) return;
2096
+ let entries;
2097
+ try {
2098
+ entries = readdirSync3(dir);
2099
+ } catch {
2100
+ return;
2101
+ }
2102
+ for (const name of entries) {
2103
+ if (hit) return;
2104
+ if (name === "node_modules" || name === "patchstack" || name.startsWith(".")) continue;
2105
+ const p = join7(dir, name);
2106
+ let st;
2107
+ try {
2108
+ st = statSync3(p);
2109
+ } catch {
2110
+ continue;
2111
+ }
2112
+ if (st.isDirectory()) walk2(p);
2113
+ else if (/\.(?:ts|js|mjs|cjs)$/.test(name)) {
2114
+ let src;
2115
+ try {
2116
+ src = readFileSync4(p, "utf8");
2117
+ } catch {
2118
+ continue;
2119
+ }
2120
+ const m = re.exec(src);
2121
+ if (m) hit = { relPath: relative(cwd, p).replace(/\\/g, "/"), appVar: m[1] };
2122
+ }
2123
+ }
2124
+ };
2125
+ walk2(root);
2126
+ return hit;
2127
+ }
2128
+ function importSpecifier(fromRel, toRel) {
2129
+ let spec = relative(dirname3(fromRel), toRel).replace(/\\/g, "/").replace(/\.(?:ts|js)$/, "");
2130
+ if (!spec.startsWith(".")) spec = `./${spec}`;
2131
+ return spec;
2132
+ }
2133
+
2134
+ // src/protect/install/register.ts
2135
+ import { writeFileSync as writeFileSync5, existsSync as existsSync10 } from "fs";
2136
+ import { join as join9 } from "path";
2137
+
2138
+ // src/protect/install/generic.ts
2139
+ import { readFileSync as readFileSync5, existsSync as existsSync9, mkdirSync as mkdirSync4, copyFileSync as copyFileSync4, readdirSync as readdirSync4, statSync as statSync4 } from "fs";
2140
+ import { join as join8 } from "path";
2141
+ var GUARD_MARKER = "patchstack/guard";
2142
+ function genericDir(cwd) {
2143
+ return existsSync9(join8(cwd, "src")) ? "src/patchstack" : "patchstack";
2144
+ }
2145
+ function scaffoldGeneric(cwd, opts, guardTemplate = "generic-guard.ts") {
2146
+ const templates = templatesDir();
2147
+ const dir = genericDir(cwd);
2148
+ const dst = join8(cwd, dir);
2149
+ mkdirSync4(dst, { recursive: true });
2150
+ copyFileSync4(join8(templates, guardTemplate), join8(dst, "guard.ts"));
2151
+ const changed = [`${dir}/guard.ts`];
2152
+ if (!opts.demo) bakeSiteUuid(cwd, `${dir}/guard.ts`);
2153
+ const rulesDst = join8(dst, "rules.json");
2154
+ if (opts.demo || !existsSync9(rulesDst)) {
2155
+ copyFileSync4(join8(templates, opts.demo ? "demo-rules.json" : "rules.json"), rulesDst);
2156
+ changed.push(`${dir}/rules.json`);
2157
+ }
2158
+ return { changed, dir };
2159
+ }
2160
+ function candidateEntries(cwd) {
2161
+ const names = [
2162
+ "src/server.ts",
2163
+ "src/server.js",
2164
+ "src/index.ts",
2165
+ "src/index.js",
2166
+ "src/app.ts",
2167
+ "src/app.js",
2168
+ "src/main.ts",
2169
+ "server.ts",
2170
+ "server.js",
2171
+ "index.ts",
2172
+ "index.js",
2173
+ "app.ts",
2174
+ "app.js"
2175
+ ];
2176
+ const hits = names.filter((n) => existsSync9(join8(cwd, n)));
2177
+ try {
2178
+ const pkg = JSON.parse(read(join8(cwd, "package.json")));
2179
+ if (typeof pkg.main === "string" && existsSync9(join8(cwd, pkg.main))) hits.push(pkg.main);
2180
+ } catch {
2181
+ }
2182
+ return [...new Set(hits)];
2183
+ }
2184
+ function usesExpress(cwd) {
2185
+ try {
2186
+ const pkg = JSON.parse(read(join8(cwd, "package.json")));
2187
+ return Boolean({ ...pkg.dependencies, ...pkg.devDependencies }.express);
2188
+ } catch {
2189
+ return false;
2190
+ }
2191
+ }
2192
+ function wiringPlan(cwd, dir) {
2193
+ const entries = candidateEntries(cwd);
2194
+ const express = usesExpress(cwd);
2195
+ const lines = [
2196
+ `no built-in adapter matched this stack \u2014 scaffolded a generic guard at ${dir}/guard.ts + ${dir}/rules.json.`,
2197
+ "Finish by wiring it into your server (pick the one that fits):",
2198
+ ` \u2022 Web-Fetch entry: export default { fetch: protectFetch(yourHandler) } // import from "${dir}/guard"`,
2199
+ ` \u2022 Node / Express: app.use(patchstackMiddleware) // add before your routes`,
2200
+ entries.length ? `Likely server ${entries.length === 1 ? "entry" : "entries"}: ${entries.join(", ")}${express ? " (Express detected)" : ""}.` : "Could not locate a server entry \u2014 wire it wherever requests enter your app.",
2201
+ "Then confirm it is hooked up: npx patchstack-connect protect --check"
2202
+ ];
2203
+ return lines.join("\n");
2204
+ }
2205
+ function genericVerify(cwd) {
2206
+ const dir = genericDir(cwd);
2207
+ const scaffolded = existsSync9(join8(cwd, dir, "guard.ts"));
2208
+ const imported = scaffolded && guardIsImported(cwd, join8(cwd, dir, "guard.ts"));
2209
+ return {
2210
+ wired: scaffolded && imported,
2211
+ checks: [
2212
+ { label: "generic guard scaffolded", ok: scaffolded, hint: "run `patchstack-connect protect`" },
2213
+ {
2214
+ label: "guard imported into a server entry",
2215
+ ok: imported,
2216
+ hint: `import { protectFetch } (or patchstackMiddleware) from "${dir}/guard" and wire it into your request path`
2217
+ }
2218
+ ]
2219
+ };
2220
+ }
2221
+ function guardIsImported(cwd, guardPath) {
2222
+ const root = existsSync9(join8(cwd, "src")) ? join8(cwd, "src") : cwd;
2223
+ let found = false;
2224
+ const walk2 = (d) => {
2225
+ if (found) return;
2226
+ let entries;
2227
+ try {
2228
+ entries = readdirSync4(d);
2229
+ } catch {
2230
+ return;
2231
+ }
2232
+ for (const name of entries) {
2233
+ if (found) return;
2234
+ if (name === "node_modules" || name.startsWith(".")) continue;
2235
+ const p = join8(d, name);
2236
+ let st;
2237
+ try {
2238
+ st = statSync4(p);
2239
+ } catch {
2240
+ continue;
2241
+ }
2242
+ if (st.isDirectory()) walk2(p);
2243
+ else if (/\.(?:ts|tsx|js|jsx|mjs|cjs)$/.test(name) && p !== guardPath) {
2244
+ try {
2245
+ if (readFileSync5(p, "utf8").includes(GUARD_MARKER)) found = true;
2246
+ } catch {
2247
+ }
2248
+ }
2249
+ }
2250
+ };
2251
+ walk2(root);
2252
+ return found;
2253
+ }
2254
+
2255
+ // src/protect/install/register.ts
2256
+ var REGION = "// #region patchstack (managed by patchstack-connect protect \u2014 do not edit)";
2257
+ function wireRegister(cwd, opts, spec) {
2258
+ const { changed, dir } = scaffoldGeneric(cwd, opts, spec.guardTemplate);
2259
+ const entry = findAppInstance(cwd, spec.appRe);
2260
+ if (!entry) {
2261
+ log(`${spec.label} not located \u2014 scaffolded guard; ${spec.manualHint}`);
2262
+ return { ok: true, changed };
2263
+ }
2264
+ const p = join9(cwd, entry.relPath);
2265
+ const s = read(p);
2266
+ if (s.includes(spec.importName)) {
2267
+ log(`${entry.relPath} already wired`);
2268
+ return { ok: true, changed };
2269
+ }
2270
+ const importLine = `import { ${spec.importName} } from "${importSpecifier(entry.relPath, `${dir}/guard`)}";`;
2271
+ const lines = s.split("\n");
2272
+ let lastImport = -1;
2273
+ for (let i = 0; i < lines.length; i++) if (/^\s*import\b/.test(lines[i] ?? "")) lastImport = i;
2274
+ lines.splice(lastImport + 1, 0, importLine);
2275
+ const appIdx = lines.findIndex((l) => spec.appRe.test(l));
2276
+ if (appIdx !== -1) {
2277
+ lines.splice(appIdx + 1, 0, REGION, spec.call(entry.appVar), "// #endregion patchstack");
2278
+ }
2279
+ writeFileSync5(p, lines.join("\n"));
2280
+ changed.push(entry.relPath);
2281
+ log(`patched ${entry.relPath} (${spec.call(entry.appVar).trim()})`);
2282
+ return { ok: true, changed: [...new Set(changed)] };
2283
+ }
2284
+ function verifyRegister(cwd, spec) {
2285
+ const dir = existsSync10(join9(cwd, "src")) ? "src/patchstack" : "patchstack";
2286
+ const scaffolded = existsSync10(join9(cwd, dir, "guard.ts"));
2287
+ const entry = findAppInstance(cwd, spec.appRe);
2288
+ const wired = entry ? read(join9(cwd, entry.relPath)).includes(spec.importName) : false;
2289
+ return {
2290
+ wired: scaffolded && wired,
2291
+ checks: [
2292
+ { label: `${spec.label} guard scaffolded`, ok: scaffolded, hint: "run `patchstack-connect protect`" },
2293
+ { label: `guard registered on the ${spec.label}`, ok: wired, hint: spec.manualHint }
2294
+ ]
2295
+ };
2296
+ }
2297
+
2298
+ // src/protect/install/adapters/nestjs.ts
2299
+ var SPEC3 = {
2300
+ appRe: /(?:const|let|var)\s+([A-Za-z_$][\w$]*)\s*=\s*await\s+NestFactory\.create/,
2301
+ guardTemplate: "generic-guard.ts",
2302
+ importName: "patchstackMiddleware",
2303
+ call: (v) => `${v}.use(patchstackMiddleware);`,
2304
+ label: "NestJS app",
2305
+ manualHint: "add `app.use(patchstackMiddleware)` right after your NestFactory.create(...) call"
2306
+ };
2307
+ var nestjsAdapter = {
2308
+ name: "nestjs",
2309
+ label: "NestJS",
2310
+ detect: (cwd) => hasDependency(cwd, "@nestjs/core") && findAppInstance(cwd, SPEC3.appRe) !== null,
2311
+ wire: (cwd, opts) => wireRegister(cwd, opts, SPEC3),
2312
+ verify: (cwd) => verifyRegister(cwd, SPEC3)
2313
+ };
2314
+
2315
+ // src/protect/install/adapters/fastify.ts
2316
+ var SPEC4 = {
2317
+ appRe: /(?:const|let|var)\s+([A-Za-z_$][\w$]*)\s*=\s*(?:fastify|Fastify)\(/,
2318
+ guardTemplate: "fastify-plugin.ts",
2319
+ importName: "patchstackFastify",
2320
+ call: (v) => `${v}.register(patchstackFastify);`,
2321
+ label: "Fastify app",
2322
+ manualHint: "add `app.register(patchstackFastify)` right after you create your fastify() app"
2323
+ };
2324
+ var fastifyAdapter = {
2325
+ name: "fastify",
2326
+ label: "Fastify (Node)",
2327
+ detect: (cwd) => hasDependency(cwd, "fastify") && findAppInstance(cwd, SPEC4.appRe) !== null,
2328
+ wire: (cwd, opts) => wireRegister(cwd, opts, SPEC4),
2329
+ verify: (cwd) => verifyRegister(cwd, SPEC4)
2330
+ };
2331
+
2332
+ // src/protect/install/adapters/express.ts
2333
+ var SPEC5 = {
2334
+ appRe: /(?:const|let|var)\s+([A-Za-z_$][\w$]*)\s*=\s*express\(\)/,
2335
+ guardTemplate: "generic-guard.ts",
2336
+ importName: "patchstackMiddleware",
2337
+ call: (v) => `${v}.use(patchstackMiddleware);`,
2338
+ label: "Express app",
2339
+ manualHint: "add `app.use(patchstackMiddleware)` right after you create your express() app"
2340
+ };
2341
+ var expressAdapter = {
2342
+ name: "express",
2343
+ label: "Express (Node)",
2344
+ detect: (cwd) => hasDependency(cwd, "express") && findAppInstance(cwd, SPEC5.appRe) !== null,
2345
+ wire: (cwd, opts) => wireRegister(cwd, opts, SPEC5),
2346
+ verify: (cwd) => verifyRegister(cwd, SPEC5)
2347
+ };
2348
+
2349
+ // src/protect/install/index.ts
2350
+ var ADAPTERS = [
2351
+ tanstackSupabaseAdapter,
2352
+ nextAdapter,
2353
+ sveltekitAdapter,
2354
+ astroAdapter,
2355
+ nestjsAdapter,
2356
+ fastifyAdapter,
2357
+ expressAdapter
2358
+ ];
2359
+ function runProtect(cwd, opts = {}) {
2360
+ const adapter = ADAPTERS.find((a) => a.detect(cwd));
2361
+ if (adapter) {
2362
+ const result = adapter.wire(cwd, opts);
2363
+ return { status: "wired", adapter: adapter.name, changed: result.changed };
2364
+ }
2365
+ const { changed, dir } = scaffoldGeneric(cwd, opts);
2366
+ const plan = wiringPlan(cwd, dir);
2367
+ log(plan);
2368
+ return { status: "scaffolded", adapter: "generic", changed, plan };
2369
+ }
2370
+ function runVerify(cwd) {
2371
+ const adapter = ADAPTERS.find((a) => a.detect(cwd));
2372
+ if (adapter) return { stack: adapter.label, ...adapter.verify(cwd) };
2373
+ return { stack: "generic", ...genericVerify(cwd) };
1807
2374
  }
1808
2375
 
1809
2376
  // src/setup.ts
1810
- import { readFileSync as readFileSync4, writeFileSync as writeFileSync3 } from "fs";
2377
+ import { readFileSync as readFileSync6, writeFileSync as writeFileSync6 } from "fs";
1811
2378
  import path10 from "path";
1812
2379
  var SCAN_COMMAND = "patchstack-connect scan";
1813
2380
  var MARK_BUILD_COMMAND = "patchstack-connect mark-build";
@@ -1822,7 +2389,7 @@ function appendHook(existing, command) {
1822
2389
  }
1823
2390
  function wireBuildScripts(cwd, packageManager) {
1824
2391
  const target = path10.join(cwd, "package.json");
1825
- const raw = readFileSync4(target, "utf8");
2392
+ const raw = readFileSync6(target, "utf8");
1826
2393
  const pkg = JSON.parse(raw);
1827
2394
  const scripts = pkg.scripts ?? {};
1828
2395
  const build = scripts.build;
@@ -1866,7 +2433,7 @@ function wireBuildScripts(cwd, packageManager) {
1866
2433
  const indentMatch = raw.match(/^[\t ]+(?=")/m)?.[0];
1867
2434
  const indent = indentMatch?.includes(" ") ? " " : indentMatch?.length ?? 2;
1868
2435
  const trailingNewline = raw.endsWith("\n") ? "\n" : "";
1869
- writeFileSync3(target, `${JSON.stringify(pkg, null, indent)}${trailingNewline}`, "utf8");
2436
+ writeFileSync6(target, `${JSON.stringify(pkg, null, indent)}${trailingNewline}`, "utf8");
1870
2437
  return packageManager === "bun" ? {
1871
2438
  changed: true,
1872
2439
  strategy: "build-chain",
@@ -1899,9 +2466,14 @@ Usage:
1899
2466
  patchstack-connect mark-build [options] Stamp built HTML with a production flag +
1900
2467
  build fingerprint, and ensure the widget
1901
2468
  tag in built pages (run as a postbuild step)
1902
- patchstack-connect protect Install always-on runtime protection (the
1903
- guard) into a TanStack Start + Supabase app.
1904
- Covers the browser + server-function paths.
2469
+ patchstack-connect protect [--demo|--check] Install always-on runtime protection (the
2470
+ guard). Auto-wires known stacks (TanStack
2471
+ Start + Supabase); for others it scaffolds a
2472
+ generic guard + prints a wiring plan.
2473
+ --demo seeds a broad sample rule set (for
2474
+ demonstrations, not production).
2475
+ --check verifies the guard is wired (exit 1
2476
+ if not) \u2014 for the wire-then-verify loop.
1905
2477
  patchstack-connect guide [--full] Show this project's setup status (what's done,
1906
2478
  what's missing, with tailored commands), then
1907
2479
  print the full setup guide. --full prints the
@@ -1922,6 +2494,8 @@ Environment:
1922
2494
  PATCHSTACK_ENDPOINT API endpoint (default: https://api.patchstack.com/monitor/pulse/manifest)
1923
2495
  PATCHSTACK_TIMEOUT_MS Request timeout in ms (default: 30000)
1924
2496
  PATCHSTACK_ENVIRONMENT Manifest environment: production | sandbox (default: production)
2497
+ PATCHSTACK_MODE (protect) Runtime guard mode: block (default) | dry-run
2498
+ PATCHSTACK_ROUTE_WAF (protect) Set to 1 to also screen every request at the route level (opt-in)
1925
2499
 
1926
2500
  Precedence: CLI flag > environment variable > .patchstackrc.json.
1927
2501
 
@@ -2107,9 +2681,19 @@ function reportSourceWidget(siteUuid) {
2107
2681
  console.warn(`Widget: skipped (${err.message}).`);
2108
2682
  }
2109
2683
  }
2110
- async function runProtectCommand(_args) {
2684
+ async function runProtectCommand(args) {
2685
+ if (args.flags.get("check") === true) {
2686
+ const report = runVerify(process.cwd());
2687
+ console.log(`patchstack protect --check (${report.stack}):`);
2688
+ for (const c of report.checks) {
2689
+ console.log(` ${c.ok ? "\u2713" : "\u2717"} ${c.label}${!c.ok && c.hint ? ` \u2014 ${c.hint}` : ""}`);
2690
+ }
2691
+ console.log(report.wired ? "guard is wired \u2713" : "guard is NOT fully wired \u2717");
2692
+ return report.wired ? 0 : 1;
2693
+ }
2694
+ const demo = args.flags.get("demo") === true;
2111
2695
  try {
2112
- runProtect(process.cwd());
2696
+ runProtect(process.cwd(), { demo });
2113
2697
  } catch (err) {
2114
2698
  console.warn(`patchstack protect: skipped (${err.message}).`);
2115
2699
  }
@@ -2135,7 +2719,7 @@ async function runGuide(args) {
2135
2719
  console.log("\u2014\u2014\u2014\u2014 Full reference guide (ships as AGENT-INSTALL.md) \u2014\u2014\u2014\u2014");
2136
2720
  console.log("");
2137
2721
  const guidePath = new URL("../AGENT-INSTALL.md", import.meta.url);
2138
- console.log(readFileSync5(guidePath, "utf8"));
2722
+ console.log(readFileSync7(guidePath, "utf8"));
2139
2723
  return 0;
2140
2724
  }
2141
2725
  async function runSetup(args) {
@@ -2250,7 +2834,7 @@ async function runMarkBuild(args) {
2250
2834
  let marked = 0;
2251
2835
  let widgetTouched = 0;
2252
2836
  for (const file of files) {
2253
- const before = readFileSync5(file, "utf8");
2837
+ const before = readFileSync7(file, "utf8");
2254
2838
  let after = injectMarker(before, snippet);
2255
2839
  if (widgetUuid !== null) {
2256
2840
  const ensured = ensureWidgetInHtml(after, widgetUuid);
@@ -2260,7 +2844,7 @@ async function runMarkBuild(args) {
2260
2844
  after = ensured.html;
2261
2845
  }
2262
2846
  if (after !== before) {
2263
- writeFileSync4(file, after);
2847
+ writeFileSync7(file, after);
2264
2848
  marked += 1;
2265
2849
  }
2266
2850
  }