@somewhere-tech/cli 0.31.21 → 0.31.22

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.
Files changed (46) hide show
  1. package/README.md +0 -59
  2. package/dist/commands/check.js +1 -1
  3. package/dist/commands/check.js.map +1 -1
  4. package/dist/commands/init.js +1 -1
  5. package/dist/commands/init.js.map +1 -1
  6. package/dist/index.js +4 -11
  7. package/dist/index.js.map +1 -1
  8. package/dist/lib/init-install.js +12 -15
  9. package/dist/lib/init-install.js.map +1 -1
  10. package/dist/lib/notify/index.js +5 -8
  11. package/dist/lib/notify/index.js.map +1 -1
  12. package/dist/lib/temp-auth.js +1 -1
  13. package/npm-shrinkwrap.json +3 -5
  14. package/package.json +2 -4
  15. package/bin/swpm.js +0 -9
  16. package/bin/swpx.js +0 -9
  17. package/dist/commands/swpx.js +0 -43
  18. package/dist/commands/swpx.js.map +0 -1
  19. package/dist/lib/notify/providers/advisory.js +0 -30
  20. package/dist/lib/notify/providers/advisory.js.map +0 -1
  21. package/dist/swpm-bin.js +0 -11
  22. package/dist/swpm-bin.js.map +0 -1
  23. package/dist/swpx/check.js +0 -80
  24. package/dist/swpx/check.js.map +0 -1
  25. package/dist/swpx/enforce.js +0 -57
  26. package/dist/swpx/enforce.js.map +0 -1
  27. package/dist/swpx/registry.js +0 -68
  28. package/dist/swpx/registry.js.map +0 -1
  29. package/dist/swpx/render.js +0 -363
  30. package/dist/swpx/render.js.map +0 -1
  31. package/dist/swpx/run-common.js +0 -24
  32. package/dist/swpx/run-common.js.map +0 -1
  33. package/dist/swpx/run-swpm.js +0 -163
  34. package/dist/swpx/run-swpm.js.map +0 -1
  35. package/dist/swpx/run-swpx.js +0 -102
  36. package/dist/swpx/run-swpx.js.map +0 -1
  37. package/dist/swpx/spawn.js +0 -30
  38. package/dist/swpx/spawn.js.map +0 -1
  39. package/dist/swpx/tree.js +0 -101
  40. package/dist/swpx/tree.js.map +0 -1
  41. package/dist/swpx/types.js +0 -14
  42. package/dist/swpx/types.js.map +0 -1
  43. package/dist/swpx/verdict-client.js +0 -165
  44. package/dist/swpx/verdict-client.js.map +0 -1
  45. package/dist/swpx-bin.js +0 -20
  46. package/dist/swpx-bin.js.map +0 -1
@@ -1,163 +0,0 @@
1
- /** `swpm <args...>` — the verdict gate in front of `npm`.
2
- *
3
- * Only install-family subcommands are gated (install/i/add/ci); everything else
4
- * (run, test, publish, …) passes straight through to npm untouched. For an
5
- * install we batch-check the resolved tree and print the summary, then:
6
- * - any BLOCKED package → stop, exit 1, don't install.
7
- * - otherwise → run the real npm install (unverified rows warn but
8
- * don't gate every install).
9
- * Couldn't verify (unreachable / unresolvable tree) → LOUD warning then fall
10
- * back to npm, OR refuse under enforce. Summary goes to stderr; npm owns stdout. */
11
- import { parseSpec } from './registry.js';
12
- import { renderTree } from './render.js';
13
- import { bindDeps } from './run-common.js';
14
- import { dim, yellow } from '../lib/output.js';
15
- import { resolveEnforce, stripEnforceFlags, loudUnavailable, refused } from './enforce.js';
16
- import { VerdictUnavailable } from './verdict-client.js';
17
- /** npm's own install aliases (including its built-in typo aliases). */
18
- const INSTALL_SUBS = new Set(['install', 'i', 'in', 'ins', 'add', 'ci', 'isntall']);
19
- function alignVerdicts(toCheck, verdicts) {
20
- const byKey = new Map(verdicts.map((v) => [`${v.package}@${v.version}`, v]));
21
- // A row the service didn't return is "unknown" → surfaced as unverified, never
22
- // silently counted as verified.
23
- return toCheck.map((t) => byKey.get(`${t.package}@${t.version}`) ?? {
24
- package: t.package,
25
- version: t.version,
26
- verdict: 'unverified',
27
- });
28
- }
29
- export async function runSwpm(args, deps = {}) {
30
- const d = bindDeps(deps);
31
- const enforce = deps.enforce ?? resolveEnforce(args);
32
- const clean = stripEnforceFlags(args);
33
- // npm accepts config flags (and a `--` terminator) BEFORE the subcommand, so the
34
- // command is the first non-flag token, not necessarily clean[0]. Keying off
35
- // clean[0] let `swpm -g install evil` / `swpm -- install evil` skip the gate
36
- // silently. (Residual: a value-flag whose value precedes the sub, e.g.
37
- // `swpm --prefix /x install`, can still hide it — needs npm's flag schema.)
38
- const subIdx = clean.findIndex((a) => !a.startsWith('-'));
39
- const sub = subIdx === -1 ? undefined : clean[subIdx];
40
- if (!sub || !INSTALL_SUBS.has(sub)) {
41
- return { exitCode: await d.runReal('npm', clean), action: 'passthrough' };
42
- }
43
- // Couldn't verify the tree → LOUD, then fall back (default) or refuse (enforce).
44
- const failOpen = async (rateLimited, cause, timedOut = false) => {
45
- if (timedOut) {
46
- d.errLog(`${yellow('⚠')} verdict pending — proceeding with npm install without waiting for a result.`);
47
- }
48
- else {
49
- loudUnavailable(d.errLog, 'this install', rateLimited, cause);
50
- }
51
- if (enforce) {
52
- refused(d.errLog, 'this install', 'npm');
53
- return { exitCode: 1, action: 'blocked' };
54
- }
55
- return { exitCode: await d.runReal('npm', clean), action: 'fallback' };
56
- };
57
- const causeOf = (err) => (err instanceof Error ? err.message : String(err));
58
- const explicit = clean.slice(subIdx + 1).filter((a) => !a.startsWith('-'));
59
- let toCheck = [];
60
- let directCount = 0;
61
- const directPackageNames = new Set();
62
- try {
63
- if (explicit.length) {
64
- toCheck = await Promise.all(explicit.map(async (a) => {
65
- const s = parseSpec(a);
66
- return { package: s.name, version: await d.resolveVersion(s.name, s.version) };
67
- }));
68
- directCount = toCheck.length;
69
- for (const pkg of toCheck)
70
- directPackageNames.add(pkg.package);
71
- }
72
- else {
73
- const tree = d.readTree(process.cwd());
74
- for (const name of tree.directNames)
75
- directPackageNames.add(name);
76
- if (tree.locked.length) {
77
- toCheck = tree.locked;
78
- const directSet = new Set(tree.directNames);
79
- directCount = tree.locked.filter((l) => directSet.has(l.package)).length;
80
- // A dep added to package.json AFTER the lockfile was written isn't in
81
- // `locked`, but `npm install` will add it — resolve + check those too, or
82
- // they'd install unchecked behind a clean "N verified" summary.
83
- const lockedNames = new Set(tree.locked.map((l) => l.package));
84
- const missing = tree.directNames.filter((n) => !lockedNames.has(n));
85
- if (missing.length) {
86
- const extra = await Promise.all(missing.map(async (name) => ({
87
- package: name,
88
- version: await d.resolveVersion(name, tree.ranges[name]),
89
- })));
90
- toCheck = [...toCheck, ...extra];
91
- directCount += extra.length;
92
- }
93
- }
94
- else if (tree.directNames.length) {
95
- toCheck = await Promise.all(tree.directNames.map(async (name) => ({
96
- package: name,
97
- version: await d.resolveVersion(name, tree.ranges[name]),
98
- })));
99
- directCount = toCheck.length;
100
- }
101
- else {
102
- d.errLog(dim('swpm: no dependencies found in package.json — running npm'));
103
- return { exitCode: await d.runReal('npm', clean), action: 'passthrough' };
104
- }
105
- }
106
- }
107
- catch (err) {
108
- return failOpen(false, causeOf(err));
109
- }
110
- let verdicts;
111
- try {
112
- verdicts = await d.getVerdictBatch(toCheck);
113
- }
114
- catch (err) {
115
- return failOpen(err instanceof VerdictUnavailable && err.rateLimited, causeOf(err), err instanceof VerdictUnavailable && err.timedOut);
116
- }
117
- const aligned = alignVerdicts(toCheck, verdicts);
118
- const pendingIndexes = aligned
119
- .map((verdict, index) => ({ verdict, index }))
120
- .filter(({ verdict }) => directPackageNames.has(verdict.package)
121
- && verdict.verdict !== 'blocked'
122
- && !verdict.summary?.trim())
123
- .map(({ index }) => index);
124
- const resolvedSummaryKeys = new Set();
125
- if (pendingIndexes.length > 0) {
126
- d.errLog(dim('Generating LLM summary…'));
127
- const refreshed = await Promise.all(pendingIndexes.map(async (index) => {
128
- const verdict = aligned[index];
129
- try {
130
- return await d.pollVerdictSummary(verdict.package, verdict.version);
131
- }
132
- catch {
133
- return null;
134
- }
135
- }));
136
- let unresolved = 0;
137
- refreshed.forEach((verdict, resultIndex) => {
138
- const alignedIndex = pendingIndexes[resultIndex];
139
- if (verdict?.summary?.trim()) {
140
- aligned[alignedIndex] = verdict;
141
- resolvedSummaryKeys.add(`${verdict.package}@${verdict.version}`);
142
- }
143
- else
144
- unresolved++;
145
- });
146
- if (unresolved > 0) {
147
- d.errLog(dim(unresolved === 1
148
- ? 'LLM summary timed out — continuing with raw verdict metadata.'
149
- : `LLM summaries timed out for ${unresolved} packages — continuing with raw verdict metadata.`));
150
- }
151
- }
152
- for (const l of renderTree(aligned, directCount, resolvedSummaryKeys))
153
- d.errLog(l);
154
- // Halt on a hard block OR any level we don't recognize as installable. Known
155
- // installable levels warn but proceed (unverified/suspicious); an unrecognized
156
- // or future-harsher level (e.g. "quarantined") must NOT install behind a warn.
157
- const INSTALLABLE = new Set(['verified', 'unverified', 'suspicious']);
158
- if (aligned.some((v) => !INSTALLABLE.has(v.verdict))) {
159
- return { exitCode: 1, action: 'blocked' };
160
- }
161
- return { exitCode: await d.runReal('npm', clean), action: 'ran' };
162
- }
163
- //# sourceMappingURL=run-swpm.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"run-swpm.js","sourceRoot":"","sources":["../../src/swpx/run-swpm.ts"],"names":[],"mappings":"AAAA;;;;;;;;;qFASqF;AAErF,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAgB,MAAM,iBAAiB,CAAC;AACzD,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC3F,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAGzD,uEAAuE;AACvE,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC,CAAC,SAAS,EAAE,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC;AAYpF,SAAS,aAAa,CAAC,OAAiB,EAAE,QAAmB;IAC3D,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7E,+EAA+E;IAC/E,gCAAgC;IAChC,OAAO,OAAO,CAAC,GAAG,CAChB,CAAC,CAAC,EAAE,EAAE,CACJ,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC,IAAI;QACxC,OAAO,EAAE,CAAC,CAAC,OAAO;QAClB,OAAO,EAAE,CAAC,CAAC,OAAO;QAClB,OAAO,EAAE,YAAqB;KAC/B,CACJ,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,IAAc,EAAE,OAAgB,EAAE;IAC9D,MAAM,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;IACzB,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,cAAc,CAAC,IAAI,CAAC,CAAC;IACrD,MAAM,KAAK,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;IAEtC,iFAAiF;IACjF,4EAA4E;IAC5E,6EAA6E;IAC7E,uEAAuE;IACvE,4EAA4E;IAC5E,MAAM,MAAM,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;IAC1D,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACtD,IAAI,CAAC,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;QACnC,OAAO,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,MAAM,EAAE,aAAa,EAAE,CAAC;IAC5E,CAAC;IAED,iFAAiF;IACjF,MAAM,QAAQ,GAAG,KAAK,EACpB,WAAoB,EACpB,KAAc,EACd,QAAQ,GAAG,KAAK,EACM,EAAE;QACxB,IAAI,QAAQ,EAAE,CAAC;YACb,CAAC,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,8EAA8E,CAAC,CAAC;QACzG,CAAC;aAAM,CAAC;YACN,eAAe,CAAC,CAAC,CAAC,MAAM,EAAE,cAAc,EAAE,WAAW,EAAE,KAAK,CAAC,CAAC;QAChE,CAAC;QACD,IAAI,OAAO,EAAE,CAAC;YACZ,OAAO,CAAC,CAAC,CAAC,MAAM,EAAE,cAAc,EAAE,KAAK,CAAC,CAAC;YACzC,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;QAC5C,CAAC;QACD,OAAO,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;IACzE,CAAC,CAAC;IACF,MAAM,OAAO,GAAG,CAAC,GAAY,EAAE,EAAE,CAAC,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;IAErF,MAAM,QAAQ,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;IAC3E,IAAI,OAAO,GAAa,EAAE,CAAC;IAC3B,IAAI,WAAW,GAAG,CAAC,CAAC;IACpB,MAAM,kBAAkB,GAAG,IAAI,GAAG,EAAU,CAAC;IAC7C,IAAI,CAAC;QACH,IAAI,QAAQ,CAAC,MAAM,EAAE,CAAC;YACpB,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,CACzB,QAAQ,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE;gBACvB,MAAM,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;gBACvB,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;YACjF,CAAC,CAAC,CACH,CAAC;YACF,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC;YAC7B,KAAK,MAAM,GAAG,IAAI,OAAO;gBAAE,kBAAkB,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACjE,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,GAAG,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;YACvC,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,WAAW;gBAAE,kBAAkB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAClE,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;gBACvB,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC;gBACtB,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;gBAC5C,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC;gBACzE,sEAAsE;gBACtE,0EAA0E;gBAC1E,gEAAgE;gBAChE,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;gBAC/D,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;gBACpE,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;oBACnB,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,GAAG,CAC7B,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC;wBAC3B,OAAO,EAAE,IAAI;wBACb,OAAO,EAAE,MAAM,CAAC,CAAC,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;qBACzD,CAAC,CAAC,CACJ,CAAC;oBACF,OAAO,GAAG,CAAC,GAAG,OAAO,EAAE,GAAG,KAAK,CAAC,CAAC;oBACjC,WAAW,IAAI,KAAK,CAAC,MAAM,CAAC;gBAC9B,CAAC;YACH,CAAC;iBAAM,IAAI,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC;gBACnC,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,CACzB,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC;oBACpC,OAAO,EAAE,IAAI;oBACb,OAAO,EAAE,MAAM,CAAC,CAAC,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;iBACzD,CAAC,CAAC,CACJ,CAAC;gBACF,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC;YAC/B,CAAC;iBAAM,CAAC;gBACN,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,2DAA2D,CAAC,CAAC,CAAC;gBAC3E,OAAO,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,MAAM,EAAE,aAAa,EAAE,CAAC;YAC5E,CAAC;QACH,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;IACvC,CAAC;IAED,IAAI,QAAmB,CAAC;IACxB,IAAI,CAAC;QACH,QAAQ,GAAG,MAAM,CAAC,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;IAC9C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,QAAQ,CACb,GAAG,YAAY,kBAAkB,IAAI,GAAG,CAAC,WAAW,EACpD,OAAO,CAAC,GAAG,CAAC,EACZ,GAAG,YAAY,kBAAkB,IAAI,GAAG,CAAC,QAAQ,CAClD,CAAC;IACJ,CAAC;IAED,MAAM,OAAO,GAAG,aAAa,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IACjD,MAAM,cAAc,GAAG,OAAO;SAC3B,GAAG,CAAC,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;SAC7C,MAAM,CAAC,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CACtB,kBAAkB,CAAC,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC;WACpC,OAAO,CAAC,OAAO,KAAK,SAAS;WAC7B,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC;SAC7B,GAAG,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC;IAC7B,MAAM,mBAAmB,GAAG,IAAI,GAAG,EAAU,CAAC;IAC9C,IAAI,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC9B,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC,CAAC;QACzC,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC,GAAG,CACjC,cAAc,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;YACjC,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;YAC/B,IAAI,CAAC;gBACH,OAAO,MAAM,CAAC,CAAC,kBAAkB,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;YACtE,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,IAAI,CAAC;YACd,CAAC;QACH,CAAC,CAAC,CACH,CAAC;QACF,IAAI,UAAU,GAAG,CAAC,CAAC;QACnB,SAAS,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,WAAW,EAAE,EAAE;YACzC,MAAM,YAAY,GAAG,cAAc,CAAC,WAAW,CAAC,CAAC;YACjD,IAAI,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,CAAC;gBAC7B,OAAO,CAAC,YAAY,CAAC,GAAG,OAAO,CAAC;gBAChC,mBAAmB,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,OAAO,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;YACnE,CAAC;;gBAAM,UAAU,EAAE,CAAC;QACtB,CAAC,CAAC,CAAC;QACH,IAAI,UAAU,GAAG,CAAC,EAAE,CAAC;YACnB,CAAC,CAAC,MAAM,CAAC,GAAG,CACV,UAAU,KAAK,CAAC;gBACd,CAAC,CAAC,+DAA+D;gBACjE,CAAC,CAAC,+BAA+B,UAAU,mDAAmD,CACjG,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,UAAU,CAAC,OAAO,EAAE,WAAW,EAAE,mBAAmB,CAAC;QAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IAEnF,6EAA6E;IAC7E,+EAA+E;IAC/E,+EAA+E;IAC/E,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,CAAC,UAAU,EAAE,YAAY,EAAE,YAAY,CAAC,CAAC,CAAC;IACtE,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC;QACrD,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;IAC5C,CAAC;IACD,OAAO,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;AACpE,CAAC"}
@@ -1,102 +0,0 @@
1
- /** `swpx <package> [args...]` — the verdict gate in front of `npx`.
2
- *
3
- * resolve → verdict → act:
4
- * verified → print the green one-liner, delegate to real npx.
5
- * unverified/suspicious → print the evidence block, STOP (exit 1). The user's
6
- * documented override is to run `npx` directly, per
7
- * the landing page ("your choice, not ours") — so we
8
- * deliberately do not prompt or take a --yes flag
9
- * (which would also collide with npx -y).
10
- * blocked → print the red block, hard refuse (exit 1, no run).
11
- * can't resolve / verdict unreachable → fall back to npx unchecked. We are a
12
- * gate, not a wall: our outage must not stop the user.
13
- *
14
- * All verdict messaging goes to STDERR so swpx is transparent on stdout — the
15
- * executed program owns stdout. */
16
- import { parseSpec } from './registry.js';
17
- import { decide, renderVerdict } from './render.js';
18
- import { bindDeps } from './run-common.js';
19
- import { resolveEnforce, stripEnforceFlags, loudUnavailable, refused } from './enforce.js';
20
- import { VerdictUnavailable } from './verdict-client.js';
21
- import { dim } from '../lib/output.js';
22
- /** The value of npx's -p/--package flag, in either `--package X` / `-p X` or
23
- * `--package=X` form — the package npx actually installs. Returns the first such
24
- * value (multiple -p flags are rare; noted as a residual). null if absent. */
25
- function packageFlagValue(args) {
26
- for (let i = 0; i < args.length; i++) {
27
- const a = args[i];
28
- if (a === '--package' || a === '-p')
29
- return args[i + 1] ?? null;
30
- if (a.startsWith('--package='))
31
- return a.slice('--package='.length);
32
- if (a.startsWith('-p='))
33
- return a.slice('-p='.length);
34
- }
35
- return null;
36
- }
37
- export async function runSwpx(args, deps = {}) {
38
- const d = bindDeps(deps);
39
- const enforce = deps.enforce ?? resolveEnforce(args);
40
- const passthrough = stripEnforceFlags(args);
41
- // npx's -p/--package names the package that actually gets installed and run; the
42
- // positional is just the binary to invoke from it (`npx -p typescript tsc`). So
43
- // grade the --package value when present — otherwise `swpx --package=evil helper`
44
- // would grade `helper`, print a green "verified", and let npx fetch+run `evil`.
45
- // Falls back to the first non-flag arg (so `swpx -y create-next-app` still works).
46
- const pkgArg = packageFlagValue(passthrough) ?? passthrough.find((a) => !a.startsWith('-'));
47
- if (!pkgArg) {
48
- d.errLog('Usage: swpx <package> [args...]');
49
- return { exitCode: 1, action: 'stopped' };
50
- }
51
- const spec = parseSpec(pkgArg);
52
- // Couldn't verify → LOUD warning (never silent), then fall back (default) OR
53
- // refuse (enforce / fail-closed).
54
- const failOpen = async (rateLimited, cause) => {
55
- loudUnavailable(d.errLog, spec.name, rateLimited, cause);
56
- if (enforce) {
57
- refused(d.errLog, spec.name, 'npx');
58
- return { exitCode: 1, action: 'blocked' };
59
- }
60
- return { exitCode: await d.runReal('npx', passthrough), action: 'fallback' };
61
- };
62
- const causeOf = (err) => (err instanceof Error ? err.message : String(err));
63
- let version;
64
- try {
65
- version = await d.resolveVersion(spec.name, spec.version);
66
- }
67
- catch (err) {
68
- return failOpen(false, causeOf(err));
69
- }
70
- let verdict;
71
- try {
72
- verdict = await d.getVerdict(spec.name, version);
73
- }
74
- catch (err) {
75
- return failOpen(err instanceof VerdictUnavailable && err.rateLimited, causeOf(err));
76
- }
77
- if (verdict.verdict !== 'blocked' && !verdict.summary?.trim()) {
78
- d.errLog(dim('Generating LLM summary…'));
79
- let enriched = null;
80
- try {
81
- enriched = await d.pollVerdictSummary(spec.name, version);
82
- }
83
- catch {
84
- // Summary generation is presentation-only. Keep the mechanical verdict.
85
- }
86
- if (enriched?.summary?.trim()) {
87
- verdict = enriched;
88
- }
89
- else {
90
- d.errLog(dim('LLM summary timed out — continuing with raw verdict metadata.'));
91
- }
92
- }
93
- const action = decide(verdict);
94
- for (const l of renderVerdict(verdict))
95
- d.errLog(l);
96
- if (action === 'run') {
97
- return { exitCode: await d.runReal('npx', passthrough), action: 'ran' };
98
- }
99
- // unverified/suspicious and blocked both stop swpx; only the exit reason differs.
100
- return { exitCode: 1, action: action === 'block' ? 'blocked' : 'stopped' };
101
- }
102
- //# sourceMappingURL=run-swpx.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"run-swpx.js","sourceRoot":"","sources":["../../src/swpx/run-swpx.ts"],"names":[],"mappings":"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"}
@@ -1,30 +0,0 @@
1
- /** Shell out to the REAL npx / npm. swpx/swpm are wrappers, never replacements:
2
- * once a verdict says "go", the genuine tool runs with the user's exact args,
3
- * inheriting stdio so its output is untouched (we keep our own messaging on
4
- * stderr). The child's exit code becomes ours. A launch failure (tool not on
5
- * PATH) resolves to 127 rather than throwing — the caller already printed the
6
- * verdict; a missing npm is the user's environment, not a swpx error. */
7
- import { spawn } from 'node:child_process';
8
- import { dim } from '../lib/output.js';
9
- export function runReal(cmd, args) {
10
- // SWPX_DRY_RUN: show the decision + what WOULD run, without executing. Useful
11
- // for "what would swpx do?" and for testing the gate end-to-end offline.
12
- if (process.env.SWPX_DRY_RUN) {
13
- console.error(dim(`swpx: [dry-run] would run: ${cmd} ${args.join(' ')}`));
14
- return Promise.resolve(0);
15
- }
16
- return new Promise((resolve) => {
17
- const child = spawn(cmd, args, {
18
- stdio: 'inherit',
19
- // On Windows npx/npm are .cmd shims that need a shell; on POSIX we spawn
20
- // the binary directly (no shell → no quoting/injection surface).
21
- shell: process.platform === 'win32',
22
- });
23
- child.on('error', (err) => {
24
- console.error(dim(`swpx: failed to launch ${cmd} — ${err.message}`));
25
- resolve(127);
26
- });
27
- child.on('exit', (code, signal) => resolve(signal ? 1 : code ?? 0));
28
- });
29
- }
30
- //# sourceMappingURL=spawn.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"spawn.js","sourceRoot":"","sources":["../../src/swpx/spawn.ts"],"names":[],"mappings":"AAAA;;;;;0EAK0E;AAE1E,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AAEvC,MAAM,UAAU,OAAO,CAAC,GAAkB,EAAE,IAAc;IACxD,8EAA8E;IAC9E,yEAAyE;IACzE,IAAI,OAAO,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;QAC7B,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,8BAA8B,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;QAC1E,OAAO,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IAC5B,CAAC;IACD,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,EAAE,IAAI,EAAE;YAC7B,KAAK,EAAE,SAAS;YAChB,yEAAyE;YACzE,iEAAiE;YACjE,KAAK,EAAE,OAAO,CAAC,QAAQ,KAAK,OAAO;SACpC,CAAC,CAAC;QACH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;YACxB,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,0BAA0B,GAAG,MAAM,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;YACrE,OAAO,CAAC,GAAG,CAAC,CAAC;QACf,CAAC,CAAC,CAAC;QACH,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC;IACtE,CAAC,CAAC,CAAC;AACL,CAAC"}
package/dist/swpx/tree.js DELETED
@@ -1,101 +0,0 @@
1
- /** Resolve a project's dependency tree for `swpm install`.
2
- *
3
- * When a lockfile is present it IS the resolved tree — the exact versions npm
4
- * would install — so we read it directly (no registry round-trips, no guessing
5
- * ranges). Without a lockfile we fall back to the direct deps in package.json
6
- * and let the caller resolve their ranges. Parsing is split from fs reads so
7
- * the lockfile/manifest parsers are unit-tested against fixture strings. */
8
- import { existsSync, readFileSync } from 'node:fs';
9
- import { join } from 'node:path';
10
- export function parsePackageJsonDeps(pkgJson) {
11
- let obj;
12
- try {
13
- obj = JSON.parse(pkgJson);
14
- }
15
- catch {
16
- return { directNames: [], ranges: {} };
17
- }
18
- const ranges = {};
19
- const o = obj;
20
- for (const field of ['dependencies', 'devDependencies', 'optionalDependencies']) {
21
- const d = o?.[field];
22
- if (d && typeof d === 'object') {
23
- for (const [k, v] of Object.entries(d)) {
24
- if (typeof v === 'string')
25
- ranges[k] = v;
26
- }
27
- }
28
- }
29
- return { directNames: Object.keys(ranges), ranges };
30
- }
31
- /** Extract every concrete package@version from a package-lock.json /
32
- * npm-shrinkwrap.json string. Handles lockfile v2/v3 (`packages` keyed by
33
- * node_modules paths) and the older v1 (`dependencies` tree). Deduped. */
34
- export function parseLockfile(lock) {
35
- let obj;
36
- try {
37
- obj = JSON.parse(lock);
38
- }
39
- catch {
40
- return [];
41
- }
42
- const out = [];
43
- const seen = new Set();
44
- const add = (name, version) => {
45
- if (!name || typeof version !== 'string')
46
- return;
47
- const id = `${name}@${version}`;
48
- if (seen.has(id))
49
- return;
50
- seen.add(id);
51
- out.push({ package: name, version });
52
- };
53
- const packages = obj.packages;
54
- if (packages && typeof packages === 'object') {
55
- for (const [key, val] of Object.entries(packages)) {
56
- if (!key)
57
- continue; // "" is the root project
58
- const idx = key.lastIndexOf('node_modules/');
59
- if (idx === -1)
60
- continue;
61
- if (val?.link)
62
- continue; // workspace symlink, not a real install
63
- add(key.slice(idx + 'node_modules/'.length), val?.version);
64
- }
65
- return out;
66
- }
67
- // lockfile v1: recursive `dependencies` tree.
68
- const walk = (deps) => {
69
- if (!deps || typeof deps !== 'object')
70
- return;
71
- for (const [name, info] of Object.entries(deps)) {
72
- add(name, info?.version);
73
- walk(info?.dependencies);
74
- }
75
- };
76
- walk(obj.dependencies);
77
- return out;
78
- }
79
- /** Read package.json + the first lockfile we find in `dir`. Missing files yield
80
- * an empty-ish tree rather than throwing — the caller decides what to do with
81
- * no deps. */
82
- export function readTree(dir) {
83
- let directNames = [];
84
- let ranges = {};
85
- const pkgPath = join(dir, 'package.json');
86
- if (existsSync(pkgPath)) {
87
- const parsed = parsePackageJsonDeps(readFileSync(pkgPath, 'utf-8'));
88
- directNames = parsed.directNames;
89
- ranges = parsed.ranges;
90
- }
91
- let locked = [];
92
- for (const lockName of ['package-lock.json', 'npm-shrinkwrap.json']) {
93
- const lockPath = join(dir, lockName);
94
- if (existsSync(lockPath)) {
95
- locked = parseLockfile(readFileSync(lockPath, 'utf-8'));
96
- break;
97
- }
98
- }
99
- return { directNames, ranges, locked };
100
- }
101
- //# sourceMappingURL=tree.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"tree.js","sourceRoot":"","sources":["../../src/swpx/tree.ts"],"names":[],"mappings":"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"}
@@ -1,14 +0,0 @@
1
- /** Shared types for the swpx / swpm verdict layer.
2
- *
3
- * The verdict API lives on the `npm` platform project (npm.somewhere.tech),
4
- * NOT the /v1 control plane. It is unauthenticated (free, no login) — the CLI
5
- * hits it with a plain fetch, independent of `somewhere login`. See
6
- * verdict-client.ts.
7
- *
8
- * The `Verdict` shape mirrors the D1 `verdicts` row (tsk_f30faf55) plus the
9
- * live MAL advisory check, which is NOT cached (a version can be retroactively
10
- * flagged). The `--json` output is a stable PROJECTION of this (toJsonVerdict)
11
- * — that projection is the public contract shown on npm.somewhere.tech, so it
12
- * is intentionally narrower than the internal row. */
13
- export {};
14
- //# sourceMappingURL=types.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/swpx/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;uDAWuD"}
@@ -1,165 +0,0 @@
1
- /** Client for the verdict API hosted on the `npm` platform project.
2
- *
3
- * This is NOT the /v1 control plane and NOT the runner — it's the public,
4
- * unauthenticated verdict service at npm.somewhere.tech (FAQ: "Free, no
5
- * login"). So this client deliberately does not touch ApiClient or the stored
6
- * developer key. Override the host for staging/tests via SWPX_VERDICT_URL.
7
- *
8
- * Reachability is a product guarantee, inverted: if the verdict API is down,
9
- * the user must still get normal npm behaviour ("a gate, not a wall"). So every
10
- * failure here raises VerdictUnavailable and the command layer falls back to
11
- * the real npx/npm. We never block on our own outage. */
12
- const VERDICT_BASE = process.env.SWPX_VERDICT_URL?.replace(/\/$/, '') || 'https://npm.somewhere.tech';
13
- /** Budget for one verdict lookup. It sits in front of every `npx`, so it must
14
- * fail to fallback rather than stall — but 4s was too tight for the COLD path
15
- * (fresh DNS/TLS from the client + a cold worker + a first-time uncached compute),
16
- * which spuriously tripped the fail-open banner on the very first call while every
17
- * warm call after was instant. 15s comfortably covers a cold uncached lookup;
18
- * override with SWPX_VERDICT_TIMEOUT_MS (e.g. lower it for strict fail-fast in CI). */
19
- export const verdictTimeoutMs = Number(process.env.SWPX_VERDICT_TIMEOUT_MS) || 15_000;
20
- /** Summary generation is best-effort, but a missing narrative must never leave
21
- * the user staring at a blank decision screen forever. Keep one overall budget
22
- * across every enrich poll; env overrides make staging and tests tunable. */
23
- const SUMMARY_POLL_TIMEOUT_MS = Number(process.env.SWPX_SUMMARY_TIMEOUT_MS) || 20_000;
24
- const SUMMARY_POLL_INTERVAL_MS = Number(process.env.SWPX_SUMMARY_POLL_INTERVAL_MS) || 1_500;
25
- const defaultFetch = (url, init) => fetch(url, init);
26
- /** Raised whenever the verdict couldn't be obtained — network error, timeout,
27
- * non-2xx, or unparseable body. The command layer treats it as "fall back to
28
- * the real tool", never as "block". */
29
- export class VerdictUnavailable extends Error {
30
- /** True when the service answered 429 — a throttle, not an outage/tampering. */
31
- rateLimited;
32
- /** True when the client deadline elapsed before the service answered. */
33
- timedOut;
34
- constructor(message, rateLimited = false, timedOut = false) {
35
- super(message);
36
- this.name = 'VerdictUnavailable';
37
- this.rateLimited = rateLimited;
38
- this.timedOut = timedOut;
39
- }
40
- }
41
- /** Accept either a bare verdict object or a `{ ok, data }` envelope. */
42
- function unwrap(body) {
43
- if (body && typeof body === 'object' && 'ok' in body) {
44
- const env = body;
45
- if (env.ok === true)
46
- return env.data;
47
- throw new VerdictUnavailable(env.message || env.error || 'verdict API returned ok:false');
48
- }
49
- return body;
50
- }
51
- function timeoutSignal(timeoutMs = verdictTimeoutMs) {
52
- try {
53
- return AbortSignal.timeout(timeoutMs);
54
- }
55
- catch {
56
- return undefined; // very old runtime — let the request run without our timeout
57
- }
58
- }
59
- async function requestVerdict(name, version, fetchImpl, enrich, timeoutMs = verdictTimeoutMs) {
60
- const suffix = enrich ? '?enrich=1' : '';
61
- const url = `${VERDICT_BASE}/api/verdict/${encodeURIComponent(name)}/${encodeURIComponent(version)}${suffix}`;
62
- let res;
63
- try {
64
- res = await fetchImpl(url, {
65
- headers: {
66
- Accept: 'application/json',
67
- ...(enrich ? { 'Cache-Control': 'no-cache' } : {}),
68
- },
69
- signal: timeoutSignal(timeoutMs),
70
- });
71
- }
72
- catch (err) {
73
- const timedOut = err instanceof Error && (err.name === 'TimeoutError' || err.name === 'AbortError');
74
- throw new VerdictUnavailable(err instanceof Error ? err.message : String(err), false, timedOut);
75
- }
76
- if (!res.ok)
77
- throw new VerdictUnavailable(`verdict API returned ${res.status}`, res.status === 429);
78
- let body;
79
- try {
80
- body = await res.json();
81
- }
82
- catch {
83
- throw new VerdictUnavailable('verdict API returned a non-JSON body');
84
- }
85
- const v = unwrap(body);
86
- if (!v || typeof v !== 'object' || typeof v.verdict !== 'string') {
87
- throw new VerdictUnavailable('verdict API returned an unexpected shape');
88
- }
89
- // Trust the caller's resolved coordinates over whatever the row echoes back.
90
- return { ...v, package: name, version };
91
- }
92
- /** Look up one package@version. Throws VerdictUnavailable on any failure. */
93
- export async function getVerdict(name, version, fetchImpl = defaultFetch) {
94
- return requestVerdict(name, version, fetchImpl, false);
95
- }
96
- /** Ask the verdict backend to enrich a mechanical verdict, then keep polling
97
- * until its LLM narrative appears or the single overall budget expires.
98
- * Returns null on timeout/unavailability so callers can continue with the raw
99
- * verdict and metadata; summary generation never changes fail-open behavior. */
100
- export async function pollVerdictSummary(name, version, fetchImpl = defaultFetch, options = {}) {
101
- const timeoutMs = Math.max(1, options.timeoutMs ?? SUMMARY_POLL_TIMEOUT_MS);
102
- const intervalMs = Math.max(1, options.intervalMs ?? SUMMARY_POLL_INTERVAL_MS);
103
- const now = options.now ?? Date.now;
104
- const sleep = options.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
105
- const deadline = now() + timeoutMs;
106
- while (now() < deadline) {
107
- const remaining = Math.max(1, deadline - now());
108
- try {
109
- const verdict = await requestVerdict(name, version, fetchImpl, true, Math.min(verdictTimeoutMs, remaining));
110
- if (typeof verdict.summary === 'string' && verdict.summary.trim())
111
- return verdict;
112
- }
113
- catch (err) {
114
- // A throttle will not clear inside this short budget. Other transient
115
- // failures get another attempt, still bounded by the same deadline.
116
- if (err instanceof VerdictUnavailable && err.rateLimited)
117
- return null;
118
- }
119
- const waitMs = Math.min(intervalMs, Math.max(0, deadline - now()));
120
- if (waitMs > 0)
121
- await sleep(waitMs);
122
- }
123
- return null;
124
- }
125
- /** Batch-check a resolved tree. Throws VerdictUnavailable on any failure so the
126
- * caller can fall back to a plain `npm install`. The returned array is aligned
127
- * to the input order; any row the service omits is dropped (caller treats a
128
- * missing row as "unknown", not "verified"). */
129
- export async function getVerdictBatch(pkgs, fetchImpl = defaultFetch) {
130
- if (pkgs.length === 0)
131
- return [];
132
- const url = `${VERDICT_BASE}/api/verdict/batch`;
133
- let res;
134
- try {
135
- res = await fetchImpl(url, {
136
- method: 'POST',
137
- headers: { Accept: 'application/json', 'Content-Type': 'application/json' },
138
- body: JSON.stringify({ packages: pkgs }),
139
- signal: timeoutSignal(),
140
- });
141
- }
142
- catch (err) {
143
- const timedOut = err instanceof Error && (err.name === 'TimeoutError' || err.name === 'AbortError');
144
- throw new VerdictUnavailable(err instanceof Error ? err.message : String(err), false, timedOut);
145
- }
146
- if (!res.ok)
147
- throw new VerdictUnavailable(`verdict API returned ${res.status}`, res.status === 429);
148
- let body;
149
- try {
150
- body = await res.json();
151
- }
152
- catch {
153
- throw new VerdictUnavailable('verdict API returned a non-JSON body');
154
- }
155
- const data = unwrap(body);
156
- const results = Array.isArray(data)
157
- ? data
158
- : data?.results;
159
- if (!Array.isArray(results)) {
160
- throw new VerdictUnavailable('verdict API batch returned an unexpected shape');
161
- }
162
- return results.filter((v) => !!v && typeof v === 'object' && typeof v.verdict === 'string');
163
- }
164
- export const verdictBaseUrl = VERDICT_BASE;
165
- //# sourceMappingURL=verdict-client.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"verdict-client.js","sourceRoot":"","sources":["../../src/swpx/verdict-client.ts"],"names":[],"mappings":"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"}