@patchstack/connect 0.5.4 → 0.5.6
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/AGENT-INSTALL.md +5 -5
- package/README.md +6 -5
- package/dist/cli.js +239 -140
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +55 -21
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +17 -3
- package/dist/index.d.ts +17 -3
- package/dist/index.js +54 -20
- package/dist/index.js.map +1 -1
- package/dist/protect.cjs +88 -57
- package/dist/protect.cjs.map +1 -1
- package/dist/protect.js +1 -1
- package/dist/{refresh-manifest-K3RT4XNH.js → refresh-manifest-2ALIJGZ3.js} +57 -26
- package/dist/refresh-manifest-2ALIJGZ3.js.map +1 -0
- package/package.json +1 -1
- package/dist/refresh-manifest-K3RT4XNH.js.map +0 -1
package/dist/cli.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/cli.ts
|
|
4
|
-
import { readFileSync as
|
|
5
|
-
import
|
|
4
|
+
import { readFileSync as readFileSync18, writeFileSync as writeFileSync11 } from "fs";
|
|
5
|
+
import path16 from "path";
|
|
6
6
|
import { createRequire as createRequire2 } from "module";
|
|
7
7
|
|
|
8
8
|
// src/parsers/index.ts
|
|
@@ -1245,8 +1245,8 @@ function detectHostingPlatform(env = process.env) {
|
|
|
1245
1245
|
var TOKEN_SKEW_MS = 6e4;
|
|
1246
1246
|
function buildTokenUrl(manifestEndpoint) {
|
|
1247
1247
|
const url = new URL(manifestEndpoint);
|
|
1248
|
-
const
|
|
1249
|
-
url.pathname =
|
|
1248
|
+
const path17 = url.pathname.replace(/\/$/, "");
|
|
1249
|
+
url.pathname = path17.endsWith("/manifest") ? `${path17.slice(0, -"/manifest".length)}/token` : "/monitor/pulse/token";
|
|
1250
1250
|
url.search = "";
|
|
1251
1251
|
url.hash = "";
|
|
1252
1252
|
return url.toString();
|
|
@@ -1385,8 +1385,8 @@ function authFailureMessage(status, config) {
|
|
|
1385
1385
|
}
|
|
1386
1386
|
function buildRulesUrl(manifestEndpoint, siteUuid) {
|
|
1387
1387
|
const url = new URL(manifestEndpoint);
|
|
1388
|
-
const
|
|
1389
|
-
url.pathname =
|
|
1388
|
+
const path17 = url.pathname.replace(/\/$/, "");
|
|
1389
|
+
url.pathname = path17.endsWith("/manifest") ? `${path17.slice(0, -"/manifest".length)}/rules/${encodeURIComponent(siteUuid)}` : `/monitor/pulse/rules/${encodeURIComponent(siteUuid)}`;
|
|
1390
1390
|
url.search = "";
|
|
1391
1391
|
url.hash = "";
|
|
1392
1392
|
return url.toString();
|
|
@@ -1401,16 +1401,16 @@ function buildSettingsUrl(endpoint, siteUuid) {
|
|
|
1401
1401
|
}
|
|
1402
1402
|
function buildPackageRemovedUrl(manifestEndpoint, siteUuid) {
|
|
1403
1403
|
const url = new URL(manifestEndpoint);
|
|
1404
|
-
const
|
|
1405
|
-
url.pathname =
|
|
1404
|
+
const path17 = url.pathname.replace(/\/$/, "");
|
|
1405
|
+
url.pathname = path17.endsWith("/manifest") ? `${path17.slice(0, -"/manifest".length)}/package-removed/${encodeURIComponent(siteUuid)}` : `/monitor/pulse/package-removed/${encodeURIComponent(siteUuid)}`;
|
|
1406
1406
|
url.search = "";
|
|
1407
1407
|
url.hash = "";
|
|
1408
1408
|
return url.toString();
|
|
1409
1409
|
}
|
|
1410
1410
|
function buildInputMapUrl(manifestEndpoint, siteUuid) {
|
|
1411
1411
|
const url = new URL(manifestEndpoint);
|
|
1412
|
-
const
|
|
1413
|
-
url.pathname =
|
|
1412
|
+
const path17 = url.pathname.replace(/\/$/, "");
|
|
1413
|
+
url.pathname = path17.endsWith("/manifest") ? `${path17.slice(0, -"/manifest".length)}/input-map/${encodeURIComponent(siteUuid)}` : `/monitor/pulse/input-map/${encodeURIComponent(siteUuid)}`;
|
|
1414
1414
|
url.search = "";
|
|
1415
1415
|
url.hash = "";
|
|
1416
1416
|
return url.toString();
|
|
@@ -1827,9 +1827,11 @@ function renderDemoTestCommands(url, scenario) {
|
|
|
1827
1827
|
|
|
1828
1828
|
// src/config.ts
|
|
1829
1829
|
import { readFile as readFile9, writeFile, chmod } from "fs/promises";
|
|
1830
|
-
import
|
|
1830
|
+
import path8 from "path";
|
|
1831
1831
|
|
|
1832
1832
|
// src/environment.ts
|
|
1833
|
+
import { readFileSync } from "fs";
|
|
1834
|
+
import path6 from "path";
|
|
1833
1835
|
var set = (value) => value !== void 0 && value !== "";
|
|
1834
1836
|
var DISCRIMINATORS = [
|
|
1835
1837
|
{
|
|
@@ -1861,13 +1863,42 @@ var DISCRIMINATORS = [
|
|
|
1861
1863
|
}
|
|
1862
1864
|
}
|
|
1863
1865
|
];
|
|
1864
|
-
|
|
1866
|
+
var HOSTED_BUILDER_PACKAGES = [
|
|
1867
|
+
// `lovable-tagger` covers projects from before ~Aug 2026; current templates ship the
|
|
1868
|
+
// `@lovable.dev/*` scoped tooling instead.
|
|
1869
|
+
{ builder: "lovable", exact: ["lovable-tagger"], prefixes: ["@lovable.dev/"] },
|
|
1870
|
+
{ builder: "replit", exact: [], prefixes: ["@replit/"] }
|
|
1871
|
+
];
|
|
1872
|
+
function detectHostedBuilder(cwd) {
|
|
1873
|
+
let declared;
|
|
1874
|
+
try {
|
|
1875
|
+
const pkg = JSON.parse(readFileSync(path6.join(cwd, "package.json"), "utf8"));
|
|
1876
|
+
declared = { ...pkg.dependencies ?? {}, ...pkg.devDependencies ?? {} };
|
|
1877
|
+
} catch {
|
|
1878
|
+
return null;
|
|
1879
|
+
}
|
|
1880
|
+
const names = Object.keys(declared);
|
|
1881
|
+
for (const rule of HOSTED_BUILDER_PACKAGES) {
|
|
1882
|
+
const hit = names.some(
|
|
1883
|
+
(name) => rule.exact.includes(name) || rule.prefixes.some((prefix) => name.startsWith(prefix))
|
|
1884
|
+
);
|
|
1885
|
+
if (hit) return rule.builder;
|
|
1886
|
+
}
|
|
1887
|
+
return null;
|
|
1888
|
+
}
|
|
1889
|
+
function inferEnvironment(env = process.env, builder = null) {
|
|
1865
1890
|
for (const discriminator of DISCRIMINATORS) {
|
|
1866
1891
|
const verdict = discriminator.read(env);
|
|
1867
1892
|
if (verdict !== null) {
|
|
1868
1893
|
return { environment: verdict.environment, evidence: [`${discriminator.platform}: ${verdict.evidence}`] };
|
|
1869
1894
|
}
|
|
1870
1895
|
}
|
|
1896
|
+
if (builder !== null) {
|
|
1897
|
+
return {
|
|
1898
|
+
environment: "production",
|
|
1899
|
+
evidence: [`${builder}: a build in a ${builder} project is its publish step`]
|
|
1900
|
+
};
|
|
1901
|
+
}
|
|
1871
1902
|
return { environment: "local", evidence: [] };
|
|
1872
1903
|
}
|
|
1873
1904
|
|
|
@@ -1940,7 +1971,7 @@ function detectSiteUrl(env = process.env) {
|
|
|
1940
1971
|
|
|
1941
1972
|
// src/site-name.ts
|
|
1942
1973
|
import { readFile as readFile8 } from "fs/promises";
|
|
1943
|
-
import
|
|
1974
|
+
import path7 from "path";
|
|
1944
1975
|
var NAME_MAX_LENGTH = 191;
|
|
1945
1976
|
var TEMPLATE_PACKAGE_NAMES = /* @__PURE__ */ new Set([
|
|
1946
1977
|
// Lovable
|
|
@@ -2017,13 +2048,13 @@ async function readIfPresent(file) {
|
|
|
2017
2048
|
}
|
|
2018
2049
|
}
|
|
2019
2050
|
async function detectSiteName(cwd) {
|
|
2020
|
-
for (const shell of ["index.html",
|
|
2021
|
-
const html = await readIfPresent(
|
|
2051
|
+
for (const shell of ["index.html", path7.join("public", "index.html")]) {
|
|
2052
|
+
const html = await readIfPresent(path7.join(cwd, shell));
|
|
2022
2053
|
if (html === null) continue;
|
|
2023
2054
|
const name = nameFromHtmlTitle(html);
|
|
2024
2055
|
if (name !== null) return { name, source: "index.html" };
|
|
2025
2056
|
}
|
|
2026
|
-
const manifest = await readIfPresent(
|
|
2057
|
+
const manifest = await readIfPresent(path7.join(cwd, "package.json"));
|
|
2027
2058
|
if (manifest !== null) {
|
|
2028
2059
|
try {
|
|
2029
2060
|
const parsed = JSON.parse(manifest);
|
|
@@ -2076,7 +2107,7 @@ async function resolveConfig(options) {
|
|
|
2076
2107
|
"CONFIG_INVALID"
|
|
2077
2108
|
);
|
|
2078
2109
|
}
|
|
2079
|
-
const inferred = environmentRaw === void 0 ? inferEnvironment(process.env) : null;
|
|
2110
|
+
const inferred = environmentRaw === void 0 ? inferEnvironment(process.env, detectHostedBuilder(options.cwd)) : null;
|
|
2080
2111
|
const environment = environmentRaw ?? inferred.environment;
|
|
2081
2112
|
const environmentEvidence = inferred?.evidence ?? [];
|
|
2082
2113
|
if (siteUuid !== null && siteUuid.length > 0 && !isUuid(siteUuid)) {
|
|
@@ -2110,14 +2141,14 @@ async function resolveConfig(options) {
|
|
|
2110
2141
|
};
|
|
2111
2142
|
}
|
|
2112
2143
|
async function writeConfigFile(cwd, config) {
|
|
2113
|
-
const target =
|
|
2144
|
+
const target = path8.join(cwd, CONFIG_FILENAME);
|
|
2114
2145
|
const content = JSON.stringify(config, null, 2) + "\n";
|
|
2115
2146
|
await writeFile(target, content, "utf8");
|
|
2116
2147
|
return target;
|
|
2117
2148
|
}
|
|
2118
2149
|
var SECRET_CONFIG_FILENAME = SECRET_FILENAME;
|
|
2119
2150
|
async function writeSecretFile(cwd, secrets) {
|
|
2120
|
-
const target =
|
|
2151
|
+
const target = path8.join(cwd, SECRET_FILENAME);
|
|
2121
2152
|
await writeFile(target, JSON.stringify(secrets, null, 2) + "\n", { encoding: "utf8", mode: 384 });
|
|
2122
2153
|
try {
|
|
2123
2154
|
await chmod(target, 384);
|
|
@@ -2127,7 +2158,7 @@ async function writeSecretFile(cwd, secrets) {
|
|
|
2127
2158
|
return { path: target, ...ignore };
|
|
2128
2159
|
}
|
|
2129
2160
|
async function ensureIgnored(cwd, entry) {
|
|
2130
|
-
const target =
|
|
2161
|
+
const target = path8.join(cwd, ".gitignore");
|
|
2131
2162
|
let existing = "";
|
|
2132
2163
|
try {
|
|
2133
2164
|
existing = await readFile9(target, "utf8");
|
|
@@ -2160,7 +2191,7 @@ ${entry}
|
|
|
2160
2191
|
}
|
|
2161
2192
|
async function secretFileIgnored(cwd) {
|
|
2162
2193
|
try {
|
|
2163
|
-
const contents = await readFile9(
|
|
2194
|
+
const contents = await readFile9(path8.join(cwd, ".gitignore"), "utf8");
|
|
2164
2195
|
if (ignoresEntry(contents, SECRET_FILENAME)) return { ignored: true };
|
|
2165
2196
|
return { ignored: false, reason: `.gitignore does not cover ${SECRET_FILENAME}` };
|
|
2166
2197
|
} catch (err) {
|
|
@@ -2211,7 +2242,7 @@ async function readConfigFile(cwd) {
|
|
|
2211
2242
|
return readJsonFile(cwd, CONFIG_FILENAME);
|
|
2212
2243
|
}
|
|
2213
2244
|
async function readJsonFile(cwd, filename) {
|
|
2214
|
-
const target =
|
|
2245
|
+
const target = path8.join(cwd, filename);
|
|
2215
2246
|
let raw;
|
|
2216
2247
|
try {
|
|
2217
2248
|
raw = await readFile9(target, "utf8");
|
|
@@ -2268,8 +2299,8 @@ function isEnvironment(value) {
|
|
|
2268
2299
|
}
|
|
2269
2300
|
|
|
2270
2301
|
// src/mark-build.ts
|
|
2271
|
-
import { existsSync, readFileSync, readdirSync, realpathSync, statSync, writeFileSync } from "fs";
|
|
2272
|
-
import
|
|
2302
|
+
import { existsSync, readFileSync as readFileSync2, readdirSync, realpathSync, statSync, writeFileSync } from "fs";
|
|
2303
|
+
import path9 from "path";
|
|
2273
2304
|
|
|
2274
2305
|
// src/stack.ts
|
|
2275
2306
|
var STACK_RULES = [
|
|
@@ -2362,6 +2393,24 @@ function isEmptyStack(stack) {
|
|
|
2362
2393
|
|
|
2363
2394
|
// src/mark-build.ts
|
|
2364
2395
|
var MARKER_ATTR = "data-patchstack-build";
|
|
2396
|
+
function marksPublishedBuild(environment) {
|
|
2397
|
+
return environment === "production";
|
|
2398
|
+
}
|
|
2399
|
+
var STALE_BUILD_WARNING_MS = 60 * 60 * 1e3;
|
|
2400
|
+
function staleBuildAge(files, startedAt) {
|
|
2401
|
+
let newest = null;
|
|
2402
|
+
for (const file of files) {
|
|
2403
|
+
try {
|
|
2404
|
+
const at = statSync(file).mtimeMs;
|
|
2405
|
+
if (newest === null || at > newest) newest = at;
|
|
2406
|
+
} catch {
|
|
2407
|
+
continue;
|
|
2408
|
+
}
|
|
2409
|
+
}
|
|
2410
|
+
if (newest === null) return null;
|
|
2411
|
+
const age = startedAt - newest;
|
|
2412
|
+
return age > STALE_BUILD_WARNING_MS ? age : null;
|
|
2413
|
+
}
|
|
2365
2414
|
var BUILD_DIR_CANDIDATES = ["dist", "build", "out", ".output/public", "_site"];
|
|
2366
2415
|
var FRAMEWORK_BUILD_DIRS = {
|
|
2367
2416
|
eleventy: ["_site"],
|
|
@@ -2382,7 +2431,7 @@ function buildDirCandidates(options = {}) {
|
|
|
2382
2431
|
}
|
|
2383
2432
|
function resolveBuildDir(cwd, override, options = {}) {
|
|
2384
2433
|
if (override !== void 0 && override !== "") {
|
|
2385
|
-
const abs =
|
|
2434
|
+
const abs = path9.resolve(cwd, override);
|
|
2386
2435
|
return existsSync(abs) && statSync(abs).isDirectory() ? abs : null;
|
|
2387
2436
|
}
|
|
2388
2437
|
let boundary;
|
|
@@ -2392,7 +2441,7 @@ function resolveBuildDir(cwd, override, options = {}) {
|
|
|
2392
2441
|
return null;
|
|
2393
2442
|
}
|
|
2394
2443
|
for (const candidate of buildDirCandidates(options)) {
|
|
2395
|
-
const abs =
|
|
2444
|
+
const abs = path9.resolve(cwd, candidate);
|
|
2396
2445
|
if (!existsSync(abs) || !statSync(abs).isDirectory()) continue;
|
|
2397
2446
|
let real;
|
|
2398
2447
|
try {
|
|
@@ -2400,7 +2449,7 @@ function resolveBuildDir(cwd, override, options = {}) {
|
|
|
2400
2449
|
} catch {
|
|
2401
2450
|
continue;
|
|
2402
2451
|
}
|
|
2403
|
-
if (real === boundary || real.startsWith(boundary +
|
|
2452
|
+
if (real === boundary || real.startsWith(boundary + path9.sep)) {
|
|
2404
2453
|
return abs;
|
|
2405
2454
|
}
|
|
2406
2455
|
}
|
|
@@ -2410,7 +2459,7 @@ function findHtmlFiles(dir) {
|
|
|
2410
2459
|
const out = [];
|
|
2411
2460
|
const walk2 = (current) => {
|
|
2412
2461
|
for (const entry of readdirSync(current, { withFileTypes: true })) {
|
|
2413
|
-
const full =
|
|
2462
|
+
const full = path9.join(current, entry.name);
|
|
2414
2463
|
if (entry.isDirectory()) {
|
|
2415
2464
|
walk2(full);
|
|
2416
2465
|
} else if (entry.isFile() && entry.name.toLowerCase().endsWith(".html")) {
|
|
@@ -2464,12 +2513,16 @@ function productionGate(framework) {
|
|
|
2464
2513
|
function hasJsxShell(framework) {
|
|
2465
2514
|
return framework !== null && JSX_SHELL_FRAMEWORKS.has(framework);
|
|
2466
2515
|
}
|
|
2467
|
-
function buildSourceMarkerSnippet(framework) {
|
|
2516
|
+
function buildSourceMarkerSnippet(framework, checksum = null) {
|
|
2468
2517
|
const gate = productionGate(framework);
|
|
2518
|
+
const statements = ["window.__PATCHSTACK_PROD__=true;"];
|
|
2519
|
+
if (checksum !== null && checksum !== "") {
|
|
2520
|
+
statements.push(`window.__PATCHSTACK_BUILD__=${JSON.stringify(checksum)};`);
|
|
2521
|
+
}
|
|
2469
2522
|
return `{${gate} && (
|
|
2470
2523
|
<script
|
|
2471
2524
|
${MARKER_ATTR}="true"
|
|
2472
|
-
dangerouslySetInnerHTML={{ __html: '
|
|
2525
|
+
dangerouslySetInnerHTML={{ __html: '${statements.join("")}' }}
|
|
2473
2526
|
/>
|
|
2474
2527
|
)}`;
|
|
2475
2528
|
}
|
|
@@ -2532,7 +2585,7 @@ function findJsxShellAnchor(source, tagName) {
|
|
|
2532
2585
|
}
|
|
2533
2586
|
return null;
|
|
2534
2587
|
}
|
|
2535
|
-
function ensureMarkerInJsxShell(source, framework) {
|
|
2588
|
+
function ensureMarkerInJsxShell(source, framework, checksum = null) {
|
|
2536
2589
|
if (!hasJsxShell(framework)) {
|
|
2537
2590
|
return { source, action: "unsupported" };
|
|
2538
2591
|
}
|
|
@@ -2540,7 +2593,7 @@ function ensureMarkerInJsxShell(source, framework) {
|
|
|
2540
2593
|
if (stripped.includes(PROD_MARKER_GLOBAL)) {
|
|
2541
2594
|
return { source: stripped, action: "manual" };
|
|
2542
2595
|
}
|
|
2543
|
-
const block = (indent) => [REGION_OPEN, ...buildSourceMarkerSnippet(framework).split("\n"), REGION_CLOSE].map((line) => `${indent}${line}`).join("\n");
|
|
2596
|
+
const block = (indent) => [REGION_OPEN, ...buildSourceMarkerSnippet(framework, checksum).split("\n"), REGION_CLOSE].map((line) => `${indent}${line}`).join("\n");
|
|
2544
2597
|
for (const tagName of ["head", "body"]) {
|
|
2545
2598
|
const anchor = findJsxShellAnchor(stripped, tagName);
|
|
2546
2599
|
if (anchor === null) continue;
|
|
@@ -2555,13 +2608,13 @@ ${block(indent)}${separator}${remainder}`,
|
|
|
2555
2608
|
}
|
|
2556
2609
|
return { source: stripped, action: "no-anchor" };
|
|
2557
2610
|
}
|
|
2558
|
-
function ensureSourceMarker(cwd, shell, framework) {
|
|
2611
|
+
function ensureSourceMarker(cwd, shell, framework, checksum = null) {
|
|
2559
2612
|
if (shell === null) {
|
|
2560
2613
|
return { shell: null, source: "", action: "no-anchor" };
|
|
2561
2614
|
}
|
|
2562
|
-
const file =
|
|
2563
|
-
const before =
|
|
2564
|
-
const result = ensureMarkerInJsxShell(before, framework);
|
|
2615
|
+
const file = path9.resolve(cwd, shell);
|
|
2616
|
+
const before = readFileSync2(file, "utf8");
|
|
2617
|
+
const result = ensureMarkerInJsxShell(before, framework, checksum);
|
|
2565
2618
|
if (result.source !== before) {
|
|
2566
2619
|
writeFileSync(file, result.source);
|
|
2567
2620
|
}
|
|
@@ -2569,15 +2622,15 @@ function ensureSourceMarker(cwd, shell, framework) {
|
|
|
2569
2622
|
}
|
|
2570
2623
|
|
|
2571
2624
|
// src/guide.ts
|
|
2572
|
-
import { existsSync as existsSync13, readFileSync as
|
|
2573
|
-
import
|
|
2625
|
+
import { existsSync as existsSync13, readFileSync as readFileSync10, readdirSync as readdirSync5, statSync as statSync4 } from "fs";
|
|
2626
|
+
import path12 from "path";
|
|
2574
2627
|
|
|
2575
2628
|
// src/architecture.ts
|
|
2576
|
-
import { existsSync as existsSync2, readFileSync as
|
|
2577
|
-
import
|
|
2629
|
+
import { existsSync as existsSync2, readFileSync as readFileSync5, statSync as statSync3 } from "fs";
|
|
2630
|
+
import path10 from "path";
|
|
2578
2631
|
|
|
2579
2632
|
// src/map/sources.ts
|
|
2580
|
-
import { readFileSync as
|
|
2633
|
+
import { readFileSync as readFileSync3, readdirSync as readdirSync2, realpathSync as realpathSync2, statSync as statSync2 } from "fs";
|
|
2581
2634
|
import { join as join2, relative, isAbsolute } from "path";
|
|
2582
2635
|
|
|
2583
2636
|
// src/map/ast.ts
|
|
@@ -2787,7 +2840,7 @@ function hasEntrySignal(text) {
|
|
|
2787
2840
|
}
|
|
2788
2841
|
function detectFramework(cwd) {
|
|
2789
2842
|
try {
|
|
2790
|
-
const pkg = JSON.parse(
|
|
2843
|
+
const pkg = JSON.parse(readFileSync3(join2(cwd, "package.json"), "utf8"));
|
|
2791
2844
|
const d = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
2792
2845
|
if (d["@tanstack/react-start"] || d["@tanstack/start"] || d["@tanstack/solid-start"]) return "tanstack-start";
|
|
2793
2846
|
if (d["next"]) return "next";
|
|
@@ -2947,10 +3000,10 @@ function detectDeploymentShapes(cwd, opts = {}) {
|
|
|
2947
3000
|
boundary = realpathSync2(boundary);
|
|
2948
3001
|
} catch {
|
|
2949
3002
|
}
|
|
2950
|
-
const inProject = (
|
|
3003
|
+
const inProject = (path17) => {
|
|
2951
3004
|
if (opts.followOutside) return true;
|
|
2952
3005
|
try {
|
|
2953
|
-
return isInside(realpathSync2(
|
|
3006
|
+
return isInside(realpathSync2(path17), boundary);
|
|
2954
3007
|
} catch {
|
|
2955
3008
|
return false;
|
|
2956
3009
|
}
|
|
@@ -3016,7 +3069,7 @@ function holdsSourceFile(dir) {
|
|
|
3016
3069
|
}
|
|
3017
3070
|
|
|
3018
3071
|
// src/map/surface.ts
|
|
3019
|
-
import { readFileSync as
|
|
3072
|
+
import { readFileSync as readFileSync4 } from "fs";
|
|
3020
3073
|
import { join as join3 } from "path";
|
|
3021
3074
|
var STATIC_GENERATORS = [
|
|
3022
3075
|
{ dep: "vite", label: "vite" },
|
|
@@ -3058,7 +3111,7 @@ var SHAPE_SIGNAL = {
|
|
|
3058
3111
|
};
|
|
3059
3112
|
function readManifest(cwd) {
|
|
3060
3113
|
try {
|
|
3061
|
-
const parsed = JSON.parse(
|
|
3114
|
+
const parsed = JSON.parse(readFileSync4(join3(cwd, "package.json"), "utf8"));
|
|
3062
3115
|
return typeof parsed === "object" && parsed !== null ? parsed : null;
|
|
3063
3116
|
} catch {
|
|
3064
3117
|
return null;
|
|
@@ -3071,7 +3124,7 @@ function nextExportsStatically(cwd, manifest, ts) {
|
|
|
3071
3124
|
for (const file of ["next.config.js", "next.config.mjs", "next.config.ts", "next.config.cjs"]) {
|
|
3072
3125
|
let text;
|
|
3073
3126
|
try {
|
|
3074
|
-
text =
|
|
3127
|
+
text = readFileSync4(join3(cwd, file), "utf8");
|
|
3075
3128
|
} catch {
|
|
3076
3129
|
continue;
|
|
3077
3130
|
}
|
|
@@ -3230,7 +3283,7 @@ var SERVING_CALL = /\b(?:createServer|createSecureServer|Bun\.serve|Deno\.serve|
|
|
|
3230
3283
|
var MAX_ENTRY_BYTES = 256 * 1024;
|
|
3231
3284
|
function readManifest2(cwd) {
|
|
3232
3285
|
try {
|
|
3233
|
-
const parsed = JSON.parse(
|
|
3286
|
+
const parsed = JSON.parse(readFileSync5(path10.join(cwd, "package.json"), "utf8"));
|
|
3234
3287
|
return typeof parsed === "object" && parsed !== null ? parsed : {};
|
|
3235
3288
|
} catch {
|
|
3236
3289
|
return {};
|
|
@@ -3259,16 +3312,16 @@ function staticGenerators(deps) {
|
|
|
3259
3312
|
}
|
|
3260
3313
|
function serverEntries(cwd, manifest) {
|
|
3261
3314
|
const candidates = new Set(SERVER_ENTRY_CANDIDATES);
|
|
3262
|
-
if (typeof manifest.main === "string" && manifest.main !== "" && !
|
|
3263
|
-
const main2 =
|
|
3315
|
+
if (typeof manifest.main === "string" && manifest.main !== "" && !path10.isAbsolute(manifest.main)) {
|
|
3316
|
+
const main2 = path10.normalize(manifest.main);
|
|
3264
3317
|
if (!main2.startsWith("..")) candidates.add(main2);
|
|
3265
3318
|
}
|
|
3266
3319
|
const found = [];
|
|
3267
3320
|
for (const relative7 of candidates) {
|
|
3268
|
-
const file =
|
|
3321
|
+
const file = path10.join(cwd, relative7);
|
|
3269
3322
|
try {
|
|
3270
3323
|
if (!existsSync2(file) || !statSync3(file).isFile()) continue;
|
|
3271
|
-
const text =
|
|
3324
|
+
const text = readFileSync5(file, "utf8").slice(0, MAX_ENTRY_BYTES);
|
|
3272
3325
|
if (SERVING_CALL.test(text)) found.push(relative7);
|
|
3273
3326
|
} catch {
|
|
3274
3327
|
}
|
|
@@ -3322,10 +3375,10 @@ function classifyArchitecture(cwd) {
|
|
|
3322
3375
|
}
|
|
3323
3376
|
|
|
3324
3377
|
// src/protect/install/util.ts
|
|
3325
|
-
import { readFileSync as
|
|
3378
|
+
import { readFileSync as readFileSync6, existsSync as existsSync3, writeFileSync as writeFileSync2 } from "fs";
|
|
3326
3379
|
import { join as join4, dirname } from "path";
|
|
3327
3380
|
import { fileURLToPath } from "url";
|
|
3328
|
-
var read = (p) =>
|
|
3381
|
+
var read = (p) => readFileSync6(p, "utf8");
|
|
3329
3382
|
var log = (msg) => console.log(`patchstack protect: ${msg}`);
|
|
3330
3383
|
function hasDependency(cwd, name) {
|
|
3331
3384
|
try {
|
|
@@ -3798,7 +3851,7 @@ var nuxtAdapter = {
|
|
|
3798
3851
|
};
|
|
3799
3852
|
|
|
3800
3853
|
// src/protect/install/find-app.ts
|
|
3801
|
-
import { readFileSync as
|
|
3854
|
+
import { readFileSync as readFileSync7, existsSync as existsSync7, readdirSync as readdirSync3, lstatSync } from "fs";
|
|
3802
3855
|
import { join as join10, relative as relative2, dirname as dirname3 } from "path";
|
|
3803
3856
|
var SKIP_DIRS2 = /* @__PURE__ */ new Set([
|
|
3804
3857
|
"node_modules",
|
|
@@ -3844,7 +3897,7 @@ function findAppInstance(cwd, re) {
|
|
|
3844
3897
|
else if (/\.(?:ts|js|mjs|cjs)$/.test(name)) {
|
|
3845
3898
|
let src;
|
|
3846
3899
|
try {
|
|
3847
|
-
src =
|
|
3900
|
+
src = readFileSync7(p, "utf8");
|
|
3848
3901
|
} catch {
|
|
3849
3902
|
continue;
|
|
3850
3903
|
}
|
|
@@ -3891,7 +3944,7 @@ function declaredEntries(cwd) {
|
|
|
3891
3944
|
const paths = /* @__PURE__ */ new Set();
|
|
3892
3945
|
let pkg;
|
|
3893
3946
|
try {
|
|
3894
|
-
pkg = JSON.parse(
|
|
3947
|
+
pkg = JSON.parse(readFileSync7(join10(cwd, "package.json"), "utf8"));
|
|
3895
3948
|
} catch {
|
|
3896
3949
|
return paths;
|
|
3897
3950
|
}
|
|
@@ -3921,7 +3974,7 @@ import { writeFileSync as writeFileSync5, existsSync as existsSync10 } from "fs"
|
|
|
3921
3974
|
import { join as join13, resolve as resolve2 } from "path";
|
|
3922
3975
|
|
|
3923
3976
|
// src/protect/install/generic.ts
|
|
3924
|
-
import { readFileSync as
|
|
3977
|
+
import { readFileSync as readFileSync8, existsSync as existsSync9, mkdirSync as mkdirSync4, copyFileSync as copyFileSync4, readdirSync as readdirSync4, lstatSync as lstatSync2 } from "fs";
|
|
3925
3978
|
import { join as join12, dirname as dirname5 } from "path";
|
|
3926
3979
|
|
|
3927
3980
|
// src/protect/install/source-scope.ts
|
|
@@ -4473,7 +4526,7 @@ function guardIsImported(cwd, guardPath) {
|
|
|
4473
4526
|
if (st.isDirectory()) walk2(p, depth + 1);
|
|
4474
4527
|
else if (/\.(?:ts|tsx|js|jsx|mjs|cjs)$/.test(name) && p !== guardPath) {
|
|
4475
4528
|
try {
|
|
4476
|
-
if (importsAndUsesGuard(
|
|
4529
|
+
if (importsAndUsesGuard(readFileSync8(p, "utf8"), p, guardDir, packageIsModule)) found = true;
|
|
4477
4530
|
} catch {
|
|
4478
4531
|
}
|
|
4479
4532
|
}
|
|
@@ -4957,8 +5010,8 @@ function runVerify(cwd) {
|
|
|
4957
5010
|
}
|
|
4958
5011
|
|
|
4959
5012
|
// src/widget.ts
|
|
4960
|
-
import { existsSync as existsSync12, readFileSync as
|
|
4961
|
-
import
|
|
5013
|
+
import { existsSync as existsSync12, readFileSync as readFileSync9, writeFileSync as writeFileSync6 } from "fs";
|
|
5014
|
+
import path11 from "path";
|
|
4962
5015
|
var WIDGET_SCRIPT_URL = "https://cdn.patchstack.com/patchstack-widget.js";
|
|
4963
5016
|
var WIDGET_MARKER_ATTR = "data-patchstack-connect-widget";
|
|
4964
5017
|
var WIDGET_NEEDLE = "patchstack-widget";
|
|
@@ -4996,19 +5049,22 @@ ${indent}</body>`;
|
|
|
4996
5049
|
}
|
|
4997
5050
|
function findSourceShell(cwd) {
|
|
4998
5051
|
for (const candidate of SOURCE_SHELL_CANDIDATES) {
|
|
4999
|
-
if (existsSync12(
|
|
5052
|
+
if (existsSync12(path11.join(cwd, candidate))) {
|
|
5000
5053
|
return candidate;
|
|
5001
5054
|
}
|
|
5002
5055
|
}
|
|
5003
5056
|
return null;
|
|
5004
5057
|
}
|
|
5005
|
-
function ensureSourceWidget(cwd, siteUuid) {
|
|
5006
|
-
const shell = findSourceShell(cwd);
|
|
5058
|
+
function ensureSourceWidget(cwd, siteUuid, jsxShell = null) {
|
|
5059
|
+
const shell = findSourceShell(cwd) ?? jsxShell;
|
|
5007
5060
|
if (shell === null) {
|
|
5008
5061
|
return { shell: null, action: "no-shell" };
|
|
5009
5062
|
}
|
|
5010
|
-
const file =
|
|
5011
|
-
|
|
5063
|
+
const file = path11.join(cwd, shell);
|
|
5064
|
+
if (!existsSync12(file)) {
|
|
5065
|
+
return { shell: null, action: "no-shell" };
|
|
5066
|
+
}
|
|
5067
|
+
const before = readFileSync9(file, "utf8");
|
|
5012
5068
|
const { html, action } = ensureWidgetInHtml(before, siteUuid);
|
|
5013
5069
|
if (html !== before) {
|
|
5014
5070
|
writeFileSync6(file, html);
|
|
@@ -5090,7 +5146,7 @@ function detectPackageManager(cwd) {
|
|
|
5090
5146
|
return declared;
|
|
5091
5147
|
}
|
|
5092
5148
|
for (const { filename, pm } of PM_BY_LOCKFILE) {
|
|
5093
|
-
if (existsSync13(
|
|
5149
|
+
if (existsSync13(path12.join(cwd, filename))) {
|
|
5094
5150
|
return pm;
|
|
5095
5151
|
}
|
|
5096
5152
|
}
|
|
@@ -5101,7 +5157,7 @@ function installCommand(pm) {
|
|
|
5101
5157
|
}
|
|
5102
5158
|
function readPackageJson(cwd) {
|
|
5103
5159
|
try {
|
|
5104
|
-
return JSON.parse(
|
|
5160
|
+
return JSON.parse(readFileSync10(path12.join(cwd, "package.json"), "utf8"));
|
|
5105
5161
|
} catch {
|
|
5106
5162
|
return null;
|
|
5107
5163
|
}
|
|
@@ -5109,7 +5165,7 @@ function readPackageJson(cwd) {
|
|
|
5109
5165
|
function installedVersion(cwd, declaredRange) {
|
|
5110
5166
|
try {
|
|
5111
5167
|
const pkg = JSON.parse(
|
|
5112
|
-
|
|
5168
|
+
readFileSync10(path12.join(cwd, "node_modules", "@patchstack", "connect", "package.json"), "utf8")
|
|
5113
5169
|
);
|
|
5114
5170
|
if (typeof pkg.version === "string" && pkg.version.length > 0) {
|
|
5115
5171
|
return pkg.version;
|
|
@@ -5137,7 +5193,7 @@ function findWidgetMarker(cwd, siteUuid) {
|
|
|
5137
5193
|
if (budget <= 0 || settled()) {
|
|
5138
5194
|
return;
|
|
5139
5195
|
}
|
|
5140
|
-
const full =
|
|
5196
|
+
const full = path12.join(dir, entry.name);
|
|
5141
5197
|
if (entry.isDirectory()) {
|
|
5142
5198
|
if (SKIPPED_DIRS.has(entry.name) || entry.name.startsWith(".")) {
|
|
5143
5199
|
continue;
|
|
@@ -5145,7 +5201,7 @@ function findWidgetMarker(cwd, siteUuid) {
|
|
|
5145
5201
|
walk2(full, depth + 1);
|
|
5146
5202
|
continue;
|
|
5147
5203
|
}
|
|
5148
|
-
if (!entry.isFile() || !WIDGET_EXTENSIONS.has(
|
|
5204
|
+
if (!entry.isFile() || !WIDGET_EXTENSIONS.has(path12.extname(entry.name).toLowerCase())) {
|
|
5149
5205
|
continue;
|
|
5150
5206
|
}
|
|
5151
5207
|
budget -= 1;
|
|
@@ -5153,7 +5209,7 @@ function findWidgetMarker(cwd, siteUuid) {
|
|
|
5153
5209
|
if (statSync4(full).size > WIDGET_SCAN_MAX_BYTES) {
|
|
5154
5210
|
continue;
|
|
5155
5211
|
}
|
|
5156
|
-
const content =
|
|
5212
|
+
const content = readFileSync10(full, "utf8");
|
|
5157
5213
|
if (!content.includes(WIDGET_NEEDLE2)) {
|
|
5158
5214
|
continue;
|
|
5159
5215
|
}
|
|
@@ -5176,7 +5232,7 @@ function findProductionMarker(cwd, widgetFileHint) {
|
|
|
5176
5232
|
return false;
|
|
5177
5233
|
}
|
|
5178
5234
|
try {
|
|
5179
|
-
return
|
|
5235
|
+
return readFileSync10(path12.join(cwd, widgetFileHint), "utf8").includes(PROD_MARKER_NEEDLE);
|
|
5180
5236
|
} catch {
|
|
5181
5237
|
return false;
|
|
5182
5238
|
}
|
|
@@ -5187,7 +5243,7 @@ function resolveWidgetFileHint(cwd, framework) {
|
|
|
5187
5243
|
...GENERIC_WIDGET_FILES
|
|
5188
5244
|
];
|
|
5189
5245
|
for (const candidate of candidates) {
|
|
5190
|
-
if (existsSync13(
|
|
5246
|
+
if (existsSync13(path12.join(cwd, candidate))) {
|
|
5191
5247
|
return candidate;
|
|
5192
5248
|
}
|
|
5193
5249
|
}
|
|
@@ -5295,7 +5351,7 @@ function renderGuideChecklist(state, useColor) {
|
|
|
5295
5351
|
const headerParts = [state.framework, state.packageManager].filter(
|
|
5296
5352
|
(part) => part !== null
|
|
5297
5353
|
);
|
|
5298
|
-
const name = state.projectName ??
|
|
5354
|
+
const name = state.projectName ?? path12.basename(process.cwd());
|
|
5299
5355
|
lines.push(paint(ANSI.bold, `Patchstack setup status \u2014 ${name} (${headerParts.join(" \xB7 ")})`));
|
|
5300
5356
|
if (state.endpointOverride !== null) {
|
|
5301
5357
|
lines.push(
|
|
@@ -5476,12 +5532,12 @@ function renderGuideChecklist(state, useColor) {
|
|
|
5476
5532
|
// src/login.ts
|
|
5477
5533
|
import { mkdtempSync } from "fs";
|
|
5478
5534
|
import { tmpdir as tmpdir2 } from "os";
|
|
5479
|
-
import
|
|
5535
|
+
import path14 from "path";
|
|
5480
5536
|
|
|
5481
5537
|
// src/device-flow.ts
|
|
5482
|
-
import { readFileSync as
|
|
5538
|
+
import { readFileSync as readFileSync11, rmSync, writeFileSync as writeFileSync7 } from "fs";
|
|
5483
5539
|
import { tmpdir } from "os";
|
|
5484
|
-
import
|
|
5540
|
+
import path13 from "path";
|
|
5485
5541
|
import { createHash as createHash2 } from "crypto";
|
|
5486
5542
|
function baseFrom(manifestEndpoint) {
|
|
5487
5543
|
const url = new URL(manifestEndpoint);
|
|
@@ -5493,7 +5549,7 @@ function baseFrom(manifestEndpoint) {
|
|
|
5493
5549
|
}
|
|
5494
5550
|
function pendingPath(siteUuid, intent) {
|
|
5495
5551
|
const key = createHash2("sha256").update(siteUuid).digest("hex").slice(0, 16);
|
|
5496
|
-
return
|
|
5552
|
+
return path13.join(tmpdir(), `patchstack-${intent}-${key}.json`);
|
|
5497
5553
|
}
|
|
5498
5554
|
function savePending(siteUuid, intent, pending) {
|
|
5499
5555
|
writeFileSync7(pendingPath(siteUuid, intent), JSON.stringify(pending), {
|
|
@@ -5503,7 +5559,7 @@ function savePending(siteUuid, intent, pending) {
|
|
|
5503
5559
|
}
|
|
5504
5560
|
function readPending(siteUuid, intent) {
|
|
5505
5561
|
try {
|
|
5506
|
-
return JSON.parse(
|
|
5562
|
+
return JSON.parse(readFileSync11(pendingPath(siteUuid, intent), "utf8"));
|
|
5507
5563
|
} catch {
|
|
5508
5564
|
return null;
|
|
5509
5565
|
}
|
|
@@ -5673,7 +5729,7 @@ async function claim2(config, onPrompt, deps = {}) {
|
|
|
5673
5729
|
import { relative as relative3 } from "path";
|
|
5674
5730
|
|
|
5675
5731
|
// src/protect/install/runtime/entry.ts
|
|
5676
|
-
import { existsSync as existsSync14, readFileSync as
|
|
5732
|
+
import { existsSync as existsSync14, readFileSync as readFileSync12, realpathSync as realpathSync3, statSync as statSync5 } from "fs";
|
|
5677
5733
|
import { join as join15, resolve as resolve3, sep } from "path";
|
|
5678
5734
|
var CONVENTIONAL = [
|
|
5679
5735
|
"server.js",
|
|
@@ -5700,15 +5756,15 @@ var CONVENTIONAL = [
|
|
|
5700
5756
|
var LOADABLE = /\.(?:js|mjs|cjs)$/;
|
|
5701
5757
|
function readPackage2(cwd) {
|
|
5702
5758
|
try {
|
|
5703
|
-
const parsed = JSON.parse(
|
|
5759
|
+
const parsed = JSON.parse(readFileSync12(join15(cwd, "package.json"), "utf8"));
|
|
5704
5760
|
return parsed !== null && typeof parsed === "object" ? parsed : null;
|
|
5705
5761
|
} catch {
|
|
5706
5762
|
return null;
|
|
5707
5763
|
}
|
|
5708
5764
|
}
|
|
5709
|
-
function isFile(
|
|
5765
|
+
function isFile(path17) {
|
|
5710
5766
|
try {
|
|
5711
|
-
return statSync5(
|
|
5767
|
+
return statSync5(path17).isFile();
|
|
5712
5768
|
} catch {
|
|
5713
5769
|
return false;
|
|
5714
5770
|
}
|
|
@@ -5717,14 +5773,14 @@ function loadable(cwd, candidate) {
|
|
|
5717
5773
|
const written = resolve3(cwd, candidate);
|
|
5718
5774
|
if (!LOADABLE.test(written) || !isFile(written)) return null;
|
|
5719
5775
|
let root;
|
|
5720
|
-
let
|
|
5776
|
+
let path17;
|
|
5721
5777
|
try {
|
|
5722
5778
|
root = realpathSync3(cwd);
|
|
5723
|
-
|
|
5779
|
+
path17 = realpathSync3(written);
|
|
5724
5780
|
} catch {
|
|
5725
5781
|
return null;
|
|
5726
5782
|
}
|
|
5727
|
-
if (
|
|
5783
|
+
if (path17 !== root && !path17.startsWith(root + sep)) return null;
|
|
5728
5784
|
return written;
|
|
5729
5785
|
}
|
|
5730
5786
|
function passable(token) {
|
|
@@ -5804,8 +5860,8 @@ function preloadPath() {
|
|
|
5804
5860
|
// beside this file, in the repository
|
|
5805
5861
|
];
|
|
5806
5862
|
for (const candidate of candidates) {
|
|
5807
|
-
const
|
|
5808
|
-
if (existsSync15(
|
|
5863
|
+
const path17 = fileURLToPath2(candidate);
|
|
5864
|
+
if (existsSync15(path17)) return path17;
|
|
5809
5865
|
}
|
|
5810
5866
|
return null;
|
|
5811
5867
|
}
|
|
@@ -6175,7 +6231,7 @@ async function loadTypeScript(cwd) {
|
|
|
6175
6231
|
}
|
|
6176
6232
|
|
|
6177
6233
|
// src/map/extract.ts
|
|
6178
|
-
import { readFileSync as
|
|
6234
|
+
import { readFileSync as readFileSync15, realpathSync as realpathSync5 } from "fs";
|
|
6179
6235
|
import { createHash as createHash5 } from "crypto";
|
|
6180
6236
|
import { relative as relative5 } from "path";
|
|
6181
6237
|
|
|
@@ -6589,7 +6645,7 @@ function dedupeSinks(sinks, owner) {
|
|
|
6589
6645
|
}
|
|
6590
6646
|
|
|
6591
6647
|
// src/map/module-graph.ts
|
|
6592
|
-
import { readFileSync as
|
|
6648
|
+
import { readFileSync as readFileSync13, realpathSync as realpathSync4, statSync as statSync6 } from "fs";
|
|
6593
6649
|
import { dirname as dirname7, join as join17, relative as relative4, resolve as resolvePath } from "path";
|
|
6594
6650
|
var RESOLVE_EXTS = [".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs"];
|
|
6595
6651
|
function createModuleGraph(ts, opts) {
|
|
@@ -6598,7 +6654,7 @@ function createModuleGraph(ts, opts) {
|
|
|
6598
6654
|
if (cache.has(file)) return cache.get(file) ?? null;
|
|
6599
6655
|
let entry = null;
|
|
6600
6656
|
try {
|
|
6601
|
-
const text =
|
|
6657
|
+
const text = readFileSync13(file, "utf8");
|
|
6602
6658
|
const sf = ts.createSourceFile(file, text, ts.ScriptTarget.Latest, true, guessScriptKind(ts, file));
|
|
6603
6659
|
const bindings = buildModuleBindings(sf, ts);
|
|
6604
6660
|
entry = { fnSinks: collectLocalSinks(sf, ts, bindings), calleesOf: collectCallees(sf, ts), bindings };
|
|
@@ -6697,8 +6753,8 @@ function collectCallees(sf, ts) {
|
|
|
6697
6753
|
}
|
|
6698
6754
|
|
|
6699
6755
|
// src/map/coordinates.ts
|
|
6700
|
-
function runtimeCoordinate(source,
|
|
6701
|
-
if (/\[\d*\]/.test(
|
|
6756
|
+
function runtimeCoordinate(source, path17) {
|
|
6757
|
+
if (/\[\d*\]/.test(path17)) {
|
|
6702
6758
|
return { runtimeParameter: null, runtimeParameterReason: "array traversal: needs an array_key_value rule, not a dotted parameter" };
|
|
6703
6759
|
}
|
|
6704
6760
|
switch (source) {
|
|
@@ -6707,15 +6763,15 @@ function runtimeCoordinate(source, path16) {
|
|
|
6707
6763
|
case "multipart":
|
|
6708
6764
|
case "body":
|
|
6709
6765
|
case "server-fn-data":
|
|
6710
|
-
return { runtimeParameter: `post.${
|
|
6766
|
+
return { runtimeParameter: `post.${path17}` };
|
|
6711
6767
|
case "query":
|
|
6712
|
-
return { runtimeParameter: `get.${
|
|
6768
|
+
return { runtimeParameter: `get.${path17}` };
|
|
6713
6769
|
case "cookie":
|
|
6714
|
-
return { runtimeParameter: `cookie.${
|
|
6770
|
+
return { runtimeParameter: `cookie.${path17}` };
|
|
6715
6771
|
case "file":
|
|
6716
|
-
return { runtimeParameter: `files.${
|
|
6772
|
+
return { runtimeParameter: `files.${path17}` };
|
|
6717
6773
|
case "header":
|
|
6718
|
-
return { runtimeParameter: `server.HTTP_${
|
|
6774
|
+
return { runtimeParameter: `server.HTTP_${path17.toUpperCase().replace(/-/g, "_")}` };
|
|
6719
6775
|
case "route-param":
|
|
6720
6776
|
return { runtimeParameter: null, runtimeParameterReason: "route parameters are not exposed by the runtime resolver" };
|
|
6721
6777
|
default:
|
|
@@ -6747,8 +6803,8 @@ function addressSpaceOf(source) {
|
|
|
6747
6803
|
function isProvenFlow(confidence) {
|
|
6748
6804
|
return confidence === "exact-local" || confidence === "transformed-local";
|
|
6749
6805
|
}
|
|
6750
|
-
function inputIdOf(source,
|
|
6751
|
-
return `${addressSpaceOf(source)}:${
|
|
6806
|
+
function inputIdOf(source, path17) {
|
|
6807
|
+
return `${addressSpaceOf(source)}:${path17}`;
|
|
6752
6808
|
}
|
|
6753
6809
|
function withCoordinates(fields, source) {
|
|
6754
6810
|
return fields.map((f) => {
|
|
@@ -6958,8 +7014,8 @@ function linkFlows(bodyNode, params, inputs, sinks, ts) {
|
|
|
6958
7014
|
if (!bodyNode || sinks.length === 0 || inputs.length === 0) return { flows: [], limitations: [] };
|
|
6959
7015
|
const CONTAINER_KEYS = /* @__PURE__ */ new Set([...REQ_SOURCES, "data", "input", "payload"]);
|
|
6960
7016
|
const rootPath = /* @__PURE__ */ new Map();
|
|
6961
|
-
const addRoot = (name,
|
|
6962
|
-
if (!rootPath.has(name)) rootPath.set(name, { path:
|
|
7017
|
+
const addRoot = (name, path17, space) => {
|
|
7018
|
+
if (!rootPath.has(name)) rootPath.set(name, { path: path17, space });
|
|
6963
7019
|
};
|
|
6964
7020
|
for (const p of params ?? []) {
|
|
6965
7021
|
if (!p?.name) continue;
|
|
@@ -7104,8 +7160,8 @@ function dedupeLimitations(list) {
|
|
|
7104
7160
|
function join22(base, seg) {
|
|
7105
7161
|
return base ? `${base}.${seg}` : seg;
|
|
7106
7162
|
}
|
|
7107
|
-
function normalizePath(
|
|
7108
|
-
return
|
|
7163
|
+
function normalizePath(path17) {
|
|
7164
|
+
return path17.replace(/\[\d*\]/g, "").split(".").filter(Boolean).join(".");
|
|
7109
7165
|
}
|
|
7110
7166
|
function fluentChainCalls(call, ts) {
|
|
7111
7167
|
let root = call;
|
|
@@ -7351,7 +7407,7 @@ function handlerEntry(name, kindLabel, params, body, ts, localSinks, bindings, c
|
|
|
7351
7407
|
}
|
|
7352
7408
|
|
|
7353
7409
|
// src/map/imports.ts
|
|
7354
|
-
import { readFileSync as
|
|
7410
|
+
import { readFileSync as readFileSync14 } from "fs";
|
|
7355
7411
|
import { join as join18 } from "path";
|
|
7356
7412
|
var MAX_SITES = 5;
|
|
7357
7413
|
var NPM_NAME = /^(?:@[^/@\s~][^/@\s]*\/)?[^/@\s.~][^/@\s]*$/;
|
|
@@ -7363,7 +7419,7 @@ function readPathAliases(cwd) {
|
|
|
7363
7419
|
for (const name of ["tsconfig.json", "jsconfig.json"]) {
|
|
7364
7420
|
let paths;
|
|
7365
7421
|
try {
|
|
7366
|
-
const raw =
|
|
7422
|
+
const raw = readFileSync14(join18(cwd, name), "utf8");
|
|
7367
7423
|
const parsed = JSON.parse(stripJsonComments(raw));
|
|
7368
7424
|
paths = parsed.compilerOptions?.paths;
|
|
7369
7425
|
} catch {
|
|
@@ -7742,7 +7798,7 @@ async function extractInputMap(cwd, ts, options = {}) {
|
|
|
7742
7798
|
const hopTargets = /* @__PURE__ */ new Set();
|
|
7743
7799
|
for (const file of files) {
|
|
7744
7800
|
try {
|
|
7745
|
-
const text =
|
|
7801
|
+
const text = readFileSync15(file, "utf8");
|
|
7746
7802
|
const relFile = relative5(cwd, file);
|
|
7747
7803
|
sourceBytes += text.length;
|
|
7748
7804
|
if (!hasEntrySignal(text)) {
|
|
@@ -7797,7 +7853,7 @@ async function extractInputMap(cwd, ts, options = {}) {
|
|
|
7797
7853
|
for (const target of hopTargets) {
|
|
7798
7854
|
if (entryFiles.has(target)) continue;
|
|
7799
7855
|
try {
|
|
7800
|
-
const text =
|
|
7856
|
+
const text = readFileSync15(target, "utf8");
|
|
7801
7857
|
const sf = ts.createSourceFile(target, text, ts.ScriptTarget.Latest, true, guessScriptKind(ts, target));
|
|
7802
7858
|
const bindings = buildModuleBindings(sf, ts);
|
|
7803
7859
|
const called = collectInvocations(sf, ts, bindings, { file: target, owner: relative5(cwd, target), graph });
|
|
@@ -7946,7 +8002,7 @@ function getStringFlag(flags, name) {
|
|
|
7946
8002
|
}
|
|
7947
8003
|
|
|
7948
8004
|
// src/build-stamp.ts
|
|
7949
|
-
import { chmodSync, lstatSync as lstatSync3, readFileSync as
|
|
8005
|
+
import { chmodSync, lstatSync as lstatSync3, readFileSync as readFileSync16, readdirSync as readdirSync6, realpathSync as realpathSync6, renameSync, unlinkSync, writeFileSync as writeFileSync8 } from "fs";
|
|
7950
8006
|
import { join as join19, relative as relative6, sep as sep2 } from "path";
|
|
7951
8007
|
var RULES_FILE_NAMES = /* @__PURE__ */ new Set(["rules.json", "patchstack.rules.json"]);
|
|
7952
8008
|
var SKIP_DIRECTORIES = /* @__PURE__ */ new Set(["node_modules", "dist", "build", "out", "coverage", "tmp", "vendor"]);
|
|
@@ -7965,11 +8021,11 @@ function guardImportsRulesFile(dir, rulesName) {
|
|
|
7965
8021
|
}
|
|
7966
8022
|
for (const name of siblings) {
|
|
7967
8023
|
if (!GUARD_SOURCE.test(name)) continue;
|
|
7968
|
-
const
|
|
8024
|
+
const path17 = join19(dir, name);
|
|
7969
8025
|
try {
|
|
7970
|
-
const entry = lstatSync3(
|
|
8026
|
+
const entry = lstatSync3(path17);
|
|
7971
8027
|
if (!entry.isFile() || entry.isSymbolicLink() || entry.size > MAX_GUARD_SOURCE_BYTES) continue;
|
|
7972
|
-
const source = stripComments(
|
|
8028
|
+
const source = stripComments(readFileSync16(path17, "utf8"));
|
|
7973
8029
|
if (source.includes("@patchstack/connect/protect") && importsRules.test(source)) return true;
|
|
7974
8030
|
} catch {
|
|
7975
8031
|
}
|
|
@@ -7990,9 +8046,9 @@ function findRulesFile(cwd) {
|
|
|
7990
8046
|
} catch {
|
|
7991
8047
|
return { kind: "none" };
|
|
7992
8048
|
}
|
|
7993
|
-
const contained = (
|
|
8049
|
+
const contained = (path17) => {
|
|
7994
8050
|
try {
|
|
7995
|
-
const real = realpathSync6(
|
|
8051
|
+
const real = realpathSync6(path17);
|
|
7996
8052
|
return real === root || real.startsWith(root + sep2);
|
|
7997
8053
|
} catch {
|
|
7998
8054
|
return false;
|
|
@@ -8008,25 +8064,25 @@ function findRulesFile(cwd) {
|
|
|
8008
8064
|
}
|
|
8009
8065
|
for (const name of entries) {
|
|
8010
8066
|
if (name.startsWith(".")) continue;
|
|
8011
|
-
const
|
|
8067
|
+
const path17 = join19(dir, name);
|
|
8012
8068
|
let entry;
|
|
8013
8069
|
try {
|
|
8014
|
-
entry = lstatSync3(
|
|
8070
|
+
entry = lstatSync3(path17);
|
|
8015
8071
|
} catch {
|
|
8016
8072
|
continue;
|
|
8017
8073
|
}
|
|
8018
8074
|
if (entry.isSymbolicLink()) continue;
|
|
8019
8075
|
if (entry.isDirectory()) {
|
|
8020
|
-
if (!SKIP_DIRECTORIES.has(name)) walk2(
|
|
8076
|
+
if (!SKIP_DIRECTORIES.has(name)) walk2(path17, depth + 1);
|
|
8021
8077
|
continue;
|
|
8022
8078
|
}
|
|
8023
8079
|
if (!entry.isFile() || !RULES_FILE_NAMES.has(name)) continue;
|
|
8024
|
-
if (!contained(
|
|
8080
|
+
if (!contained(path17)) continue;
|
|
8025
8081
|
if (!guardImportsRulesFile(dir, name)) continue;
|
|
8026
8082
|
try {
|
|
8027
|
-
if (isRuleBundle(JSON.parse(
|
|
8083
|
+
if (isRuleBundle(JSON.parse(readFileSync16(path17, "utf8")))) found.push(path17);
|
|
8028
8084
|
} catch {
|
|
8029
|
-
unreadable.push(
|
|
8085
|
+
unreadable.push(path17);
|
|
8030
8086
|
}
|
|
8031
8087
|
}
|
|
8032
8088
|
};
|
|
@@ -8057,7 +8113,7 @@ function applyBuildStamp(cwd, id) {
|
|
|
8057
8113
|
const file = relative6(cwd, location.path);
|
|
8058
8114
|
let text;
|
|
8059
8115
|
try {
|
|
8060
|
-
text =
|
|
8116
|
+
text = readFileSync16(location.path, "utf8");
|
|
8061
8117
|
} catch (err) {
|
|
8062
8118
|
return { kind: "skipped", reason: `${file} could not be read (${err.message})` };
|
|
8063
8119
|
}
|
|
@@ -8275,8 +8331,8 @@ async function runMap(flags) {
|
|
|
8275
8331
|
}
|
|
8276
8332
|
|
|
8277
8333
|
// src/setup.ts
|
|
8278
|
-
import { readFileSync as
|
|
8279
|
-
import
|
|
8334
|
+
import { readFileSync as readFileSync17, writeFileSync as writeFileSync10 } from "fs";
|
|
8335
|
+
import path15 from "path";
|
|
8280
8336
|
var SCAN_COMMAND = "patchstack-connect scan";
|
|
8281
8337
|
var MARK_BUILD_COMMAND = "patchstack-connect mark-build";
|
|
8282
8338
|
function setupProtection(cwd) {
|
|
@@ -8301,8 +8357,8 @@ function prependHook(existing, command) {
|
|
|
8301
8357
|
return [command, ...remaining].join(" && ");
|
|
8302
8358
|
}
|
|
8303
8359
|
function wireBuildScripts(cwd, packageManager) {
|
|
8304
|
-
const target =
|
|
8305
|
-
const raw =
|
|
8360
|
+
const target = path15.join(cwd, "package.json");
|
|
8361
|
+
const raw = readFileSync17(target, "utf8");
|
|
8306
8362
|
const pkg = JSON.parse(raw);
|
|
8307
8363
|
const scripts = pkg.scripts ?? {};
|
|
8308
8364
|
const build = scripts.build;
|
|
@@ -8411,6 +8467,10 @@ Usage:
|
|
|
8411
8467
|
patchstack-connect mark-build [options] Stamp built HTML with a production flag +
|
|
8412
8468
|
build fingerprint, and ensure the widget
|
|
8413
8469
|
tag in built pages (run as a postbuild step).
|
|
8470
|
+
The flag marks a page as the LIVE site, so it
|
|
8471
|
+
is stamped only on a production build; a local
|
|
8472
|
+
or preview build gets the widget tag and no
|
|
8473
|
+
marker (and any stale marker is removed).
|
|
8414
8474
|
Looks in the framework's own output dir, an
|
|
8415
8475
|
--output the build script names, then dist/,
|
|
8416
8476
|
build/, out/, .output/public/, _site/ \u2014 inside
|
|
@@ -8496,8 +8556,15 @@ Options (for scan, setup, status, and uninstall):
|
|
|
8496
8556
|
too. Never written to a file, never printed back
|
|
8497
8557
|
|
|
8498
8558
|
Options (for mark-build):
|
|
8499
|
-
--dir <path> Build output directory (default: auto-detect
|
|
8500
|
-
|
|
8559
|
+
--dir <path> Build output directory (default: auto-detect the
|
|
8560
|
+
framework's own output dir, an --output the build
|
|
8561
|
+
script names, then dist/ build/ out/ .output/public/
|
|
8562
|
+
_site/ \u2014 inside the project only)
|
|
8563
|
+
--production Stamp the live-site marker on a build this command
|
|
8564
|
+
cannot tell is a deployment \u2014 publishing a static
|
|
8565
|
+
build by hand from a laptop, say. PATCHSTACK_ENVIRONMENT=production
|
|
8566
|
+
does the same. Never needed on a hosting platform,
|
|
8567
|
+
whose own build is recognised
|
|
8501
8568
|
|
|
8502
8569
|
Options (for demo and demo-guide):
|
|
8503
8570
|
--url <url> Test endpoint printed at the end
|
|
@@ -8867,8 +8934,9 @@ async function runScan(args, options = {}) {
|
|
|
8867
8934
|
const cleared = applyBuildStamp(process.cwd(), null);
|
|
8868
8935
|
if (cleared.kind === "cleared") console.log(`Removed the previous map binding from ${cleared.file}.`);
|
|
8869
8936
|
}
|
|
8937
|
+
const shellFramework = detectStack(payload.packages).framework;
|
|
8870
8938
|
if (config.widget) {
|
|
8871
|
-
reportSourceMarker(
|
|
8939
|
+
reportSourceMarker(shellFramework, computeManifestChecksum(payload.packages));
|
|
8872
8940
|
}
|
|
8873
8941
|
const provisioning = config.siteUuid === null;
|
|
8874
8942
|
if (provisioning) {
|
|
@@ -8914,7 +8982,7 @@ async function runScan(args, options = {}) {
|
|
|
8914
8982
|
const connected = response.claim?.state === "claimed" || response.claim?.state === "owned-by-you";
|
|
8915
8983
|
const effectiveUuid = config.siteUuid ?? response.uuid ?? null;
|
|
8916
8984
|
if (config.widget && effectiveUuid !== null && effectiveUuid.length > 0) {
|
|
8917
|
-
reportSourceWidget(effectiveUuid);
|
|
8985
|
+
reportSourceWidget(effectiveUuid, shellFramework);
|
|
8918
8986
|
}
|
|
8919
8987
|
const linkUuid = response.uuid ?? config.siteUuid;
|
|
8920
8988
|
if (!connected && (provisioning || claimLines.length > 0) && linkUuid !== null && linkUuid !== void 0 && linkUuid.length > 0) {
|
|
@@ -8945,9 +9013,11 @@ async function runScan(args, options = {}) {
|
|
|
8945
9013
|
}
|
|
8946
9014
|
return 0;
|
|
8947
9015
|
}
|
|
8948
|
-
function reportSourceWidget(siteUuid) {
|
|
9016
|
+
function reportSourceWidget(siteUuid, framework) {
|
|
8949
9017
|
try {
|
|
8950
|
-
const
|
|
9018
|
+
const hint = hasJsxShell(framework) ? resolveWidgetFileHint(process.cwd(), framework) : null;
|
|
9019
|
+
const jsxShell = hint !== null && !hint.toLowerCase().endsWith(".html") ? hint : null;
|
|
9020
|
+
const result = ensureSourceWidget(process.cwd(), siteUuid, jsxShell);
|
|
8951
9021
|
switch (result.action) {
|
|
8952
9022
|
case "added":
|
|
8953
9023
|
console.log(`Widget: added the "Report a vulnerability" tag to ${result.shell}. Reload your preview to see it.`);
|
|
@@ -8966,7 +9036,7 @@ function reportSourceWidget(siteUuid) {
|
|
|
8966
9036
|
console.log(` ${buildWidgetTag(siteUuid)}`);
|
|
8967
9037
|
break;
|
|
8968
9038
|
case "no-shell":
|
|
8969
|
-
console.log("Widget: no
|
|
9039
|
+
console.log("Widget: no root shell found to edit (index.html / public/index.html / src/app.html, or a JSX root).");
|
|
8970
9040
|
console.log("Add this tag to your root layout before </body> (run `guide` for framework-specific placement):");
|
|
8971
9041
|
console.log(` ${buildWidgetTag(siteUuid)}`);
|
|
8972
9042
|
break;
|
|
@@ -8978,13 +9048,13 @@ function reportSourceWidget(siteUuid) {
|
|
|
8978
9048
|
console.warn(`Widget: skipped (${err.message}).`);
|
|
8979
9049
|
}
|
|
8980
9050
|
}
|
|
8981
|
-
function reportSourceMarker(framework) {
|
|
9051
|
+
function reportSourceMarker(framework, checksum = null) {
|
|
8982
9052
|
try {
|
|
8983
9053
|
const shell = resolveWidgetFileHint(process.cwd(), framework);
|
|
8984
9054
|
if (shell === null || shell.toLowerCase().endsWith(".html")) {
|
|
8985
9055
|
return;
|
|
8986
9056
|
}
|
|
8987
|
-
const result = ensureSourceMarker(process.cwd(), shell, framework);
|
|
9057
|
+
const result = ensureSourceMarker(process.cwd(), shell, framework, checksum);
|
|
8988
9058
|
switch (result.action) {
|
|
8989
9059
|
case "added":
|
|
8990
9060
|
console.log(`Production marker: added to ${shell} (guarded by ${productionGate(framework)}).`);
|
|
@@ -9171,7 +9241,7 @@ async function runGuide(args) {
|
|
|
9171
9241
|
console.log("\u2014\u2014\u2014\u2014 Full reference guide (ships as AGENT-INSTALL.md) \u2014\u2014\u2014\u2014");
|
|
9172
9242
|
console.log("");
|
|
9173
9243
|
const guidePath = new URL("../AGENT-INSTALL.md", import.meta.url);
|
|
9174
|
-
console.log(
|
|
9244
|
+
console.log(readFileSync18(guidePath, "utf8"));
|
|
9175
9245
|
return 0;
|
|
9176
9246
|
}
|
|
9177
9247
|
async function runSetup(args) {
|
|
@@ -9346,7 +9416,7 @@ function describeStack(stack) {
|
|
|
9346
9416
|
}
|
|
9347
9417
|
function readBuildScript(cwd) {
|
|
9348
9418
|
try {
|
|
9349
|
-
const pkg = JSON.parse(
|
|
9419
|
+
const pkg = JSON.parse(readFileSync18(path16.join(cwd, "package.json"), "utf8"));
|
|
9350
9420
|
return pkg.scripts?.build;
|
|
9351
9421
|
} catch {
|
|
9352
9422
|
return void 0;
|
|
@@ -9354,6 +9424,7 @@ function readBuildScript(cwd) {
|
|
|
9354
9424
|
}
|
|
9355
9425
|
async function runMarkBuild(args) {
|
|
9356
9426
|
const cwd = process.cwd();
|
|
9427
|
+
const startedAt = Date.now();
|
|
9357
9428
|
let checksum = null;
|
|
9358
9429
|
let stack = null;
|
|
9359
9430
|
try {
|
|
@@ -9370,6 +9441,8 @@ async function runMarkBuild(args) {
|
|
|
9370
9441
|
);
|
|
9371
9442
|
}
|
|
9372
9443
|
let widgetUuid = null;
|
|
9444
|
+
let environment = "local";
|
|
9445
|
+
let environmentEvidence = [];
|
|
9373
9446
|
try {
|
|
9374
9447
|
const config = await resolveConfig({
|
|
9375
9448
|
cwd,
|
|
@@ -9378,11 +9451,15 @@ async function runMarkBuild(args) {
|
|
|
9378
9451
|
if (config.widget) {
|
|
9379
9452
|
widgetUuid = config.siteUuid;
|
|
9380
9453
|
}
|
|
9454
|
+
environment = config.environment;
|
|
9455
|
+
environmentEvidence = config.environmentEvidence ?? [];
|
|
9381
9456
|
} catch (err) {
|
|
9382
9457
|
console.warn(
|
|
9383
9458
|
`mark-build: could not resolve the site UUID (${err.message}). Skipping the widget pass.`
|
|
9384
9459
|
);
|
|
9385
9460
|
}
|
|
9461
|
+
const forcedProduction = args.flags.get("production") === true;
|
|
9462
|
+
const published = forcedProduction || marksPublishedBuild(environment);
|
|
9386
9463
|
const buildDirOptions = { framework: stack?.framework ?? null, buildScript: readBuildScript(cwd) };
|
|
9387
9464
|
const dir = resolveBuildDir(cwd, getStringFlag(args.flags, "dir"), buildDirOptions);
|
|
9388
9465
|
if (dir === null) {
|
|
@@ -9406,11 +9483,20 @@ async function runMarkBuild(args) {
|
|
|
9406
9483
|
);
|
|
9407
9484
|
return 0;
|
|
9408
9485
|
}
|
|
9409
|
-
const
|
|
9486
|
+
const staleBy = staleBuildAge(files, startedAt);
|
|
9487
|
+
if (staleBy !== null) {
|
|
9488
|
+
console.warn(
|
|
9489
|
+
`mark-build: nothing in ${dir} has been written in the last ${Math.round(staleBy / 6e4)} minute(s), so this looks like output from an earlier build.`
|
|
9490
|
+
);
|
|
9491
|
+
console.warn(
|
|
9492
|
+
"mark-build: run it as a postbuild hook (or straight after the build) so what is stamped is what was just produced."
|
|
9493
|
+
);
|
|
9494
|
+
}
|
|
9495
|
+
const snippet = published ? buildInjectionSnippet(checksum, stack) : "";
|
|
9410
9496
|
let marked = 0;
|
|
9411
9497
|
let widgetTouched = 0;
|
|
9412
9498
|
for (const file of files) {
|
|
9413
|
-
const before =
|
|
9499
|
+
const before = readFileSync18(file, "utf8");
|
|
9414
9500
|
let after = injectMarker(before, snippet);
|
|
9415
9501
|
if (widgetUuid !== null) {
|
|
9416
9502
|
const ensured = ensureWidgetInHtml(after, widgetUuid);
|
|
@@ -9425,8 +9511,21 @@ async function runMarkBuild(args) {
|
|
|
9425
9511
|
}
|
|
9426
9512
|
}
|
|
9427
9513
|
const stackSummary = stack !== null ? describeStack(stack) : null;
|
|
9514
|
+
if (published) {
|
|
9515
|
+
console.log(
|
|
9516
|
+
`mark-build: marked ${marked} HTML file(s) in ${dir}${checksum !== null ? ` (build ${checksum})` : ""}${widgetTouched > 0 ? `, widget tag ensured in ${widgetTouched}` : ""}${stackSummary !== null ? ` [${stackSummary}]` : ""}.`
|
|
9517
|
+
);
|
|
9518
|
+
return 0;
|
|
9519
|
+
}
|
|
9520
|
+
const because = environmentEvidence.length > 0 ? ` (${environmentEvidence.join("; ")})` : "";
|
|
9521
|
+
console.log(
|
|
9522
|
+
`mark-build: ${environment} build${because} \u2014 production marker withheld from ${files.length} HTML file(s) in ${dir}${widgetTouched > 0 ? `, widget tag ensured in ${widgetTouched}` : ""}${stackSummary !== null ? ` [${stackSummary}]` : ""}.`
|
|
9523
|
+
);
|
|
9524
|
+
console.log(
|
|
9525
|
+
"mark-build: the marker tells Patchstack a page is the live site, so only the build that deploys carries it. Your hosting platform's build stamps it automatically."
|
|
9526
|
+
);
|
|
9428
9527
|
console.log(
|
|
9429
|
-
|
|
9528
|
+
"mark-build: publishing this directory by hand? Re-run with --production (or set PATCHSTACK_ENVIRONMENT=production) so the deployed pages carry it."
|
|
9430
9529
|
);
|
|
9431
9530
|
return 0;
|
|
9432
9531
|
}
|