@patchstack/connect 0.5.4 → 0.5.5
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 +4 -4
- package/README.md +5 -5
- package/dist/cli.js +214 -125
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +50 -19
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +49 -18
- 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")) {
|
|
@@ -2559,8 +2608,8 @@ function ensureSourceMarker(cwd, shell, framework) {
|
|
|
2559
2608
|
if (shell === null) {
|
|
2560
2609
|
return { shell: null, source: "", action: "no-anchor" };
|
|
2561
2610
|
}
|
|
2562
|
-
const file =
|
|
2563
|
-
const before =
|
|
2611
|
+
const file = path9.resolve(cwd, shell);
|
|
2612
|
+
const before = readFileSync2(file, "utf8");
|
|
2564
2613
|
const result = ensureMarkerInJsxShell(before, framework);
|
|
2565
2614
|
if (result.source !== before) {
|
|
2566
2615
|
writeFileSync(file, result.source);
|
|
@@ -2569,15 +2618,15 @@ function ensureSourceMarker(cwd, shell, framework) {
|
|
|
2569
2618
|
}
|
|
2570
2619
|
|
|
2571
2620
|
// src/guide.ts
|
|
2572
|
-
import { existsSync as existsSync13, readFileSync as
|
|
2573
|
-
import
|
|
2621
|
+
import { existsSync as existsSync13, readFileSync as readFileSync10, readdirSync as readdirSync5, statSync as statSync4 } from "fs";
|
|
2622
|
+
import path12 from "path";
|
|
2574
2623
|
|
|
2575
2624
|
// src/architecture.ts
|
|
2576
|
-
import { existsSync as existsSync2, readFileSync as
|
|
2577
|
-
import
|
|
2625
|
+
import { existsSync as existsSync2, readFileSync as readFileSync5, statSync as statSync3 } from "fs";
|
|
2626
|
+
import path10 from "path";
|
|
2578
2627
|
|
|
2579
2628
|
// src/map/sources.ts
|
|
2580
|
-
import { readFileSync as
|
|
2629
|
+
import { readFileSync as readFileSync3, readdirSync as readdirSync2, realpathSync as realpathSync2, statSync as statSync2 } from "fs";
|
|
2581
2630
|
import { join as join2, relative, isAbsolute } from "path";
|
|
2582
2631
|
|
|
2583
2632
|
// src/map/ast.ts
|
|
@@ -2787,7 +2836,7 @@ function hasEntrySignal(text) {
|
|
|
2787
2836
|
}
|
|
2788
2837
|
function detectFramework(cwd) {
|
|
2789
2838
|
try {
|
|
2790
|
-
const pkg = JSON.parse(
|
|
2839
|
+
const pkg = JSON.parse(readFileSync3(join2(cwd, "package.json"), "utf8"));
|
|
2791
2840
|
const d = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
2792
2841
|
if (d["@tanstack/react-start"] || d["@tanstack/start"] || d["@tanstack/solid-start"]) return "tanstack-start";
|
|
2793
2842
|
if (d["next"]) return "next";
|
|
@@ -2947,10 +2996,10 @@ function detectDeploymentShapes(cwd, opts = {}) {
|
|
|
2947
2996
|
boundary = realpathSync2(boundary);
|
|
2948
2997
|
} catch {
|
|
2949
2998
|
}
|
|
2950
|
-
const inProject = (
|
|
2999
|
+
const inProject = (path17) => {
|
|
2951
3000
|
if (opts.followOutside) return true;
|
|
2952
3001
|
try {
|
|
2953
|
-
return isInside(realpathSync2(
|
|
3002
|
+
return isInside(realpathSync2(path17), boundary);
|
|
2954
3003
|
} catch {
|
|
2955
3004
|
return false;
|
|
2956
3005
|
}
|
|
@@ -3016,7 +3065,7 @@ function holdsSourceFile(dir) {
|
|
|
3016
3065
|
}
|
|
3017
3066
|
|
|
3018
3067
|
// src/map/surface.ts
|
|
3019
|
-
import { readFileSync as
|
|
3068
|
+
import { readFileSync as readFileSync4 } from "fs";
|
|
3020
3069
|
import { join as join3 } from "path";
|
|
3021
3070
|
var STATIC_GENERATORS = [
|
|
3022
3071
|
{ dep: "vite", label: "vite" },
|
|
@@ -3058,7 +3107,7 @@ var SHAPE_SIGNAL = {
|
|
|
3058
3107
|
};
|
|
3059
3108
|
function readManifest(cwd) {
|
|
3060
3109
|
try {
|
|
3061
|
-
const parsed = JSON.parse(
|
|
3110
|
+
const parsed = JSON.parse(readFileSync4(join3(cwd, "package.json"), "utf8"));
|
|
3062
3111
|
return typeof parsed === "object" && parsed !== null ? parsed : null;
|
|
3063
3112
|
} catch {
|
|
3064
3113
|
return null;
|
|
@@ -3071,7 +3120,7 @@ function nextExportsStatically(cwd, manifest, ts) {
|
|
|
3071
3120
|
for (const file of ["next.config.js", "next.config.mjs", "next.config.ts", "next.config.cjs"]) {
|
|
3072
3121
|
let text;
|
|
3073
3122
|
try {
|
|
3074
|
-
text =
|
|
3123
|
+
text = readFileSync4(join3(cwd, file), "utf8");
|
|
3075
3124
|
} catch {
|
|
3076
3125
|
continue;
|
|
3077
3126
|
}
|
|
@@ -3230,7 +3279,7 @@ var SERVING_CALL = /\b(?:createServer|createSecureServer|Bun\.serve|Deno\.serve|
|
|
|
3230
3279
|
var MAX_ENTRY_BYTES = 256 * 1024;
|
|
3231
3280
|
function readManifest2(cwd) {
|
|
3232
3281
|
try {
|
|
3233
|
-
const parsed = JSON.parse(
|
|
3282
|
+
const parsed = JSON.parse(readFileSync5(path10.join(cwd, "package.json"), "utf8"));
|
|
3234
3283
|
return typeof parsed === "object" && parsed !== null ? parsed : {};
|
|
3235
3284
|
} catch {
|
|
3236
3285
|
return {};
|
|
@@ -3259,16 +3308,16 @@ function staticGenerators(deps) {
|
|
|
3259
3308
|
}
|
|
3260
3309
|
function serverEntries(cwd, manifest) {
|
|
3261
3310
|
const candidates = new Set(SERVER_ENTRY_CANDIDATES);
|
|
3262
|
-
if (typeof manifest.main === "string" && manifest.main !== "" && !
|
|
3263
|
-
const main2 =
|
|
3311
|
+
if (typeof manifest.main === "string" && manifest.main !== "" && !path10.isAbsolute(manifest.main)) {
|
|
3312
|
+
const main2 = path10.normalize(manifest.main);
|
|
3264
3313
|
if (!main2.startsWith("..")) candidates.add(main2);
|
|
3265
3314
|
}
|
|
3266
3315
|
const found = [];
|
|
3267
3316
|
for (const relative7 of candidates) {
|
|
3268
|
-
const file =
|
|
3317
|
+
const file = path10.join(cwd, relative7);
|
|
3269
3318
|
try {
|
|
3270
3319
|
if (!existsSync2(file) || !statSync3(file).isFile()) continue;
|
|
3271
|
-
const text =
|
|
3320
|
+
const text = readFileSync5(file, "utf8").slice(0, MAX_ENTRY_BYTES);
|
|
3272
3321
|
if (SERVING_CALL.test(text)) found.push(relative7);
|
|
3273
3322
|
} catch {
|
|
3274
3323
|
}
|
|
@@ -3322,10 +3371,10 @@ function classifyArchitecture(cwd) {
|
|
|
3322
3371
|
}
|
|
3323
3372
|
|
|
3324
3373
|
// src/protect/install/util.ts
|
|
3325
|
-
import { readFileSync as
|
|
3374
|
+
import { readFileSync as readFileSync6, existsSync as existsSync3, writeFileSync as writeFileSync2 } from "fs";
|
|
3326
3375
|
import { join as join4, dirname } from "path";
|
|
3327
3376
|
import { fileURLToPath } from "url";
|
|
3328
|
-
var read = (p) =>
|
|
3377
|
+
var read = (p) => readFileSync6(p, "utf8");
|
|
3329
3378
|
var log = (msg) => console.log(`patchstack protect: ${msg}`);
|
|
3330
3379
|
function hasDependency(cwd, name) {
|
|
3331
3380
|
try {
|
|
@@ -3798,7 +3847,7 @@ var nuxtAdapter = {
|
|
|
3798
3847
|
};
|
|
3799
3848
|
|
|
3800
3849
|
// src/protect/install/find-app.ts
|
|
3801
|
-
import { readFileSync as
|
|
3850
|
+
import { readFileSync as readFileSync7, existsSync as existsSync7, readdirSync as readdirSync3, lstatSync } from "fs";
|
|
3802
3851
|
import { join as join10, relative as relative2, dirname as dirname3 } from "path";
|
|
3803
3852
|
var SKIP_DIRS2 = /* @__PURE__ */ new Set([
|
|
3804
3853
|
"node_modules",
|
|
@@ -3844,7 +3893,7 @@ function findAppInstance(cwd, re) {
|
|
|
3844
3893
|
else if (/\.(?:ts|js|mjs|cjs)$/.test(name)) {
|
|
3845
3894
|
let src;
|
|
3846
3895
|
try {
|
|
3847
|
-
src =
|
|
3896
|
+
src = readFileSync7(p, "utf8");
|
|
3848
3897
|
} catch {
|
|
3849
3898
|
continue;
|
|
3850
3899
|
}
|
|
@@ -3891,7 +3940,7 @@ function declaredEntries(cwd) {
|
|
|
3891
3940
|
const paths = /* @__PURE__ */ new Set();
|
|
3892
3941
|
let pkg;
|
|
3893
3942
|
try {
|
|
3894
|
-
pkg = JSON.parse(
|
|
3943
|
+
pkg = JSON.parse(readFileSync7(join10(cwd, "package.json"), "utf8"));
|
|
3895
3944
|
} catch {
|
|
3896
3945
|
return paths;
|
|
3897
3946
|
}
|
|
@@ -3921,7 +3970,7 @@ import { writeFileSync as writeFileSync5, existsSync as existsSync10 } from "fs"
|
|
|
3921
3970
|
import { join as join13, resolve as resolve2 } from "path";
|
|
3922
3971
|
|
|
3923
3972
|
// src/protect/install/generic.ts
|
|
3924
|
-
import { readFileSync as
|
|
3973
|
+
import { readFileSync as readFileSync8, existsSync as existsSync9, mkdirSync as mkdirSync4, copyFileSync as copyFileSync4, readdirSync as readdirSync4, lstatSync as lstatSync2 } from "fs";
|
|
3925
3974
|
import { join as join12, dirname as dirname5 } from "path";
|
|
3926
3975
|
|
|
3927
3976
|
// src/protect/install/source-scope.ts
|
|
@@ -4473,7 +4522,7 @@ function guardIsImported(cwd, guardPath) {
|
|
|
4473
4522
|
if (st.isDirectory()) walk2(p, depth + 1);
|
|
4474
4523
|
else if (/\.(?:ts|tsx|js|jsx|mjs|cjs)$/.test(name) && p !== guardPath) {
|
|
4475
4524
|
try {
|
|
4476
|
-
if (importsAndUsesGuard(
|
|
4525
|
+
if (importsAndUsesGuard(readFileSync8(p, "utf8"), p, guardDir, packageIsModule)) found = true;
|
|
4477
4526
|
} catch {
|
|
4478
4527
|
}
|
|
4479
4528
|
}
|
|
@@ -4957,8 +5006,8 @@ function runVerify(cwd) {
|
|
|
4957
5006
|
}
|
|
4958
5007
|
|
|
4959
5008
|
// src/widget.ts
|
|
4960
|
-
import { existsSync as existsSync12, readFileSync as
|
|
4961
|
-
import
|
|
5009
|
+
import { existsSync as existsSync12, readFileSync as readFileSync9, writeFileSync as writeFileSync6 } from "fs";
|
|
5010
|
+
import path11 from "path";
|
|
4962
5011
|
var WIDGET_SCRIPT_URL = "https://cdn.patchstack.com/patchstack-widget.js";
|
|
4963
5012
|
var WIDGET_MARKER_ATTR = "data-patchstack-connect-widget";
|
|
4964
5013
|
var WIDGET_NEEDLE = "patchstack-widget";
|
|
@@ -4996,7 +5045,7 @@ ${indent}</body>`;
|
|
|
4996
5045
|
}
|
|
4997
5046
|
function findSourceShell(cwd) {
|
|
4998
5047
|
for (const candidate of SOURCE_SHELL_CANDIDATES) {
|
|
4999
|
-
if (existsSync12(
|
|
5048
|
+
if (existsSync12(path11.join(cwd, candidate))) {
|
|
5000
5049
|
return candidate;
|
|
5001
5050
|
}
|
|
5002
5051
|
}
|
|
@@ -5007,8 +5056,8 @@ function ensureSourceWidget(cwd, siteUuid) {
|
|
|
5007
5056
|
if (shell === null) {
|
|
5008
5057
|
return { shell: null, action: "no-shell" };
|
|
5009
5058
|
}
|
|
5010
|
-
const file =
|
|
5011
|
-
const before =
|
|
5059
|
+
const file = path11.join(cwd, shell);
|
|
5060
|
+
const before = readFileSync9(file, "utf8");
|
|
5012
5061
|
const { html, action } = ensureWidgetInHtml(before, siteUuid);
|
|
5013
5062
|
if (html !== before) {
|
|
5014
5063
|
writeFileSync6(file, html);
|
|
@@ -5090,7 +5139,7 @@ function detectPackageManager(cwd) {
|
|
|
5090
5139
|
return declared;
|
|
5091
5140
|
}
|
|
5092
5141
|
for (const { filename, pm } of PM_BY_LOCKFILE) {
|
|
5093
|
-
if (existsSync13(
|
|
5142
|
+
if (existsSync13(path12.join(cwd, filename))) {
|
|
5094
5143
|
return pm;
|
|
5095
5144
|
}
|
|
5096
5145
|
}
|
|
@@ -5101,7 +5150,7 @@ function installCommand(pm) {
|
|
|
5101
5150
|
}
|
|
5102
5151
|
function readPackageJson(cwd) {
|
|
5103
5152
|
try {
|
|
5104
|
-
return JSON.parse(
|
|
5153
|
+
return JSON.parse(readFileSync10(path12.join(cwd, "package.json"), "utf8"));
|
|
5105
5154
|
} catch {
|
|
5106
5155
|
return null;
|
|
5107
5156
|
}
|
|
@@ -5109,7 +5158,7 @@ function readPackageJson(cwd) {
|
|
|
5109
5158
|
function installedVersion(cwd, declaredRange) {
|
|
5110
5159
|
try {
|
|
5111
5160
|
const pkg = JSON.parse(
|
|
5112
|
-
|
|
5161
|
+
readFileSync10(path12.join(cwd, "node_modules", "@patchstack", "connect", "package.json"), "utf8")
|
|
5113
5162
|
);
|
|
5114
5163
|
if (typeof pkg.version === "string" && pkg.version.length > 0) {
|
|
5115
5164
|
return pkg.version;
|
|
@@ -5137,7 +5186,7 @@ function findWidgetMarker(cwd, siteUuid) {
|
|
|
5137
5186
|
if (budget <= 0 || settled()) {
|
|
5138
5187
|
return;
|
|
5139
5188
|
}
|
|
5140
|
-
const full =
|
|
5189
|
+
const full = path12.join(dir, entry.name);
|
|
5141
5190
|
if (entry.isDirectory()) {
|
|
5142
5191
|
if (SKIPPED_DIRS.has(entry.name) || entry.name.startsWith(".")) {
|
|
5143
5192
|
continue;
|
|
@@ -5145,7 +5194,7 @@ function findWidgetMarker(cwd, siteUuid) {
|
|
|
5145
5194
|
walk2(full, depth + 1);
|
|
5146
5195
|
continue;
|
|
5147
5196
|
}
|
|
5148
|
-
if (!entry.isFile() || !WIDGET_EXTENSIONS.has(
|
|
5197
|
+
if (!entry.isFile() || !WIDGET_EXTENSIONS.has(path12.extname(entry.name).toLowerCase())) {
|
|
5149
5198
|
continue;
|
|
5150
5199
|
}
|
|
5151
5200
|
budget -= 1;
|
|
@@ -5153,7 +5202,7 @@ function findWidgetMarker(cwd, siteUuid) {
|
|
|
5153
5202
|
if (statSync4(full).size > WIDGET_SCAN_MAX_BYTES) {
|
|
5154
5203
|
continue;
|
|
5155
5204
|
}
|
|
5156
|
-
const content =
|
|
5205
|
+
const content = readFileSync10(full, "utf8");
|
|
5157
5206
|
if (!content.includes(WIDGET_NEEDLE2)) {
|
|
5158
5207
|
continue;
|
|
5159
5208
|
}
|
|
@@ -5176,7 +5225,7 @@ function findProductionMarker(cwd, widgetFileHint) {
|
|
|
5176
5225
|
return false;
|
|
5177
5226
|
}
|
|
5178
5227
|
try {
|
|
5179
|
-
return
|
|
5228
|
+
return readFileSync10(path12.join(cwd, widgetFileHint), "utf8").includes(PROD_MARKER_NEEDLE);
|
|
5180
5229
|
} catch {
|
|
5181
5230
|
return false;
|
|
5182
5231
|
}
|
|
@@ -5187,7 +5236,7 @@ function resolveWidgetFileHint(cwd, framework) {
|
|
|
5187
5236
|
...GENERIC_WIDGET_FILES
|
|
5188
5237
|
];
|
|
5189
5238
|
for (const candidate of candidates) {
|
|
5190
|
-
if (existsSync13(
|
|
5239
|
+
if (existsSync13(path12.join(cwd, candidate))) {
|
|
5191
5240
|
return candidate;
|
|
5192
5241
|
}
|
|
5193
5242
|
}
|
|
@@ -5295,7 +5344,7 @@ function renderGuideChecklist(state, useColor) {
|
|
|
5295
5344
|
const headerParts = [state.framework, state.packageManager].filter(
|
|
5296
5345
|
(part) => part !== null
|
|
5297
5346
|
);
|
|
5298
|
-
const name = state.projectName ??
|
|
5347
|
+
const name = state.projectName ?? path12.basename(process.cwd());
|
|
5299
5348
|
lines.push(paint(ANSI.bold, `Patchstack setup status \u2014 ${name} (${headerParts.join(" \xB7 ")})`));
|
|
5300
5349
|
if (state.endpointOverride !== null) {
|
|
5301
5350
|
lines.push(
|
|
@@ -5476,12 +5525,12 @@ function renderGuideChecklist(state, useColor) {
|
|
|
5476
5525
|
// src/login.ts
|
|
5477
5526
|
import { mkdtempSync } from "fs";
|
|
5478
5527
|
import { tmpdir as tmpdir2 } from "os";
|
|
5479
|
-
import
|
|
5528
|
+
import path14 from "path";
|
|
5480
5529
|
|
|
5481
5530
|
// src/device-flow.ts
|
|
5482
|
-
import { readFileSync as
|
|
5531
|
+
import { readFileSync as readFileSync11, rmSync, writeFileSync as writeFileSync7 } from "fs";
|
|
5483
5532
|
import { tmpdir } from "os";
|
|
5484
|
-
import
|
|
5533
|
+
import path13 from "path";
|
|
5485
5534
|
import { createHash as createHash2 } from "crypto";
|
|
5486
5535
|
function baseFrom(manifestEndpoint) {
|
|
5487
5536
|
const url = new URL(manifestEndpoint);
|
|
@@ -5493,7 +5542,7 @@ function baseFrom(manifestEndpoint) {
|
|
|
5493
5542
|
}
|
|
5494
5543
|
function pendingPath(siteUuid, intent) {
|
|
5495
5544
|
const key = createHash2("sha256").update(siteUuid).digest("hex").slice(0, 16);
|
|
5496
|
-
return
|
|
5545
|
+
return path13.join(tmpdir(), `patchstack-${intent}-${key}.json`);
|
|
5497
5546
|
}
|
|
5498
5547
|
function savePending(siteUuid, intent, pending) {
|
|
5499
5548
|
writeFileSync7(pendingPath(siteUuid, intent), JSON.stringify(pending), {
|
|
@@ -5503,7 +5552,7 @@ function savePending(siteUuid, intent, pending) {
|
|
|
5503
5552
|
}
|
|
5504
5553
|
function readPending(siteUuid, intent) {
|
|
5505
5554
|
try {
|
|
5506
|
-
return JSON.parse(
|
|
5555
|
+
return JSON.parse(readFileSync11(pendingPath(siteUuid, intent), "utf8"));
|
|
5507
5556
|
} catch {
|
|
5508
5557
|
return null;
|
|
5509
5558
|
}
|
|
@@ -5673,7 +5722,7 @@ async function claim2(config, onPrompt, deps = {}) {
|
|
|
5673
5722
|
import { relative as relative3 } from "path";
|
|
5674
5723
|
|
|
5675
5724
|
// src/protect/install/runtime/entry.ts
|
|
5676
|
-
import { existsSync as existsSync14, readFileSync as
|
|
5725
|
+
import { existsSync as existsSync14, readFileSync as readFileSync12, realpathSync as realpathSync3, statSync as statSync5 } from "fs";
|
|
5677
5726
|
import { join as join15, resolve as resolve3, sep } from "path";
|
|
5678
5727
|
var CONVENTIONAL = [
|
|
5679
5728
|
"server.js",
|
|
@@ -5700,15 +5749,15 @@ var CONVENTIONAL = [
|
|
|
5700
5749
|
var LOADABLE = /\.(?:js|mjs|cjs)$/;
|
|
5701
5750
|
function readPackage2(cwd) {
|
|
5702
5751
|
try {
|
|
5703
|
-
const parsed = JSON.parse(
|
|
5752
|
+
const parsed = JSON.parse(readFileSync12(join15(cwd, "package.json"), "utf8"));
|
|
5704
5753
|
return parsed !== null && typeof parsed === "object" ? parsed : null;
|
|
5705
5754
|
} catch {
|
|
5706
5755
|
return null;
|
|
5707
5756
|
}
|
|
5708
5757
|
}
|
|
5709
|
-
function isFile(
|
|
5758
|
+
function isFile(path17) {
|
|
5710
5759
|
try {
|
|
5711
|
-
return statSync5(
|
|
5760
|
+
return statSync5(path17).isFile();
|
|
5712
5761
|
} catch {
|
|
5713
5762
|
return false;
|
|
5714
5763
|
}
|
|
@@ -5717,14 +5766,14 @@ function loadable(cwd, candidate) {
|
|
|
5717
5766
|
const written = resolve3(cwd, candidate);
|
|
5718
5767
|
if (!LOADABLE.test(written) || !isFile(written)) return null;
|
|
5719
5768
|
let root;
|
|
5720
|
-
let
|
|
5769
|
+
let path17;
|
|
5721
5770
|
try {
|
|
5722
5771
|
root = realpathSync3(cwd);
|
|
5723
|
-
|
|
5772
|
+
path17 = realpathSync3(written);
|
|
5724
5773
|
} catch {
|
|
5725
5774
|
return null;
|
|
5726
5775
|
}
|
|
5727
|
-
if (
|
|
5776
|
+
if (path17 !== root && !path17.startsWith(root + sep)) return null;
|
|
5728
5777
|
return written;
|
|
5729
5778
|
}
|
|
5730
5779
|
function passable(token) {
|
|
@@ -5804,8 +5853,8 @@ function preloadPath() {
|
|
|
5804
5853
|
// beside this file, in the repository
|
|
5805
5854
|
];
|
|
5806
5855
|
for (const candidate of candidates) {
|
|
5807
|
-
const
|
|
5808
|
-
if (existsSync15(
|
|
5856
|
+
const path17 = fileURLToPath2(candidate);
|
|
5857
|
+
if (existsSync15(path17)) return path17;
|
|
5809
5858
|
}
|
|
5810
5859
|
return null;
|
|
5811
5860
|
}
|
|
@@ -6175,7 +6224,7 @@ async function loadTypeScript(cwd) {
|
|
|
6175
6224
|
}
|
|
6176
6225
|
|
|
6177
6226
|
// src/map/extract.ts
|
|
6178
|
-
import { readFileSync as
|
|
6227
|
+
import { readFileSync as readFileSync15, realpathSync as realpathSync5 } from "fs";
|
|
6179
6228
|
import { createHash as createHash5 } from "crypto";
|
|
6180
6229
|
import { relative as relative5 } from "path";
|
|
6181
6230
|
|
|
@@ -6589,7 +6638,7 @@ function dedupeSinks(sinks, owner) {
|
|
|
6589
6638
|
}
|
|
6590
6639
|
|
|
6591
6640
|
// src/map/module-graph.ts
|
|
6592
|
-
import { readFileSync as
|
|
6641
|
+
import { readFileSync as readFileSync13, realpathSync as realpathSync4, statSync as statSync6 } from "fs";
|
|
6593
6642
|
import { dirname as dirname7, join as join17, relative as relative4, resolve as resolvePath } from "path";
|
|
6594
6643
|
var RESOLVE_EXTS = [".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs"];
|
|
6595
6644
|
function createModuleGraph(ts, opts) {
|
|
@@ -6598,7 +6647,7 @@ function createModuleGraph(ts, opts) {
|
|
|
6598
6647
|
if (cache.has(file)) return cache.get(file) ?? null;
|
|
6599
6648
|
let entry = null;
|
|
6600
6649
|
try {
|
|
6601
|
-
const text =
|
|
6650
|
+
const text = readFileSync13(file, "utf8");
|
|
6602
6651
|
const sf = ts.createSourceFile(file, text, ts.ScriptTarget.Latest, true, guessScriptKind(ts, file));
|
|
6603
6652
|
const bindings = buildModuleBindings(sf, ts);
|
|
6604
6653
|
entry = { fnSinks: collectLocalSinks(sf, ts, bindings), calleesOf: collectCallees(sf, ts), bindings };
|
|
@@ -6697,8 +6746,8 @@ function collectCallees(sf, ts) {
|
|
|
6697
6746
|
}
|
|
6698
6747
|
|
|
6699
6748
|
// src/map/coordinates.ts
|
|
6700
|
-
function runtimeCoordinate(source,
|
|
6701
|
-
if (/\[\d*\]/.test(
|
|
6749
|
+
function runtimeCoordinate(source, path17) {
|
|
6750
|
+
if (/\[\d*\]/.test(path17)) {
|
|
6702
6751
|
return { runtimeParameter: null, runtimeParameterReason: "array traversal: needs an array_key_value rule, not a dotted parameter" };
|
|
6703
6752
|
}
|
|
6704
6753
|
switch (source) {
|
|
@@ -6707,15 +6756,15 @@ function runtimeCoordinate(source, path16) {
|
|
|
6707
6756
|
case "multipart":
|
|
6708
6757
|
case "body":
|
|
6709
6758
|
case "server-fn-data":
|
|
6710
|
-
return { runtimeParameter: `post.${
|
|
6759
|
+
return { runtimeParameter: `post.${path17}` };
|
|
6711
6760
|
case "query":
|
|
6712
|
-
return { runtimeParameter: `get.${
|
|
6761
|
+
return { runtimeParameter: `get.${path17}` };
|
|
6713
6762
|
case "cookie":
|
|
6714
|
-
return { runtimeParameter: `cookie.${
|
|
6763
|
+
return { runtimeParameter: `cookie.${path17}` };
|
|
6715
6764
|
case "file":
|
|
6716
|
-
return { runtimeParameter: `files.${
|
|
6765
|
+
return { runtimeParameter: `files.${path17}` };
|
|
6717
6766
|
case "header":
|
|
6718
|
-
return { runtimeParameter: `server.HTTP_${
|
|
6767
|
+
return { runtimeParameter: `server.HTTP_${path17.toUpperCase().replace(/-/g, "_")}` };
|
|
6719
6768
|
case "route-param":
|
|
6720
6769
|
return { runtimeParameter: null, runtimeParameterReason: "route parameters are not exposed by the runtime resolver" };
|
|
6721
6770
|
default:
|
|
@@ -6747,8 +6796,8 @@ function addressSpaceOf(source) {
|
|
|
6747
6796
|
function isProvenFlow(confidence) {
|
|
6748
6797
|
return confidence === "exact-local" || confidence === "transformed-local";
|
|
6749
6798
|
}
|
|
6750
|
-
function inputIdOf(source,
|
|
6751
|
-
return `${addressSpaceOf(source)}:${
|
|
6799
|
+
function inputIdOf(source, path17) {
|
|
6800
|
+
return `${addressSpaceOf(source)}:${path17}`;
|
|
6752
6801
|
}
|
|
6753
6802
|
function withCoordinates(fields, source) {
|
|
6754
6803
|
return fields.map((f) => {
|
|
@@ -6958,8 +7007,8 @@ function linkFlows(bodyNode, params, inputs, sinks, ts) {
|
|
|
6958
7007
|
if (!bodyNode || sinks.length === 0 || inputs.length === 0) return { flows: [], limitations: [] };
|
|
6959
7008
|
const CONTAINER_KEYS = /* @__PURE__ */ new Set([...REQ_SOURCES, "data", "input", "payload"]);
|
|
6960
7009
|
const rootPath = /* @__PURE__ */ new Map();
|
|
6961
|
-
const addRoot = (name,
|
|
6962
|
-
if (!rootPath.has(name)) rootPath.set(name, { path:
|
|
7010
|
+
const addRoot = (name, path17, space) => {
|
|
7011
|
+
if (!rootPath.has(name)) rootPath.set(name, { path: path17, space });
|
|
6963
7012
|
};
|
|
6964
7013
|
for (const p of params ?? []) {
|
|
6965
7014
|
if (!p?.name) continue;
|
|
@@ -7104,8 +7153,8 @@ function dedupeLimitations(list) {
|
|
|
7104
7153
|
function join22(base, seg) {
|
|
7105
7154
|
return base ? `${base}.${seg}` : seg;
|
|
7106
7155
|
}
|
|
7107
|
-
function normalizePath(
|
|
7108
|
-
return
|
|
7156
|
+
function normalizePath(path17) {
|
|
7157
|
+
return path17.replace(/\[\d*\]/g, "").split(".").filter(Boolean).join(".");
|
|
7109
7158
|
}
|
|
7110
7159
|
function fluentChainCalls(call, ts) {
|
|
7111
7160
|
let root = call;
|
|
@@ -7351,7 +7400,7 @@ function handlerEntry(name, kindLabel, params, body, ts, localSinks, bindings, c
|
|
|
7351
7400
|
}
|
|
7352
7401
|
|
|
7353
7402
|
// src/map/imports.ts
|
|
7354
|
-
import { readFileSync as
|
|
7403
|
+
import { readFileSync as readFileSync14 } from "fs";
|
|
7355
7404
|
import { join as join18 } from "path";
|
|
7356
7405
|
var MAX_SITES = 5;
|
|
7357
7406
|
var NPM_NAME = /^(?:@[^/@\s~][^/@\s]*\/)?[^/@\s.~][^/@\s]*$/;
|
|
@@ -7363,7 +7412,7 @@ function readPathAliases(cwd) {
|
|
|
7363
7412
|
for (const name of ["tsconfig.json", "jsconfig.json"]) {
|
|
7364
7413
|
let paths;
|
|
7365
7414
|
try {
|
|
7366
|
-
const raw =
|
|
7415
|
+
const raw = readFileSync14(join18(cwd, name), "utf8");
|
|
7367
7416
|
const parsed = JSON.parse(stripJsonComments(raw));
|
|
7368
7417
|
paths = parsed.compilerOptions?.paths;
|
|
7369
7418
|
} catch {
|
|
@@ -7742,7 +7791,7 @@ async function extractInputMap(cwd, ts, options = {}) {
|
|
|
7742
7791
|
const hopTargets = /* @__PURE__ */ new Set();
|
|
7743
7792
|
for (const file of files) {
|
|
7744
7793
|
try {
|
|
7745
|
-
const text =
|
|
7794
|
+
const text = readFileSync15(file, "utf8");
|
|
7746
7795
|
const relFile = relative5(cwd, file);
|
|
7747
7796
|
sourceBytes += text.length;
|
|
7748
7797
|
if (!hasEntrySignal(text)) {
|
|
@@ -7797,7 +7846,7 @@ async function extractInputMap(cwd, ts, options = {}) {
|
|
|
7797
7846
|
for (const target of hopTargets) {
|
|
7798
7847
|
if (entryFiles.has(target)) continue;
|
|
7799
7848
|
try {
|
|
7800
|
-
const text =
|
|
7849
|
+
const text = readFileSync15(target, "utf8");
|
|
7801
7850
|
const sf = ts.createSourceFile(target, text, ts.ScriptTarget.Latest, true, guessScriptKind(ts, target));
|
|
7802
7851
|
const bindings = buildModuleBindings(sf, ts);
|
|
7803
7852
|
const called = collectInvocations(sf, ts, bindings, { file: target, owner: relative5(cwd, target), graph });
|
|
@@ -7946,7 +7995,7 @@ function getStringFlag(flags, name) {
|
|
|
7946
7995
|
}
|
|
7947
7996
|
|
|
7948
7997
|
// src/build-stamp.ts
|
|
7949
|
-
import { chmodSync, lstatSync as lstatSync3, readFileSync as
|
|
7998
|
+
import { chmodSync, lstatSync as lstatSync3, readFileSync as readFileSync16, readdirSync as readdirSync6, realpathSync as realpathSync6, renameSync, unlinkSync, writeFileSync as writeFileSync8 } from "fs";
|
|
7950
7999
|
import { join as join19, relative as relative6, sep as sep2 } from "path";
|
|
7951
8000
|
var RULES_FILE_NAMES = /* @__PURE__ */ new Set(["rules.json", "patchstack.rules.json"]);
|
|
7952
8001
|
var SKIP_DIRECTORIES = /* @__PURE__ */ new Set(["node_modules", "dist", "build", "out", "coverage", "tmp", "vendor"]);
|
|
@@ -7965,11 +8014,11 @@ function guardImportsRulesFile(dir, rulesName) {
|
|
|
7965
8014
|
}
|
|
7966
8015
|
for (const name of siblings) {
|
|
7967
8016
|
if (!GUARD_SOURCE.test(name)) continue;
|
|
7968
|
-
const
|
|
8017
|
+
const path17 = join19(dir, name);
|
|
7969
8018
|
try {
|
|
7970
|
-
const entry = lstatSync3(
|
|
8019
|
+
const entry = lstatSync3(path17);
|
|
7971
8020
|
if (!entry.isFile() || entry.isSymbolicLink() || entry.size > MAX_GUARD_SOURCE_BYTES) continue;
|
|
7972
|
-
const source = stripComments(
|
|
8021
|
+
const source = stripComments(readFileSync16(path17, "utf8"));
|
|
7973
8022
|
if (source.includes("@patchstack/connect/protect") && importsRules.test(source)) return true;
|
|
7974
8023
|
} catch {
|
|
7975
8024
|
}
|
|
@@ -7990,9 +8039,9 @@ function findRulesFile(cwd) {
|
|
|
7990
8039
|
} catch {
|
|
7991
8040
|
return { kind: "none" };
|
|
7992
8041
|
}
|
|
7993
|
-
const contained = (
|
|
8042
|
+
const contained = (path17) => {
|
|
7994
8043
|
try {
|
|
7995
|
-
const real = realpathSync6(
|
|
8044
|
+
const real = realpathSync6(path17);
|
|
7996
8045
|
return real === root || real.startsWith(root + sep2);
|
|
7997
8046
|
} catch {
|
|
7998
8047
|
return false;
|
|
@@ -8008,25 +8057,25 @@ function findRulesFile(cwd) {
|
|
|
8008
8057
|
}
|
|
8009
8058
|
for (const name of entries) {
|
|
8010
8059
|
if (name.startsWith(".")) continue;
|
|
8011
|
-
const
|
|
8060
|
+
const path17 = join19(dir, name);
|
|
8012
8061
|
let entry;
|
|
8013
8062
|
try {
|
|
8014
|
-
entry = lstatSync3(
|
|
8063
|
+
entry = lstatSync3(path17);
|
|
8015
8064
|
} catch {
|
|
8016
8065
|
continue;
|
|
8017
8066
|
}
|
|
8018
8067
|
if (entry.isSymbolicLink()) continue;
|
|
8019
8068
|
if (entry.isDirectory()) {
|
|
8020
|
-
if (!SKIP_DIRECTORIES.has(name)) walk2(
|
|
8069
|
+
if (!SKIP_DIRECTORIES.has(name)) walk2(path17, depth + 1);
|
|
8021
8070
|
continue;
|
|
8022
8071
|
}
|
|
8023
8072
|
if (!entry.isFile() || !RULES_FILE_NAMES.has(name)) continue;
|
|
8024
|
-
if (!contained(
|
|
8073
|
+
if (!contained(path17)) continue;
|
|
8025
8074
|
if (!guardImportsRulesFile(dir, name)) continue;
|
|
8026
8075
|
try {
|
|
8027
|
-
if (isRuleBundle(JSON.parse(
|
|
8076
|
+
if (isRuleBundle(JSON.parse(readFileSync16(path17, "utf8")))) found.push(path17);
|
|
8028
8077
|
} catch {
|
|
8029
|
-
unreadable.push(
|
|
8078
|
+
unreadable.push(path17);
|
|
8030
8079
|
}
|
|
8031
8080
|
}
|
|
8032
8081
|
};
|
|
@@ -8057,7 +8106,7 @@ function applyBuildStamp(cwd, id) {
|
|
|
8057
8106
|
const file = relative6(cwd, location.path);
|
|
8058
8107
|
let text;
|
|
8059
8108
|
try {
|
|
8060
|
-
text =
|
|
8109
|
+
text = readFileSync16(location.path, "utf8");
|
|
8061
8110
|
} catch (err) {
|
|
8062
8111
|
return { kind: "skipped", reason: `${file} could not be read (${err.message})` };
|
|
8063
8112
|
}
|
|
@@ -8275,8 +8324,8 @@ async function runMap(flags) {
|
|
|
8275
8324
|
}
|
|
8276
8325
|
|
|
8277
8326
|
// src/setup.ts
|
|
8278
|
-
import { readFileSync as
|
|
8279
|
-
import
|
|
8327
|
+
import { readFileSync as readFileSync17, writeFileSync as writeFileSync10 } from "fs";
|
|
8328
|
+
import path15 from "path";
|
|
8280
8329
|
var SCAN_COMMAND = "patchstack-connect scan";
|
|
8281
8330
|
var MARK_BUILD_COMMAND = "patchstack-connect mark-build";
|
|
8282
8331
|
function setupProtection(cwd) {
|
|
@@ -8301,8 +8350,8 @@ function prependHook(existing, command) {
|
|
|
8301
8350
|
return [command, ...remaining].join(" && ");
|
|
8302
8351
|
}
|
|
8303
8352
|
function wireBuildScripts(cwd, packageManager) {
|
|
8304
|
-
const target =
|
|
8305
|
-
const raw =
|
|
8353
|
+
const target = path15.join(cwd, "package.json");
|
|
8354
|
+
const raw = readFileSync17(target, "utf8");
|
|
8306
8355
|
const pkg = JSON.parse(raw);
|
|
8307
8356
|
const scripts = pkg.scripts ?? {};
|
|
8308
8357
|
const build = scripts.build;
|
|
@@ -8411,6 +8460,10 @@ Usage:
|
|
|
8411
8460
|
patchstack-connect mark-build [options] Stamp built HTML with a production flag +
|
|
8412
8461
|
build fingerprint, and ensure the widget
|
|
8413
8462
|
tag in built pages (run as a postbuild step).
|
|
8463
|
+
The flag marks a page as the LIVE site, so it
|
|
8464
|
+
is stamped only on a production build; a local
|
|
8465
|
+
or preview build gets the widget tag and no
|
|
8466
|
+
marker (and any stale marker is removed).
|
|
8414
8467
|
Looks in the framework's own output dir, an
|
|
8415
8468
|
--output the build script names, then dist/,
|
|
8416
8469
|
build/, out/, .output/public/, _site/ \u2014 inside
|
|
@@ -8496,8 +8549,15 @@ Options (for scan, setup, status, and uninstall):
|
|
|
8496
8549
|
too. Never written to a file, never printed back
|
|
8497
8550
|
|
|
8498
8551
|
Options (for mark-build):
|
|
8499
|
-
--dir <path> Build output directory (default: auto-detect
|
|
8500
|
-
|
|
8552
|
+
--dir <path> Build output directory (default: auto-detect the
|
|
8553
|
+
framework's own output dir, an --output the build
|
|
8554
|
+
script names, then dist/ build/ out/ .output/public/
|
|
8555
|
+
_site/ \u2014 inside the project only)
|
|
8556
|
+
--production Stamp the live-site marker on a build this command
|
|
8557
|
+
cannot tell is a deployment \u2014 publishing a static
|
|
8558
|
+
build by hand from a laptop, say. PATCHSTACK_ENVIRONMENT=production
|
|
8559
|
+
does the same. Never needed on a hosting platform,
|
|
8560
|
+
whose own build is recognised
|
|
8501
8561
|
|
|
8502
8562
|
Options (for demo and demo-guide):
|
|
8503
8563
|
--url <url> Test endpoint printed at the end
|
|
@@ -9171,7 +9231,7 @@ async function runGuide(args) {
|
|
|
9171
9231
|
console.log("\u2014\u2014\u2014\u2014 Full reference guide (ships as AGENT-INSTALL.md) \u2014\u2014\u2014\u2014");
|
|
9172
9232
|
console.log("");
|
|
9173
9233
|
const guidePath = new URL("../AGENT-INSTALL.md", import.meta.url);
|
|
9174
|
-
console.log(
|
|
9234
|
+
console.log(readFileSync18(guidePath, "utf8"));
|
|
9175
9235
|
return 0;
|
|
9176
9236
|
}
|
|
9177
9237
|
async function runSetup(args) {
|
|
@@ -9346,7 +9406,7 @@ function describeStack(stack) {
|
|
|
9346
9406
|
}
|
|
9347
9407
|
function readBuildScript(cwd) {
|
|
9348
9408
|
try {
|
|
9349
|
-
const pkg = JSON.parse(
|
|
9409
|
+
const pkg = JSON.parse(readFileSync18(path16.join(cwd, "package.json"), "utf8"));
|
|
9350
9410
|
return pkg.scripts?.build;
|
|
9351
9411
|
} catch {
|
|
9352
9412
|
return void 0;
|
|
@@ -9354,6 +9414,7 @@ function readBuildScript(cwd) {
|
|
|
9354
9414
|
}
|
|
9355
9415
|
async function runMarkBuild(args) {
|
|
9356
9416
|
const cwd = process.cwd();
|
|
9417
|
+
const startedAt = Date.now();
|
|
9357
9418
|
let checksum = null;
|
|
9358
9419
|
let stack = null;
|
|
9359
9420
|
try {
|
|
@@ -9370,6 +9431,8 @@ async function runMarkBuild(args) {
|
|
|
9370
9431
|
);
|
|
9371
9432
|
}
|
|
9372
9433
|
let widgetUuid = null;
|
|
9434
|
+
let environment = "local";
|
|
9435
|
+
let environmentEvidence = [];
|
|
9373
9436
|
try {
|
|
9374
9437
|
const config = await resolveConfig({
|
|
9375
9438
|
cwd,
|
|
@@ -9378,11 +9441,15 @@ async function runMarkBuild(args) {
|
|
|
9378
9441
|
if (config.widget) {
|
|
9379
9442
|
widgetUuid = config.siteUuid;
|
|
9380
9443
|
}
|
|
9444
|
+
environment = config.environment;
|
|
9445
|
+
environmentEvidence = config.environmentEvidence ?? [];
|
|
9381
9446
|
} catch (err) {
|
|
9382
9447
|
console.warn(
|
|
9383
9448
|
`mark-build: could not resolve the site UUID (${err.message}). Skipping the widget pass.`
|
|
9384
9449
|
);
|
|
9385
9450
|
}
|
|
9451
|
+
const forcedProduction = args.flags.get("production") === true;
|
|
9452
|
+
const published = forcedProduction || marksPublishedBuild(environment);
|
|
9386
9453
|
const buildDirOptions = { framework: stack?.framework ?? null, buildScript: readBuildScript(cwd) };
|
|
9387
9454
|
const dir = resolveBuildDir(cwd, getStringFlag(args.flags, "dir"), buildDirOptions);
|
|
9388
9455
|
if (dir === null) {
|
|
@@ -9406,11 +9473,20 @@ async function runMarkBuild(args) {
|
|
|
9406
9473
|
);
|
|
9407
9474
|
return 0;
|
|
9408
9475
|
}
|
|
9409
|
-
const
|
|
9476
|
+
const staleBy = staleBuildAge(files, startedAt);
|
|
9477
|
+
if (staleBy !== null) {
|
|
9478
|
+
console.warn(
|
|
9479
|
+
`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.`
|
|
9480
|
+
);
|
|
9481
|
+
console.warn(
|
|
9482
|
+
"mark-build: run it as a postbuild hook (or straight after the build) so what is stamped is what was just produced."
|
|
9483
|
+
);
|
|
9484
|
+
}
|
|
9485
|
+
const snippet = published ? buildInjectionSnippet(checksum, stack) : "";
|
|
9410
9486
|
let marked = 0;
|
|
9411
9487
|
let widgetTouched = 0;
|
|
9412
9488
|
for (const file of files) {
|
|
9413
|
-
const before =
|
|
9489
|
+
const before = readFileSync18(file, "utf8");
|
|
9414
9490
|
let after = injectMarker(before, snippet);
|
|
9415
9491
|
if (widgetUuid !== null) {
|
|
9416
9492
|
const ensured = ensureWidgetInHtml(after, widgetUuid);
|
|
@@ -9425,8 +9501,21 @@ async function runMarkBuild(args) {
|
|
|
9425
9501
|
}
|
|
9426
9502
|
}
|
|
9427
9503
|
const stackSummary = stack !== null ? describeStack(stack) : null;
|
|
9504
|
+
if (published) {
|
|
9505
|
+
console.log(
|
|
9506
|
+
`mark-build: marked ${marked} HTML file(s) in ${dir}${checksum !== null ? ` (build ${checksum})` : ""}${widgetTouched > 0 ? `, widget tag ensured in ${widgetTouched}` : ""}${stackSummary !== null ? ` [${stackSummary}]` : ""}.`
|
|
9507
|
+
);
|
|
9508
|
+
return 0;
|
|
9509
|
+
}
|
|
9510
|
+
const because = environmentEvidence.length > 0 ? ` (${environmentEvidence.join("; ")})` : "";
|
|
9511
|
+
console.log(
|
|
9512
|
+
`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}]` : ""}.`
|
|
9513
|
+
);
|
|
9514
|
+
console.log(
|
|
9515
|
+
"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."
|
|
9516
|
+
);
|
|
9428
9517
|
console.log(
|
|
9429
|
-
|
|
9518
|
+
"mark-build: publishing this directory by hand? Re-run with --production (or set PATCHSTACK_ENVIRONMENT=production) so the deployed pages carry it."
|
|
9430
9519
|
);
|
|
9431
9520
|
return 0;
|
|
9432
9521
|
}
|