@patchstack/connect 0.5.3 → 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 +3802 -3306
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +150 -28
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +68 -55
- package/dist/index.d.ts +68 -55
- package/dist/index.js +149 -27
- package/dist/index.js.map +1 -1
- package/dist/protect.cjs +200 -67
- package/dist/protect.cjs.map +1 -1
- package/dist/protect.js +1 -1
- package/dist/{refresh-manifest-3QGLYXV5.js → refresh-manifest-2ALIJGZ3.js} +152 -33
- package/dist/refresh-manifest-2ALIJGZ3.js.map +1 -0
- package/package.json +1 -1
- package/dist/refresh-manifest-3QGLYXV5.js.map +0 -1
package/dist/protect.cjs
CHANGED
|
@@ -38,8 +38,8 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
38
38
|
// src/pulse-token.ts
|
|
39
39
|
function buildTokenUrl(manifestEndpoint) {
|
|
40
40
|
const url = new URL(manifestEndpoint);
|
|
41
|
-
const
|
|
42
|
-
url.pathname =
|
|
41
|
+
const path9 = url.pathname.replace(/\/$/, "");
|
|
42
|
+
url.pathname = path9.endsWith("/manifest") ? `${path9.slice(0, -"/manifest".length)}/token` : "/monitor/pulse/token";
|
|
43
43
|
url.search = "";
|
|
44
44
|
url.hash = "";
|
|
45
45
|
return url.toString();
|
|
@@ -158,6 +158,46 @@ var init_types = __esm({
|
|
|
158
158
|
}
|
|
159
159
|
code;
|
|
160
160
|
cause;
|
|
161
|
+
/**
|
|
162
|
+
* For a `VALIDATION_ERROR`, the request fields the server refused, as it named them. Read from the
|
|
163
|
+
* structured `errors` object a validation response carries, so a caller deciding what to do about a
|
|
164
|
+
* refusal keys on the field rather than on the wording of a sentence.
|
|
165
|
+
*/
|
|
166
|
+
fields = [];
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
// src/hosting.ts
|
|
172
|
+
function detectHostingPlatform(env = process.env) {
|
|
173
|
+
for (const rule of RULES) {
|
|
174
|
+
const evidence = rule.any.filter((name) => present(env, name));
|
|
175
|
+
if (evidence.length > 0) {
|
|
176
|
+
return { platform: rule.platform, evidence };
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
return { platform: null, evidence: [] };
|
|
180
|
+
}
|
|
181
|
+
var RULES, present;
|
|
182
|
+
var init_hosting = __esm({
|
|
183
|
+
"src/hosting.ts"() {
|
|
184
|
+
"use strict";
|
|
185
|
+
RULES = [
|
|
186
|
+
{ platform: "netlify", any: ["NETLIFY", "NETLIFY_BUILD_BASE", "DEPLOY_PRIME_URL"] },
|
|
187
|
+
{ platform: "vercel", any: ["VERCEL", "VERCEL_ENV", "VERCEL_URL"] },
|
|
188
|
+
{ platform: "cloudflare", any: ["CF_PAGES", "CF_PAGES_URL", "CLOUDFLARE_ACCOUNT_ID"] },
|
|
189
|
+
{ platform: "aws", any: ["AWS_APP_ID", "AWS_LAMBDA_FUNCTION_NAME", "AWS_EXECUTION_ENV"] },
|
|
190
|
+
{ platform: "render", any: ["RENDER", "RENDER_SERVICE_ID", "RENDER_EXTERNAL_URL"] },
|
|
191
|
+
{ platform: "railway", any: ["RAILWAY_ENVIRONMENT", "RAILWAY_ENVIRONMENT_NAME", "RAILWAY_PROJECT_ID"] },
|
|
192
|
+
{ platform: "fly", any: ["FLY_APP_NAME", "FLY_REGION", "FLY_ALLOC_ID"] },
|
|
193
|
+
{ platform: "heroku", any: ["DYNO", "HEROKU_APP_NAME"] },
|
|
194
|
+
{ platform: "google-cloud", any: ["K_SERVICE", "GAE_APPLICATION", "GAE_SERVICE"] },
|
|
195
|
+
{ platform: "deno-deploy", any: ["DENO_DEPLOYMENT_ID"] },
|
|
196
|
+
{ platform: "azure", any: ["WEBSITE_SITE_NAME", "WEBSITE_INSTANCE_ID"] }
|
|
197
|
+
];
|
|
198
|
+
present = (env, name) => {
|
|
199
|
+
const value = env[name];
|
|
200
|
+
return value !== void 0 && value !== "";
|
|
161
201
|
};
|
|
162
202
|
}
|
|
163
203
|
});
|
|
@@ -183,14 +223,22 @@ function authFailureMessage(status, config) {
|
|
|
183
223
|
}
|
|
184
224
|
return null;
|
|
185
225
|
}
|
|
186
|
-
function buildManifestBody(config, payload) {
|
|
226
|
+
function buildManifestBody(config, payload, env = process.env) {
|
|
227
|
+
const hosting = config.environment === "local" ? null : detectHostingPlatform(env);
|
|
187
228
|
return {
|
|
188
229
|
...payload,
|
|
189
230
|
environment: config.environment,
|
|
190
231
|
...typeof config.siteUrl === "string" && config.siteUrl !== "" ? { url: config.siteUrl } : {},
|
|
191
|
-
...typeof config.siteName === "string" && config.siteName !== "" ? { name: config.siteName } : {}
|
|
232
|
+
...typeof config.siteName === "string" && config.siteName !== "" ? { name: config.siteName } : {},
|
|
233
|
+
...hosting !== null && hosting.platform !== null ? { hosting } : {}
|
|
192
234
|
};
|
|
193
235
|
}
|
|
236
|
+
function validationFields(body) {
|
|
237
|
+
if (typeof body !== "object" || body === null) return [];
|
|
238
|
+
const errors = body.errors;
|
|
239
|
+
if (typeof errors !== "object" || errors === null || Array.isArray(errors)) return [];
|
|
240
|
+
return Object.keys(errors);
|
|
241
|
+
}
|
|
194
242
|
async function postManifest(config, payload) {
|
|
195
243
|
const url = buildEndpointUrl(config.endpoint, config.siteUuid);
|
|
196
244
|
const timeoutMs = config.timeoutMs;
|
|
@@ -235,10 +283,12 @@ async function postManifest(config, payload) {
|
|
|
235
283
|
);
|
|
236
284
|
}
|
|
237
285
|
if (response.status === 422) {
|
|
238
|
-
|
|
286
|
+
const refused2 = new PatchstackError(
|
|
239
287
|
body?.message ?? "Patchstack rejected the manifest payload (validation failed).",
|
|
240
288
|
"VALIDATION_ERROR"
|
|
241
289
|
);
|
|
290
|
+
refused2.fields = validationFields(body);
|
|
291
|
+
throw refused2;
|
|
242
292
|
}
|
|
243
293
|
const refused = authFailureMessage(response.status, config);
|
|
244
294
|
if (refused !== null) {
|
|
@@ -266,6 +316,7 @@ var init_client = __esm({
|
|
|
266
316
|
"src/client.ts"() {
|
|
267
317
|
"use strict";
|
|
268
318
|
init_types();
|
|
319
|
+
init_hosting();
|
|
269
320
|
init_pulse_token();
|
|
270
321
|
init_build_id();
|
|
271
322
|
DEFAULT_ENDPOINT = "https://api.patchstack.com/monitor/pulse/manifest";
|
|
@@ -274,6 +325,85 @@ var init_client = __esm({
|
|
|
274
325
|
}
|
|
275
326
|
});
|
|
276
327
|
|
|
328
|
+
// src/environment.ts
|
|
329
|
+
function detectHostedBuilder(cwd) {
|
|
330
|
+
let declared;
|
|
331
|
+
try {
|
|
332
|
+
const pkg = JSON.parse((0, import_node_fs.readFileSync)(import_node_path.default.join(cwd, "package.json"), "utf8"));
|
|
333
|
+
declared = { ...pkg.dependencies ?? {}, ...pkg.devDependencies ?? {} };
|
|
334
|
+
} catch {
|
|
335
|
+
return null;
|
|
336
|
+
}
|
|
337
|
+
const names = Object.keys(declared);
|
|
338
|
+
for (const rule of HOSTED_BUILDER_PACKAGES) {
|
|
339
|
+
const hit = names.some(
|
|
340
|
+
(name) => rule.exact.includes(name) || rule.prefixes.some((prefix) => name.startsWith(prefix))
|
|
341
|
+
);
|
|
342
|
+
if (hit) return rule.builder;
|
|
343
|
+
}
|
|
344
|
+
return null;
|
|
345
|
+
}
|
|
346
|
+
function inferEnvironment(env = process.env, builder = null) {
|
|
347
|
+
for (const discriminator of DISCRIMINATORS) {
|
|
348
|
+
const verdict = discriminator.read(env);
|
|
349
|
+
if (verdict !== null) {
|
|
350
|
+
return { environment: verdict.environment, evidence: [`${discriminator.platform}: ${verdict.evidence}`] };
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
if (builder !== null) {
|
|
354
|
+
return {
|
|
355
|
+
environment: "production",
|
|
356
|
+
evidence: [`${builder}: a build in a ${builder} project is its publish step`]
|
|
357
|
+
};
|
|
358
|
+
}
|
|
359
|
+
return { environment: "local", evidence: [] };
|
|
360
|
+
}
|
|
361
|
+
var import_node_fs, import_node_path, set, DISCRIMINATORS, HOSTED_BUILDER_PACKAGES;
|
|
362
|
+
var init_environment = __esm({
|
|
363
|
+
"src/environment.ts"() {
|
|
364
|
+
"use strict";
|
|
365
|
+
import_node_fs = require("fs");
|
|
366
|
+
import_node_path = __toESM(require("path"), 1);
|
|
367
|
+
set = (value) => value !== void 0 && value !== "";
|
|
368
|
+
DISCRIMINATORS = [
|
|
369
|
+
{
|
|
370
|
+
platform: "vercel",
|
|
371
|
+
read: (env) => {
|
|
372
|
+
if (!set(env.VERCEL) || !set(env.VERCEL_ENV)) return null;
|
|
373
|
+
return env.VERCEL_ENV === "production" ? { environment: "production", evidence: "VERCEL_ENV=production" } : { environment: "sandbox", evidence: `VERCEL_ENV=${env.VERCEL_ENV}` };
|
|
374
|
+
}
|
|
375
|
+
},
|
|
376
|
+
{
|
|
377
|
+
platform: "netlify",
|
|
378
|
+
read: (env) => {
|
|
379
|
+
if (env.NETLIFY !== "true" || !set(env.CONTEXT)) return null;
|
|
380
|
+
return env.CONTEXT === "production" ? { environment: "production", evidence: "CONTEXT=production" } : { environment: "sandbox", evidence: `CONTEXT=${env.CONTEXT}` };
|
|
381
|
+
}
|
|
382
|
+
},
|
|
383
|
+
{
|
|
384
|
+
platform: "render",
|
|
385
|
+
read: (env) => {
|
|
386
|
+
if (env.RENDER !== "true") return null;
|
|
387
|
+
return env.IS_PULL_REQUEST === "true" ? { environment: "sandbox", evidence: "IS_PULL_REQUEST=true" } : { environment: "production", evidence: "RENDER=true, not a pull request" };
|
|
388
|
+
}
|
|
389
|
+
},
|
|
390
|
+
{
|
|
391
|
+
platform: "railway",
|
|
392
|
+
read: (env) => {
|
|
393
|
+
if (!set(env.RAILWAY_ENVIRONMENT_NAME)) return null;
|
|
394
|
+
return env.RAILWAY_ENVIRONMENT_NAME === "production" ? { environment: "production", evidence: "RAILWAY_ENVIRONMENT_NAME=production" } : { environment: "sandbox", evidence: `RAILWAY_ENVIRONMENT_NAME=${env.RAILWAY_ENVIRONMENT_NAME}` };
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
];
|
|
398
|
+
HOSTED_BUILDER_PACKAGES = [
|
|
399
|
+
// `lovable-tagger` covers projects from before ~Aug 2026; current templates ship the
|
|
400
|
+
// `@lovable.dev/*` scoped tooling instead.
|
|
401
|
+
{ builder: "lovable", exact: ["lovable-tagger"], prefixes: ["@lovable.dev/"] },
|
|
402
|
+
{ builder: "replit", exact: [], prefixes: ["@replit/"] }
|
|
403
|
+
];
|
|
404
|
+
}
|
|
405
|
+
});
|
|
406
|
+
|
|
277
407
|
// src/site-url.ts
|
|
278
408
|
function isUnpublishableHost(hostname) {
|
|
279
409
|
const host = hostname.toLowerCase().replace(/\.+$/, "");
|
|
@@ -378,13 +508,13 @@ async function readIfPresent(file) {
|
|
|
378
508
|
}
|
|
379
509
|
}
|
|
380
510
|
async function detectSiteName(cwd) {
|
|
381
|
-
for (const shell of ["index.html",
|
|
382
|
-
const html = await readIfPresent(
|
|
511
|
+
for (const shell of ["index.html", import_node_path2.default.join("public", "index.html")]) {
|
|
512
|
+
const html = await readIfPresent(import_node_path2.default.join(cwd, shell));
|
|
383
513
|
if (html === null) continue;
|
|
384
514
|
const name = nameFromHtmlTitle(html);
|
|
385
515
|
if (name !== null) return { name, source: "index.html" };
|
|
386
516
|
}
|
|
387
|
-
const manifest = await readIfPresent(
|
|
517
|
+
const manifest = await readIfPresent(import_node_path2.default.join(cwd, "package.json"));
|
|
388
518
|
if (manifest !== null) {
|
|
389
519
|
try {
|
|
390
520
|
const parsed = JSON.parse(manifest);
|
|
@@ -397,12 +527,12 @@ async function detectSiteName(cwd) {
|
|
|
397
527
|
}
|
|
398
528
|
return null;
|
|
399
529
|
}
|
|
400
|
-
var import_promises,
|
|
530
|
+
var import_promises, import_node_path2, NAME_MAX_LENGTH, TEMPLATE_PACKAGE_NAMES, TEMPLATE_TITLES, NAMED_ENTITIES2;
|
|
401
531
|
var init_site_name = __esm({
|
|
402
532
|
"src/site-name.ts"() {
|
|
403
533
|
"use strict";
|
|
404
534
|
import_promises = require("fs/promises");
|
|
405
|
-
|
|
535
|
+
import_node_path2 = __toESM(require("path"), 1);
|
|
406
536
|
NAME_MAX_LENGTH = 191;
|
|
407
537
|
TEMPLATE_PACKAGE_NAMES = /* @__PURE__ */ new Set([
|
|
408
538
|
// Lovable
|
|
@@ -485,11 +615,13 @@ async function resolveConfig(options) {
|
|
|
485
615
|
const environmentRaw = fromEnv.environment ?? fromFile.environment;
|
|
486
616
|
if (environmentRaw !== void 0 && !isEnvironment(environmentRaw)) {
|
|
487
617
|
throw new PatchstackError(
|
|
488
|
-
`Environment must be "production" or "
|
|
618
|
+
`Environment must be "production", "sandbox" or "local"; got "${environmentRaw}".`,
|
|
489
619
|
"CONFIG_INVALID"
|
|
490
620
|
);
|
|
491
621
|
}
|
|
492
|
-
const
|
|
622
|
+
const inferred = environmentRaw === void 0 ? inferEnvironment(process.env, detectHostedBuilder(options.cwd)) : null;
|
|
623
|
+
const environment = environmentRaw ?? inferred.environment;
|
|
624
|
+
const environmentEvidence = inferred?.evidence ?? [];
|
|
493
625
|
if (siteUuid !== null && siteUuid.length > 0 && !isUuid(siteUuid)) {
|
|
494
626
|
throw new PatchstackError(
|
|
495
627
|
`Site UUID "${siteUuid}" does not look like a valid UUID.`,
|
|
@@ -515,6 +647,7 @@ async function resolveConfig(options) {
|
|
|
515
647
|
endpoint,
|
|
516
648
|
timeoutMs,
|
|
517
649
|
environment,
|
|
650
|
+
environmentEvidence,
|
|
518
651
|
widget: fromFile.widget !== false,
|
|
519
652
|
claimToken
|
|
520
653
|
};
|
|
@@ -527,7 +660,7 @@ async function readConfigFile(cwd) {
|
|
|
527
660
|
return readJsonFile(cwd, CONFIG_FILENAME);
|
|
528
661
|
}
|
|
529
662
|
async function readJsonFile(cwd, filename) {
|
|
530
|
-
const target =
|
|
663
|
+
const target = import_node_path3.default.join(cwd, filename);
|
|
531
664
|
let raw;
|
|
532
665
|
try {
|
|
533
666
|
raw = await (0, import_promises2.readFile)(target, "utf8");
|
|
@@ -580,21 +713,21 @@ function isUuid(value) {
|
|
|
580
713
|
return /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(value);
|
|
581
714
|
}
|
|
582
715
|
function isEnvironment(value) {
|
|
583
|
-
return value === "production" || value === "sandbox";
|
|
716
|
+
return value === "production" || value === "sandbox" || value === "local";
|
|
584
717
|
}
|
|
585
|
-
var import_promises2,
|
|
718
|
+
var import_promises2, import_node_path3, CONFIG_FILENAME, SECRET_FILENAME;
|
|
586
719
|
var init_config = __esm({
|
|
587
720
|
"src/config.ts"() {
|
|
588
721
|
"use strict";
|
|
589
722
|
import_promises2 = require("fs/promises");
|
|
590
|
-
|
|
723
|
+
import_node_path3 = __toESM(require("path"), 1);
|
|
591
724
|
init_types();
|
|
592
725
|
init_client();
|
|
726
|
+
init_environment();
|
|
593
727
|
init_site_url();
|
|
594
728
|
init_site_name();
|
|
595
729
|
CONFIG_FILENAME = ".patchstackrc.json";
|
|
596
730
|
SECRET_FILENAME = ".patchstackrc.local.json";
|
|
597
|
-
DEFAULT_ENVIRONMENT = "production";
|
|
598
731
|
}
|
|
599
732
|
});
|
|
600
733
|
|
|
@@ -602,7 +735,7 @@ var init_config = __esm({
|
|
|
602
735
|
async function readDeclaredDependencyNames(cwd) {
|
|
603
736
|
let raw;
|
|
604
737
|
try {
|
|
605
|
-
raw = await (0, import_promises3.readFile)(
|
|
738
|
+
raw = await (0, import_promises3.readFile)(import_node_path4.default.join(cwd, "package.json"), "utf8");
|
|
606
739
|
} catch {
|
|
607
740
|
return [];
|
|
608
741
|
}
|
|
@@ -631,8 +764,8 @@ async function readDeclaredDependencyNames(cwd) {
|
|
|
631
764
|
return [...names];
|
|
632
765
|
}
|
|
633
766
|
function missingDependencies(declared, packages) {
|
|
634
|
-
const
|
|
635
|
-
return declared.filter((name) => !
|
|
767
|
+
const present2 = new Set(packages.map((entry) => entry.name));
|
|
768
|
+
return declared.filter((name) => !present2.has(name));
|
|
636
769
|
}
|
|
637
770
|
function disagreements(packages, other) {
|
|
638
771
|
const otherVersions = /* @__PURE__ */ new Map();
|
|
@@ -651,12 +784,12 @@ function disagreements(packages, other) {
|
|
|
651
784
|
}
|
|
652
785
|
return conflicts;
|
|
653
786
|
}
|
|
654
|
-
var import_promises3,
|
|
787
|
+
var import_promises3, import_node_path4;
|
|
655
788
|
var init_consistency = __esm({
|
|
656
789
|
"src/parsers/consistency.ts"() {
|
|
657
790
|
"use strict";
|
|
658
791
|
import_promises3 = require("fs/promises");
|
|
659
|
-
|
|
792
|
+
import_node_path4 = __toESM(require("path"), 1);
|
|
660
793
|
}
|
|
661
794
|
});
|
|
662
795
|
|
|
@@ -874,7 +1007,7 @@ function extractFromV1(deps, acc = [], depth = 0) {
|
|
|
874
1007
|
return acc;
|
|
875
1008
|
}
|
|
876
1009
|
function extractNameFromPath(pkgPath) {
|
|
877
|
-
const segments = pkgPath.split("node_modules" +
|
|
1010
|
+
const segments = pkgPath.split("node_modules" + import_node_path5.default.sep === pkgPath ? import_node_path5.default.sep : "/");
|
|
878
1011
|
const parts = pkgPath.split("/");
|
|
879
1012
|
const nmIndex = parts.lastIndexOf("node_modules");
|
|
880
1013
|
if (nmIndex === -1 || nmIndex >= parts.length - 1) {
|
|
@@ -895,19 +1028,19 @@ function isDirectV2(pkgPath) {
|
|
|
895
1028
|
const nmCount = parts.filter((p) => p === "node_modules").length;
|
|
896
1029
|
return nmCount === 1;
|
|
897
1030
|
}
|
|
898
|
-
var import_promises5,
|
|
1031
|
+
var import_promises5, import_node_path5;
|
|
899
1032
|
var init_npm = __esm({
|
|
900
1033
|
"src/parsers/npm.ts"() {
|
|
901
1034
|
"use strict";
|
|
902
1035
|
import_promises5 = require("fs/promises");
|
|
903
|
-
|
|
1036
|
+
import_node_path5 = __toESM(require("path"), 1);
|
|
904
1037
|
init_types();
|
|
905
1038
|
}
|
|
906
1039
|
});
|
|
907
1040
|
|
|
908
1041
|
// src/parsers/node_modules.ts
|
|
909
1042
|
async function walkNodeModules(cwd) {
|
|
910
|
-
const root =
|
|
1043
|
+
const root = import_node_path6.default.join(cwd, "node_modules");
|
|
911
1044
|
try {
|
|
912
1045
|
const info = await (0, import_promises6.stat)(root);
|
|
913
1046
|
if (!info.isDirectory()) {
|
|
@@ -950,7 +1083,7 @@ async function walk(dir, depth, seen, root) {
|
|
|
950
1083
|
}
|
|
951
1084
|
const perEntry = await mapLimit(names, async (name) => {
|
|
952
1085
|
if (name.startsWith(".") && !PACKAGE_STORE_DIRS.has(name)) return [];
|
|
953
|
-
const fullPath =
|
|
1086
|
+
const fullPath = import_node_path6.default.join(dir, name);
|
|
954
1087
|
const resolved = await claim(fullPath, seen, depth);
|
|
955
1088
|
if (resolved === null) return [];
|
|
956
1089
|
if (PACKAGE_STORE_DIRS.has(name)) return walk(fullPath, depth, seen, root);
|
|
@@ -963,7 +1096,7 @@ async function walk(dir, depth, seen, root) {
|
|
|
963
1096
|
}
|
|
964
1097
|
const scoped = await mapLimit(subNames, async (sub) => {
|
|
965
1098
|
if (sub.startsWith(".")) return [];
|
|
966
|
-
const scopedDir =
|
|
1099
|
+
const scopedDir = import_node_path6.default.join(fullPath, sub);
|
|
967
1100
|
const scopedReal = await claim(scopedDir, seen, depth);
|
|
968
1101
|
if (scopedReal === null) return [];
|
|
969
1102
|
return packageAndNested(scopedDir, scopedReal, depth, seen, root);
|
|
@@ -990,13 +1123,13 @@ async function mapLimit(items, fn) {
|
|
|
990
1123
|
await Promise.all(workers);
|
|
991
1124
|
return results;
|
|
992
1125
|
}
|
|
993
|
-
function installLocation(root, pkgDir, impl =
|
|
1126
|
+
function installLocation(root, pkgDir, impl = import_node_path6.default) {
|
|
994
1127
|
return impl.relative(root, pkgDir).split(impl.sep).join("/");
|
|
995
1128
|
}
|
|
996
1129
|
async function readPackage(pkgDir, depth, root) {
|
|
997
1130
|
let raw;
|
|
998
1131
|
try {
|
|
999
|
-
raw = await (0, import_promises6.readFile)(
|
|
1132
|
+
raw = await (0, import_promises6.readFile)(import_node_path6.default.join(pkgDir, "package.json"), "utf8");
|
|
1000
1133
|
} catch {
|
|
1001
1134
|
return null;
|
|
1002
1135
|
}
|
|
@@ -1015,7 +1148,7 @@ async function readPackage(pkgDir, depth, root) {
|
|
|
1015
1148
|
return { name: parsed.name, version: parsed.version, path: installLocation(root, pkgDir), direct: depth === 0 };
|
|
1016
1149
|
}
|
|
1017
1150
|
async function walkNested(pkgDir, depth, seen, root) {
|
|
1018
|
-
const nested =
|
|
1151
|
+
const nested = import_node_path6.default.join(pkgDir, "node_modules");
|
|
1019
1152
|
if (await claim(nested, seen, depth + 1) === null) {
|
|
1020
1153
|
return [];
|
|
1021
1154
|
}
|
|
@@ -1037,12 +1170,12 @@ async function claim(dir, seen, depth) {
|
|
|
1037
1170
|
seen.set(resolved, depth);
|
|
1038
1171
|
return resolved;
|
|
1039
1172
|
}
|
|
1040
|
-
var import_promises6,
|
|
1173
|
+
var import_promises6, import_node_path6, PACKAGE_STORE_DIRS, CONCURRENCY;
|
|
1041
1174
|
var init_node_modules = __esm({
|
|
1042
1175
|
"src/parsers/node_modules.ts"() {
|
|
1043
1176
|
"use strict";
|
|
1044
1177
|
import_promises6 = require("fs/promises");
|
|
1045
|
-
|
|
1178
|
+
import_node_path6 = __toESM(require("path"), 1);
|
|
1046
1179
|
init_types();
|
|
1047
1180
|
PACKAGE_STORE_DIRS = /* @__PURE__ */ new Set([".bun", ".pnpm", ".store"]);
|
|
1048
1181
|
CONCURRENCY = 32;
|
|
@@ -1329,7 +1462,7 @@ async function parseYarnLockfile(lockfilePath, report) {
|
|
|
1329
1462
|
"LOCKFILE_PARSE_ERROR"
|
|
1330
1463
|
);
|
|
1331
1464
|
}
|
|
1332
|
-
const directNames = await readDirectDepNames(
|
|
1465
|
+
const directNames = await readDirectDepNames(import_node_path7.default.dirname(lockfilePath));
|
|
1333
1466
|
const entries = [];
|
|
1334
1467
|
const seen = /* @__PURE__ */ new Set();
|
|
1335
1468
|
for (const block of blocks) {
|
|
@@ -1494,7 +1627,7 @@ async function readDirectDepNames(cwd) {
|
|
|
1494
1627
|
const names = /* @__PURE__ */ new Set();
|
|
1495
1628
|
let raw;
|
|
1496
1629
|
try {
|
|
1497
|
-
raw = await (0, import_promises8.readFile)(
|
|
1630
|
+
raw = await (0, import_promises8.readFile)(import_node_path7.default.join(cwd, "package.json"), "utf8");
|
|
1498
1631
|
} catch {
|
|
1499
1632
|
return names;
|
|
1500
1633
|
}
|
|
@@ -1519,12 +1652,12 @@ async function readDirectDepNames(cwd) {
|
|
|
1519
1652
|
}
|
|
1520
1653
|
return names;
|
|
1521
1654
|
}
|
|
1522
|
-
var import_promises8,
|
|
1655
|
+
var import_promises8, import_node_path7, NON_PACKAGE_KEYS, NON_REGISTRY_PROTOCOLS;
|
|
1523
1656
|
var init_yarn = __esm({
|
|
1524
1657
|
"src/parsers/yarn.ts"() {
|
|
1525
1658
|
"use strict";
|
|
1526
1659
|
import_promises8 = require("fs/promises");
|
|
1527
|
-
|
|
1660
|
+
import_node_path7 = __toESM(require("path"), 1);
|
|
1528
1661
|
init_types();
|
|
1529
1662
|
init_report();
|
|
1530
1663
|
NON_PACKAGE_KEYS = /* @__PURE__ */ new Set(["__metadata"]);
|
|
@@ -1536,7 +1669,7 @@ var init_yarn = __esm({
|
|
|
1536
1669
|
async function detectLockfile(cwd) {
|
|
1537
1670
|
const probed = await Promise.all(
|
|
1538
1671
|
LOCKFILE_CANDIDATES.map(async (candidate) => {
|
|
1539
|
-
const filePath =
|
|
1672
|
+
const filePath = import_node_path8.default.join(cwd, candidate.filename);
|
|
1540
1673
|
return { ...candidate, filePath, present: await exists(filePath) };
|
|
1541
1674
|
})
|
|
1542
1675
|
);
|
|
@@ -1647,7 +1780,7 @@ function staleWarning(source, missing) {
|
|
|
1647
1780
|
async function presentLockfiles(cwd) {
|
|
1648
1781
|
const probed = await Promise.all(
|
|
1649
1782
|
LOCKFILE_CANDIDATES.map(async (candidate) => {
|
|
1650
|
-
const filePath =
|
|
1783
|
+
const filePath = import_node_path8.default.join(cwd, candidate.filename);
|
|
1651
1784
|
return { ...candidate, filePath, present: await exists(filePath) };
|
|
1652
1785
|
})
|
|
1653
1786
|
);
|
|
@@ -1677,12 +1810,12 @@ async function exists(filePath) {
|
|
|
1677
1810
|
return false;
|
|
1678
1811
|
}
|
|
1679
1812
|
}
|
|
1680
|
-
var import_promises9,
|
|
1813
|
+
var import_promises9, import_node_path8, LOCKFILE_CANDIDATES;
|
|
1681
1814
|
var init_parsers = __esm({
|
|
1682
1815
|
"src/parsers/index.ts"() {
|
|
1683
1816
|
"use strict";
|
|
1684
1817
|
import_promises9 = require("fs/promises");
|
|
1685
|
-
|
|
1818
|
+
import_node_path8 = __toESM(require("path"), 1);
|
|
1686
1819
|
init_types();
|
|
1687
1820
|
init_consistency();
|
|
1688
1821
|
init_bun();
|
|
@@ -3125,12 +3258,12 @@ function isRegexForm(pattern) {
|
|
|
3125
3258
|
const parts = REGEX_FORM.exec(pattern);
|
|
3126
3259
|
return parts !== null && REGEX_SYNTAX.test(parts[1]);
|
|
3127
3260
|
}
|
|
3128
|
-
function pathMatches(pattern,
|
|
3261
|
+
function pathMatches(pattern, path9) {
|
|
3129
3262
|
if (isRegexForm(pattern)) {
|
|
3130
3263
|
const re = safeRegExp(pattern);
|
|
3131
|
-
return re ? re.test(
|
|
3264
|
+
return re ? re.test(path9) : false;
|
|
3132
3265
|
}
|
|
3133
|
-
const target = foldPathForScope(
|
|
3266
|
+
const target = foldPathForScope(path9);
|
|
3134
3267
|
const folded = foldPathForScope(pattern);
|
|
3135
3268
|
if (folded.includes("*")) {
|
|
3136
3269
|
const trailing = folded.endsWith("/*");
|
|
@@ -4773,8 +4906,8 @@ function extractHttpTarget(args) {
|
|
|
4773
4906
|
const host = normalizeHost(first.hostname || first.host) || "localhost";
|
|
4774
4907
|
const protocol = first.protocol || "http:";
|
|
4775
4908
|
const port = first.port ? `:${first.port}` : "";
|
|
4776
|
-
const
|
|
4777
|
-
return { url: `${protocol}//${host}${port}${
|
|
4909
|
+
const path9 = first.path || "/";
|
|
4910
|
+
return { url: `${protocol}//${host}${port}${path9}`, host, method: first.method || "GET" };
|
|
4778
4911
|
}
|
|
4779
4912
|
} catch {
|
|
4780
4913
|
}
|
|
@@ -5140,12 +5273,12 @@ var fsMod;
|
|
|
5140
5273
|
async function loadFs() {
|
|
5141
5274
|
if (fsMod !== void 0) return fsMod;
|
|
5142
5275
|
try {
|
|
5143
|
-
const [fs,
|
|
5276
|
+
const [fs, path9] = await Promise.all([import("fs"), import("path")]);
|
|
5144
5277
|
fsMod = {
|
|
5145
5278
|
readFileSync: fs.readFileSync,
|
|
5146
5279
|
writeFileSync: fs.writeFileSync,
|
|
5147
5280
|
mkdirSync: fs.mkdirSync,
|
|
5148
|
-
join:
|
|
5281
|
+
join: path9.join
|
|
5149
5282
|
};
|
|
5150
5283
|
} catch {
|
|
5151
5284
|
fsMod = null;
|
|
@@ -5533,13 +5666,13 @@ var MAX_CAPTURED_VALUE_CHARS = 512;
|
|
|
5533
5666
|
var MAX_QUERY_KEYS = 10;
|
|
5534
5667
|
var MAX_METHOD_CHARS = 16;
|
|
5535
5668
|
var MAX_BODY_BYTES2 = 64 * 1024;
|
|
5536
|
-
function queryKeysOf(
|
|
5537
|
-
if (typeof
|
|
5538
|
-
const start =
|
|
5669
|
+
function queryKeysOf(path9) {
|
|
5670
|
+
if (typeof path9 !== "string") return { keys: [], total: 0 };
|
|
5671
|
+
const start = path9.indexOf("?");
|
|
5539
5672
|
if (start === -1) return { keys: [], total: 0 };
|
|
5540
5673
|
let names;
|
|
5541
5674
|
try {
|
|
5542
|
-
names = [...new URLSearchParams(
|
|
5675
|
+
names = [...new URLSearchParams(path9.slice(start + 1)).keys()];
|
|
5543
5676
|
} catch {
|
|
5544
5677
|
return { keys: [], total: 0 };
|
|
5545
5678
|
}
|
|
@@ -5678,10 +5811,10 @@ function revisionOf(rule) {
|
|
|
5678
5811
|
if (typeof revision === "number" && Number.isFinite(revision)) return String(revision);
|
|
5679
5812
|
return null;
|
|
5680
5813
|
}
|
|
5681
|
-
function routeOf(
|
|
5682
|
-
if (typeof
|
|
5683
|
-
const cut =
|
|
5684
|
-
return cut === -1 ?
|
|
5814
|
+
function routeOf(path9) {
|
|
5815
|
+
if (typeof path9 !== "string" || path9 === "") return null;
|
|
5816
|
+
const cut = path9.search(/[?#]/);
|
|
5817
|
+
return cut === -1 ? path9 : path9.slice(0, cut);
|
|
5685
5818
|
}
|
|
5686
5819
|
function createDetectionReporter(opts) {
|
|
5687
5820
|
const siteUuid = opts.siteUuid ?? process.env?.PATCHSTACK_SITE_UUID;
|
|
@@ -6985,8 +7118,8 @@ async function createProtection(options = {}) {
|
|
|
6985
7118
|
hardened = true;
|
|
6986
7119
|
try {
|
|
6987
7120
|
if (res.headersSent || typeof res.setHeader !== "function") return null;
|
|
6988
|
-
const
|
|
6989
|
-
const headers = effective && effective.headers ? { ...
|
|
7121
|
+
const set2 = typeof res.getHeaders === "function" ? res.getHeaders() : {};
|
|
7122
|
+
const headers = effective && effective.headers ? { ...set2, ...effective.headers } : set2;
|
|
6990
7123
|
const status = effective && effective.status !== void 0 ? effective.status : res.statusCode;
|
|
6991
7124
|
const r = screenText("", { status, headers }, reqCtx, hardensWithoutBody);
|
|
6992
7125
|
answeredWithoutBody = true;
|
|
@@ -7389,11 +7522,11 @@ function resolveMode(options, bundle) {
|
|
|
7389
7522
|
var CREDENTIAL_FILES = [".patchstackrc.local.json", ".patchstackrc.json"];
|
|
7390
7523
|
async function readCredentialField(options, field) {
|
|
7391
7524
|
if (typeof process === "undefined" || typeof process.cwd !== "function") return void 0;
|
|
7392
|
-
let
|
|
7525
|
+
let readFileSync2;
|
|
7393
7526
|
let join;
|
|
7394
7527
|
try {
|
|
7395
7528
|
const [fs, pathMod] = await Promise.all([import("fs"), import("path")]);
|
|
7396
|
-
|
|
7529
|
+
readFileSync2 = fs.readFileSync;
|
|
7397
7530
|
join = pathMod.join;
|
|
7398
7531
|
} catch {
|
|
7399
7532
|
return void 0;
|
|
@@ -7401,7 +7534,7 @@ async function readCredentialField(options, field) {
|
|
|
7401
7534
|
const cwd = options?.cwd ?? process.cwd();
|
|
7402
7535
|
for (const filename of CREDENTIAL_FILES) {
|
|
7403
7536
|
try {
|
|
7404
|
-
const value = JSON.parse(
|
|
7537
|
+
const value = JSON.parse(readFileSync2(join(cwd, filename), "utf8"))?.[field];
|
|
7405
7538
|
if (typeof value === "string" && value.length > 0) return value;
|
|
7406
7539
|
} catch {
|
|
7407
7540
|
}
|
|
@@ -7698,8 +7831,8 @@ function applyHeaderMutation(headers, rule) {
|
|
|
7698
7831
|
const ensure = rule.ensure === true;
|
|
7699
7832
|
for (const [name, value] of Object.entries(rule.set_headers ?? {})) {
|
|
7700
7833
|
const key = String(name).toLowerCase();
|
|
7701
|
-
const
|
|
7702
|
-
if (ensure &&
|
|
7834
|
+
const present2 = headers[key] != null && headers[key] !== "";
|
|
7835
|
+
if (ensure && present2) continue;
|
|
7703
7836
|
headers[key] = String(value);
|
|
7704
7837
|
}
|
|
7705
7838
|
return;
|
|
@@ -7822,20 +7955,20 @@ function requestMetaFromContext(reqCtx) {
|
|
|
7822
7955
|
}
|
|
7823
7956
|
function requestMeta(shaped, request) {
|
|
7824
7957
|
const client = shaped?._clientIp ?? { ip: null, source: "unavailable" };
|
|
7825
|
-
let
|
|
7958
|
+
let path9 = null;
|
|
7826
7959
|
let method = null;
|
|
7827
7960
|
let userAgent = null;
|
|
7828
7961
|
if (request) {
|
|
7829
7962
|
try {
|
|
7830
7963
|
const u = new URL(request.url);
|
|
7831
|
-
|
|
7964
|
+
path9 = u.pathname + u.search;
|
|
7832
7965
|
} catch {
|
|
7833
|
-
|
|
7966
|
+
path9 = typeof request.url === "string" ? request.url : null;
|
|
7834
7967
|
}
|
|
7835
7968
|
method = request.method ?? null;
|
|
7836
7969
|
userAgent = request.headers?.get?.("user-agent") ?? null;
|
|
7837
7970
|
}
|
|
7838
|
-
return { method, path:
|
|
7971
|
+
return { method, path: path9, ip: client.ip, clientIpSource: client.source, userAgent, event: eventFor(request) };
|
|
7839
7972
|
}
|
|
7840
7973
|
function nodeRequestMeta(req, client) {
|
|
7841
7974
|
if (!req) return {};
|