@patchstack/connect 0.2.6 → 0.2.8
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/README.md +7 -1
- package/dist/cli.js +272 -162
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +170 -78
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +16 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.js +163 -71
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -47,8 +47,8 @@ __export(src_exports, {
|
|
|
47
47
|
module.exports = __toCommonJS(src_exports);
|
|
48
48
|
|
|
49
49
|
// src/parsers/index.ts
|
|
50
|
-
var
|
|
51
|
-
var
|
|
50
|
+
var import_promises6 = require("fs/promises");
|
|
51
|
+
var import_node_path5 = __toESM(require("path"), 1);
|
|
52
52
|
|
|
53
53
|
// src/types.ts
|
|
54
54
|
var PatchstackError = class extends Error {
|
|
@@ -62,13 +62,52 @@ var PatchstackError = class extends Error {
|
|
|
62
62
|
cause;
|
|
63
63
|
};
|
|
64
64
|
|
|
65
|
-
// src/parsers/
|
|
65
|
+
// src/parsers/consistency.ts
|
|
66
66
|
var import_promises = require("fs/promises");
|
|
67
67
|
var import_node_path = __toESM(require("path"), 1);
|
|
68
|
+
async function readDeclaredDependencyNames(cwd) {
|
|
69
|
+
let raw;
|
|
70
|
+
try {
|
|
71
|
+
raw = await (0, import_promises.readFile)(import_node_path.default.join(cwd, "package.json"), "utf8");
|
|
72
|
+
} catch {
|
|
73
|
+
return [];
|
|
74
|
+
}
|
|
75
|
+
let parsed;
|
|
76
|
+
try {
|
|
77
|
+
parsed = JSON.parse(raw);
|
|
78
|
+
} catch {
|
|
79
|
+
return [];
|
|
80
|
+
}
|
|
81
|
+
if (typeof parsed !== "object" || parsed === null) {
|
|
82
|
+
return [];
|
|
83
|
+
}
|
|
84
|
+
const names = /* @__PURE__ */ new Set();
|
|
85
|
+
for (const group of ["dependencies", "devDependencies"]) {
|
|
86
|
+
const deps = parsed[group];
|
|
87
|
+
if (typeof deps !== "object" || deps === null) {
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
for (const [name, spec] of Object.entries(deps)) {
|
|
91
|
+
if (typeof spec === "string" && /^(file|link|workspace|portal):/.test(spec)) {
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
names.add(name);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return [...names];
|
|
98
|
+
}
|
|
99
|
+
function missingDependencies(declared, packages) {
|
|
100
|
+
const present = new Set(packages.map((entry) => entry.name));
|
|
101
|
+
return declared.filter((name) => !present.has(name));
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// src/parsers/npm.ts
|
|
105
|
+
var import_promises2 = require("fs/promises");
|
|
106
|
+
var import_node_path2 = __toESM(require("path"), 1);
|
|
68
107
|
async function parseNpmLockfile(lockfilePath) {
|
|
69
108
|
let raw;
|
|
70
109
|
try {
|
|
71
|
-
raw = await (0,
|
|
110
|
+
raw = await (0, import_promises2.readFile)(lockfilePath, "utf8");
|
|
72
111
|
} catch (cause) {
|
|
73
112
|
throw new PatchstackError(`Could not read lockfile at ${lockfilePath}`, "LOCKFILE_NOT_FOUND", cause);
|
|
74
113
|
}
|
|
@@ -126,7 +165,7 @@ function extractFromV1(deps, acc = [], depth = 0) {
|
|
|
126
165
|
return acc;
|
|
127
166
|
}
|
|
128
167
|
function extractNameFromPath(pkgPath) {
|
|
129
|
-
const segments = pkgPath.split("node_modules" +
|
|
168
|
+
const segments = pkgPath.split("node_modules" + import_node_path2.default.sep === pkgPath ? import_node_path2.default.sep : "/");
|
|
130
169
|
const parts = pkgPath.split("/");
|
|
131
170
|
const nmIndex = parts.lastIndexOf("node_modules");
|
|
132
171
|
if (nmIndex === -1 || nmIndex >= parts.length - 1) {
|
|
@@ -149,12 +188,12 @@ function isDirectV2(pkgPath) {
|
|
|
149
188
|
}
|
|
150
189
|
|
|
151
190
|
// src/parsers/node_modules.ts
|
|
152
|
-
var
|
|
153
|
-
var
|
|
191
|
+
var import_promises3 = require("fs/promises");
|
|
192
|
+
var import_node_path3 = __toESM(require("path"), 1);
|
|
154
193
|
async function walkNodeModules(cwd) {
|
|
155
|
-
const root =
|
|
194
|
+
const root = import_node_path3.default.join(cwd, "node_modules");
|
|
156
195
|
try {
|
|
157
|
-
const info = await (0,
|
|
196
|
+
const info = await (0, import_promises3.stat)(root);
|
|
158
197
|
if (!info.isDirectory()) {
|
|
159
198
|
throw new PatchstackError(
|
|
160
199
|
`${root} exists but is not a directory.`,
|
|
@@ -178,7 +217,7 @@ async function walkNodeModules(cwd) {
|
|
|
178
217
|
async function walk(dir, acc, depth) {
|
|
179
218
|
let names;
|
|
180
219
|
try {
|
|
181
|
-
names = await (0,
|
|
220
|
+
names = await (0, import_promises3.readdir)(dir);
|
|
182
221
|
} catch {
|
|
183
222
|
return;
|
|
184
223
|
}
|
|
@@ -186,14 +225,14 @@ async function walk(dir, acc, depth) {
|
|
|
186
225
|
if (name.startsWith(".")) {
|
|
187
226
|
continue;
|
|
188
227
|
}
|
|
189
|
-
const fullPath =
|
|
228
|
+
const fullPath = import_node_path3.default.join(dir, name);
|
|
190
229
|
if (!await isPlainDirectory(fullPath)) {
|
|
191
230
|
continue;
|
|
192
231
|
}
|
|
193
232
|
if (name.startsWith("@")) {
|
|
194
233
|
let subNames;
|
|
195
234
|
try {
|
|
196
|
-
subNames = await (0,
|
|
235
|
+
subNames = await (0, import_promises3.readdir)(fullPath);
|
|
197
236
|
} catch {
|
|
198
237
|
continue;
|
|
199
238
|
}
|
|
@@ -201,7 +240,7 @@ async function walk(dir, acc, depth) {
|
|
|
201
240
|
if (sub.startsWith(".")) {
|
|
202
241
|
continue;
|
|
203
242
|
}
|
|
204
|
-
const scopedDir =
|
|
243
|
+
const scopedDir = import_node_path3.default.join(fullPath, sub);
|
|
205
244
|
if (!await isPlainDirectory(scopedDir)) {
|
|
206
245
|
continue;
|
|
207
246
|
}
|
|
@@ -217,7 +256,7 @@ async function walk(dir, acc, depth) {
|
|
|
217
256
|
async function readPackage(pkgDir, depth, acc) {
|
|
218
257
|
let raw;
|
|
219
258
|
try {
|
|
220
|
-
raw = await (0,
|
|
259
|
+
raw = await (0, import_promises3.readFile)(import_node_path3.default.join(pkgDir, "package.json"), "utf8");
|
|
221
260
|
} catch {
|
|
222
261
|
return;
|
|
223
262
|
}
|
|
@@ -240,7 +279,7 @@ async function readPackage(pkgDir, depth, acc) {
|
|
|
240
279
|
});
|
|
241
280
|
}
|
|
242
281
|
async function walkNested(pkgDir, acc, depth) {
|
|
243
|
-
const nested =
|
|
282
|
+
const nested = import_node_path3.default.join(pkgDir, "node_modules");
|
|
244
283
|
if (!await isPlainDirectory(nested)) {
|
|
245
284
|
return;
|
|
246
285
|
}
|
|
@@ -248,7 +287,7 @@ async function walkNested(pkgDir, acc, depth) {
|
|
|
248
287
|
}
|
|
249
288
|
async function isPlainDirectory(dir) {
|
|
250
289
|
try {
|
|
251
|
-
const info = await (0,
|
|
290
|
+
const info = await (0, import_promises3.lstat)(dir);
|
|
252
291
|
return info.isDirectory() && !info.isSymbolicLink();
|
|
253
292
|
} catch {
|
|
254
293
|
return false;
|
|
@@ -256,11 +295,11 @@ async function isPlainDirectory(dir) {
|
|
|
256
295
|
}
|
|
257
296
|
|
|
258
297
|
// src/parsers/pnpm.ts
|
|
259
|
-
var
|
|
298
|
+
var import_promises4 = require("fs/promises");
|
|
260
299
|
async function parsePnpmLockfile(lockfilePath) {
|
|
261
300
|
let raw;
|
|
262
301
|
try {
|
|
263
|
-
raw = await (0,
|
|
302
|
+
raw = await (0, import_promises4.readFile)(lockfilePath, "utf8");
|
|
264
303
|
} catch (cause) {
|
|
265
304
|
throw new PatchstackError(
|
|
266
305
|
`Could not read lockfile at ${lockfilePath}`,
|
|
@@ -508,12 +547,12 @@ function extractLeafName(trimmed) {
|
|
|
508
547
|
}
|
|
509
548
|
|
|
510
549
|
// src/parsers/yarn.ts
|
|
511
|
-
var
|
|
512
|
-
var
|
|
550
|
+
var import_promises5 = require("fs/promises");
|
|
551
|
+
var import_node_path4 = __toESM(require("path"), 1);
|
|
513
552
|
async function parseYarnLockfile(lockfilePath) {
|
|
514
553
|
let raw;
|
|
515
554
|
try {
|
|
516
|
-
raw = await (0,
|
|
555
|
+
raw = await (0, import_promises5.readFile)(lockfilePath, "utf8");
|
|
517
556
|
} catch (cause) {
|
|
518
557
|
throw new PatchstackError(
|
|
519
558
|
`Could not read lockfile at ${lockfilePath}`,
|
|
@@ -528,7 +567,7 @@ async function parseYarnLockfile(lockfilePath) {
|
|
|
528
567
|
"LOCKFILE_PARSE_ERROR"
|
|
529
568
|
);
|
|
530
569
|
}
|
|
531
|
-
const directNames = await readDirectDepNames(
|
|
570
|
+
const directNames = await readDirectDepNames(import_node_path4.default.dirname(lockfilePath));
|
|
532
571
|
const entries = [];
|
|
533
572
|
const seen = /* @__PURE__ */ new Set();
|
|
534
573
|
for (const block of blocks) {
|
|
@@ -672,7 +711,7 @@ async function readDirectDepNames(cwd) {
|
|
|
672
711
|
const names = /* @__PURE__ */ new Set();
|
|
673
712
|
let raw;
|
|
674
713
|
try {
|
|
675
|
-
raw = await (0,
|
|
714
|
+
raw = await (0, import_promises5.readFile)(import_node_path4.default.join(cwd, "package.json"), "utf8");
|
|
676
715
|
} catch {
|
|
677
716
|
return names;
|
|
678
717
|
}
|
|
@@ -699,61 +738,99 @@ async function readDirectDepNames(cwd) {
|
|
|
699
738
|
}
|
|
700
739
|
|
|
701
740
|
// src/parsers/index.ts
|
|
741
|
+
var LOCKFILE_CANDIDATES = [
|
|
742
|
+
{ filename: "package-lock.json", strategy: "npm-lockfile" },
|
|
743
|
+
{ filename: "bun.lock", strategy: "node-modules-walk" },
|
|
744
|
+
{ filename: "bun.lockb", strategy: "node-modules-walk" },
|
|
745
|
+
{ filename: "pnpm-lock.yaml", strategy: "pnpm-lockfile" },
|
|
746
|
+
{ filename: "yarn.lock", strategy: "yarn-lockfile" }
|
|
747
|
+
];
|
|
702
748
|
async function detectLockfile(cwd) {
|
|
703
|
-
const
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
}
|
|
712
|
-
const bunLock = import_node_path4.default.join(cwd, "bun.lock");
|
|
713
|
-
if (await exists(bunLock)) {
|
|
714
|
-
return {
|
|
715
|
-
ecosystem: "npm",
|
|
716
|
-
filePath: bunLock,
|
|
717
|
-
filename: "bun.lock",
|
|
718
|
-
strategy: "node-modules-walk"
|
|
719
|
-
};
|
|
720
|
-
}
|
|
721
|
-
const bunLockB = import_node_path4.default.join(cwd, "bun.lockb");
|
|
722
|
-
if (await exists(bunLockB)) {
|
|
723
|
-
return {
|
|
724
|
-
ecosystem: "npm",
|
|
725
|
-
filePath: bunLockB,
|
|
726
|
-
filename: "bun.lockb",
|
|
727
|
-
strategy: "node-modules-walk"
|
|
728
|
-
};
|
|
729
|
-
}
|
|
730
|
-
const pnpmLock = import_node_path4.default.join(cwd, "pnpm-lock.yaml");
|
|
731
|
-
if (await exists(pnpmLock)) {
|
|
732
|
-
return {
|
|
733
|
-
ecosystem: "npm",
|
|
734
|
-
filePath: pnpmLock,
|
|
735
|
-
filename: "pnpm-lock.yaml",
|
|
736
|
-
strategy: "pnpm-lockfile"
|
|
737
|
-
};
|
|
738
|
-
}
|
|
739
|
-
const yarnLock = import_node_path4.default.join(cwd, "yarn.lock");
|
|
740
|
-
if (await exists(yarnLock)) {
|
|
749
|
+
const probed = await Promise.all(
|
|
750
|
+
LOCKFILE_CANDIDATES.map(async (candidate) => {
|
|
751
|
+
const filePath = import_node_path5.default.join(cwd, candidate.filename);
|
|
752
|
+
return { ...candidate, filePath, present: await exists(filePath) };
|
|
753
|
+
})
|
|
754
|
+
);
|
|
755
|
+
const match = probed.find((candidate) => candidate.present);
|
|
756
|
+
if (match) {
|
|
741
757
|
return {
|
|
742
758
|
ecosystem: "npm",
|
|
743
|
-
filePath:
|
|
744
|
-
filename:
|
|
745
|
-
strategy:
|
|
759
|
+
filePath: match.filePath,
|
|
760
|
+
filename: match.filename,
|
|
761
|
+
strategy: match.strategy
|
|
746
762
|
};
|
|
747
763
|
}
|
|
764
|
+
const expected = LOCKFILE_CANDIDATES.map((candidate) => candidate.filename).join(", ");
|
|
748
765
|
throw new PatchstackError(
|
|
749
|
-
`No lockfile found in ${cwd}. Expected one of:
|
|
766
|
+
`No lockfile found in ${cwd}. Expected one of: ${expected}.`,
|
|
750
767
|
"LOCKFILE_NOT_FOUND"
|
|
751
768
|
);
|
|
752
769
|
}
|
|
753
770
|
async function scanLockfile(cwd) {
|
|
754
|
-
const
|
|
755
|
-
|
|
756
|
-
|
|
771
|
+
const candidates = await presentLockfiles(cwd);
|
|
772
|
+
if (candidates.length === 0) {
|
|
773
|
+
await detectLockfile(cwd);
|
|
774
|
+
}
|
|
775
|
+
const declared = await readDeclaredDependencyNames(cwd);
|
|
776
|
+
const warnings = [];
|
|
777
|
+
let firstParsed = null;
|
|
778
|
+
let walkTried = false;
|
|
779
|
+
for (const candidate of candidates) {
|
|
780
|
+
let packages;
|
|
781
|
+
try {
|
|
782
|
+
packages = await runStrategy(candidate, cwd);
|
|
783
|
+
} catch {
|
|
784
|
+
continue;
|
|
785
|
+
}
|
|
786
|
+
walkTried ||= candidate.strategy === "node-modules-walk";
|
|
787
|
+
firstParsed ??= { packages, filename: candidate.filename };
|
|
788
|
+
const missing = missingDependencies(declared, packages);
|
|
789
|
+
if (missing.length === 0) {
|
|
790
|
+
return manifestWith(packages, warnings);
|
|
791
|
+
}
|
|
792
|
+
warnings.push(staleWarning(candidate.filename, missing));
|
|
793
|
+
}
|
|
794
|
+
if (!walkTried) {
|
|
795
|
+
try {
|
|
796
|
+
const packages = await walkNodeModules(cwd);
|
|
797
|
+
const missing = missingDependencies(declared, packages);
|
|
798
|
+
if (missing.length > 0) {
|
|
799
|
+
warnings.push(staleWarning("node_modules/", missing));
|
|
800
|
+
}
|
|
801
|
+
warnings.push("Scanned node_modules/ instead. Delete the stale lockfile to silence this warning.");
|
|
802
|
+
return manifestWith(packages, warnings);
|
|
803
|
+
} catch {
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
if (firstParsed === null) {
|
|
807
|
+
const expected = LOCKFILE_CANDIDATES.map((candidate) => candidate.filename).join(", ");
|
|
808
|
+
throw new PatchstackError(
|
|
809
|
+
`No readable lockfile found in ${cwd}. Expected one of: ${expected}.`,
|
|
810
|
+
"LOCKFILE_NOT_FOUND"
|
|
811
|
+
);
|
|
812
|
+
}
|
|
813
|
+
warnings.push(
|
|
814
|
+
`No fully-consistent source found; reporting ${firstParsed.filename}. The manifest may understate the real dependency set.`
|
|
815
|
+
);
|
|
816
|
+
return manifestWith(firstParsed.packages, warnings);
|
|
817
|
+
}
|
|
818
|
+
function manifestWith(packages, warnings) {
|
|
819
|
+
return warnings.length > 0 ? { ecosystem: "npm", packages, warnings } : { ecosystem: "npm", packages };
|
|
820
|
+
}
|
|
821
|
+
function staleWarning(source, missing) {
|
|
822
|
+
const sample = missing.slice(0, 3).join(", ");
|
|
823
|
+
const suffix = missing.length > 3 ? `, +${missing.length - 3} more` : "";
|
|
824
|
+
return `${source} looks stale: package.json declares ${missing.length} dependenc${missing.length === 1 ? "y" : "ies"} it does not contain (${sample}${suffix}).`;
|
|
825
|
+
}
|
|
826
|
+
async function presentLockfiles(cwd) {
|
|
827
|
+
const probed = await Promise.all(
|
|
828
|
+
LOCKFILE_CANDIDATES.map(async (candidate) => {
|
|
829
|
+
const filePath = import_node_path5.default.join(cwd, candidate.filename);
|
|
830
|
+
return { ...candidate, filePath, present: await exists(filePath) };
|
|
831
|
+
})
|
|
832
|
+
);
|
|
833
|
+
return probed.filter((candidate) => candidate.present).map(({ filename, strategy, filePath }) => ({ ecosystem: "npm", filename, strategy, filePath }));
|
|
757
834
|
}
|
|
758
835
|
async function runStrategy(detected, cwd) {
|
|
759
836
|
switch (detected.strategy) {
|
|
@@ -769,7 +846,7 @@ async function runStrategy(detected, cwd) {
|
|
|
769
846
|
}
|
|
770
847
|
async function exists(filePath) {
|
|
771
848
|
try {
|
|
772
|
-
await (0,
|
|
849
|
+
await (0, import_promises6.access)(filePath);
|
|
773
850
|
return true;
|
|
774
851
|
} catch {
|
|
775
852
|
return false;
|
|
@@ -901,7 +978,7 @@ async function postManifest(config, payload) {
|
|
|
901
978
|
Accept: "application/json",
|
|
902
979
|
"User-Agent": "@patchstack/connect"
|
|
903
980
|
},
|
|
904
|
-
body: JSON.stringify(payload),
|
|
981
|
+
body: JSON.stringify({ ...payload, environment: config.environment }),
|
|
905
982
|
signal: AbortSignal.timeout(timeoutMs)
|
|
906
983
|
});
|
|
907
984
|
} catch (cause) {
|
|
@@ -956,15 +1033,24 @@ function isTimeoutError(cause) {
|
|
|
956
1033
|
}
|
|
957
1034
|
|
|
958
1035
|
// src/config.ts
|
|
959
|
-
var
|
|
960
|
-
var
|
|
1036
|
+
var import_promises7 = require("fs/promises");
|
|
1037
|
+
var import_node_path6 = __toESM(require("path"), 1);
|
|
961
1038
|
var CONFIG_FILENAME = ".patchstackrc.json";
|
|
1039
|
+
var DEFAULT_ENVIRONMENT = "production";
|
|
962
1040
|
async function resolveConfig(options) {
|
|
963
1041
|
const fromFile = await readConfigFile(options.cwd);
|
|
964
1042
|
const fromEnv = readEnv();
|
|
965
1043
|
const siteUuid = options.cliSiteUuid ?? fromEnv.siteUuid ?? fromFile.siteUuid ?? null;
|
|
966
1044
|
const endpoint = options.cliEndpoint ?? fromEnv.endpoint ?? fromFile.endpoint ?? DEFAULT_ENDPOINT;
|
|
967
1045
|
const timeoutMs = fromEnv.timeoutMs ?? fromFile.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
1046
|
+
const environmentRaw = fromEnv.environment ?? fromFile.environment;
|
|
1047
|
+
if (environmentRaw !== void 0 && !isEnvironment(environmentRaw)) {
|
|
1048
|
+
throw new PatchstackError(
|
|
1049
|
+
`Environment must be "production" or "sandbox"; got "${environmentRaw}".`,
|
|
1050
|
+
"CONFIG_INVALID"
|
|
1051
|
+
);
|
|
1052
|
+
}
|
|
1053
|
+
const environment = environmentRaw ?? DEFAULT_ENVIRONMENT;
|
|
968
1054
|
if (siteUuid !== null && siteUuid.length > 0 && !isUuid(siteUuid)) {
|
|
969
1055
|
throw new PatchstackError(
|
|
970
1056
|
`Site UUID "${siteUuid}" does not look like a valid UUID.`,
|
|
@@ -980,13 +1066,14 @@ async function resolveConfig(options) {
|
|
|
980
1066
|
return {
|
|
981
1067
|
siteUuid: siteUuid === null || siteUuid.length === 0 ? null : siteUuid,
|
|
982
1068
|
endpoint,
|
|
983
|
-
timeoutMs
|
|
1069
|
+
timeoutMs,
|
|
1070
|
+
environment
|
|
984
1071
|
};
|
|
985
1072
|
}
|
|
986
1073
|
async function writeConfigFile(cwd, config) {
|
|
987
|
-
const target =
|
|
1074
|
+
const target = import_node_path6.default.join(cwd, CONFIG_FILENAME);
|
|
988
1075
|
const content = JSON.stringify(config, null, 2) + "\n";
|
|
989
|
-
await (0,
|
|
1076
|
+
await (0, import_promises7.writeFile)(target, content, "utf8");
|
|
990
1077
|
return target;
|
|
991
1078
|
}
|
|
992
1079
|
async function persistSiteUuid(cwd, siteUuid) {
|
|
@@ -994,10 +1081,10 @@ async function persistSiteUuid(cwd, siteUuid) {
|
|
|
994
1081
|
return writeConfigFile(cwd, { ...existing, siteUuid });
|
|
995
1082
|
}
|
|
996
1083
|
async function readConfigFile(cwd) {
|
|
997
|
-
const target =
|
|
1084
|
+
const target = import_node_path6.default.join(cwd, CONFIG_FILENAME);
|
|
998
1085
|
let raw;
|
|
999
1086
|
try {
|
|
1000
|
-
raw = await (0,
|
|
1087
|
+
raw = await (0, import_promises7.readFile)(target, "utf8");
|
|
1001
1088
|
} catch (err) {
|
|
1002
1089
|
if (err.code === "ENOENT") {
|
|
1003
1090
|
return {};
|
|
@@ -1031,15 +1118,20 @@ function readEnv() {
|
|
|
1031
1118
|
}
|
|
1032
1119
|
timeoutMs = parsed;
|
|
1033
1120
|
}
|
|
1121
|
+
const environmentRaw = process.env.PATCHSTACK_ENVIRONMENT;
|
|
1034
1122
|
return {
|
|
1035
1123
|
siteUuid: process.env.PATCHSTACK_SITE_UUID ?? void 0,
|
|
1036
1124
|
endpoint: process.env.PATCHSTACK_ENDPOINT ?? void 0,
|
|
1037
|
-
timeoutMs
|
|
1125
|
+
timeoutMs,
|
|
1126
|
+
environment: environmentRaw !== void 0 && environmentRaw.length > 0 ? environmentRaw : void 0
|
|
1038
1127
|
};
|
|
1039
1128
|
}
|
|
1040
1129
|
function isUuid(value) {
|
|
1041
1130
|
return /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(value);
|
|
1042
1131
|
}
|
|
1132
|
+
function isEnvironment(value) {
|
|
1133
|
+
return value === "production" || value === "sandbox";
|
|
1134
|
+
}
|
|
1043
1135
|
|
|
1044
1136
|
// src/index.ts
|
|
1045
1137
|
async function scanAndReport(options = {}) {
|