@westbayberry/dg 1.0.16 → 1.0.17
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/dist/index.mjs +40 -97
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -114,6 +114,12 @@ function parseConfig(argv) {
|
|
|
114
114
|
const noConfig = values["no-config"];
|
|
115
115
|
const dgrc = noConfig ? {} : loadDgrc();
|
|
116
116
|
const apiKey = dgrc.apiKey ?? "";
|
|
117
|
+
if (!apiKey) {
|
|
118
|
+
process.stderr.write(
|
|
119
|
+
"Error: Not logged in. Run `dg login` to authenticate.\n"
|
|
120
|
+
);
|
|
121
|
+
process.exit(1);
|
|
122
|
+
}
|
|
117
123
|
const modeRaw = values.mode ?? process.env.DG_MODE ?? dgrc.mode ?? "warn";
|
|
118
124
|
if (!["block", "warn", "off"].includes(modeRaw)) {
|
|
119
125
|
process.stderr.write(
|
|
@@ -125,10 +131,7 @@ function parseConfig(argv) {
|
|
|
125
131
|
const allowlistRaw = values.allowlist ?? process.env.DG_ALLOWLIST ?? "";
|
|
126
132
|
const blockThreshold = Number(values["block-threshold"] ?? dgrc.blockThreshold ?? "70");
|
|
127
133
|
const warnThreshold = Number(values["warn-threshold"] ?? dgrc.warnThreshold ?? "60");
|
|
128
|
-
|
|
129
|
-
if (!apiKey) {
|
|
130
|
-
maxPackages = Math.min(maxPackages, 50);
|
|
131
|
-
}
|
|
134
|
+
const maxPackages = Number(values["max-packages"] ?? dgrc.maxPackages ?? "200");
|
|
132
135
|
const debug = values.debug || process.env.DG_DEBUG === "1";
|
|
133
136
|
if (isNaN(blockThreshold) || blockThreshold < 0 || blockThreshold > 100) {
|
|
134
137
|
process.stderr.write("Error: --block-threshold must be a number between 0 and 100\n");
|
|
@@ -38914,35 +38917,15 @@ async function callAnalyzeAPI(packages, config, onProgress) {
|
|
|
38914
38917
|
for (let i = 0; i < packages.length; i += BATCH_SIZE) {
|
|
38915
38918
|
batches.push(packages.slice(i, i + BATCH_SIZE));
|
|
38916
38919
|
}
|
|
38917
|
-
const
|
|
38918
|
-
const results = new Array(batches.length);
|
|
38920
|
+
const results = [];
|
|
38919
38921
|
let completed = 0;
|
|
38920
|
-
|
|
38921
|
-
|
|
38922
|
-
|
|
38923
|
-
results[idx] = result;
|
|
38924
|
-
completed += batches[idx].length;
|
|
38922
|
+
for (const batch of batches) {
|
|
38923
|
+
const result = await callBatchWithRetry(batch, config);
|
|
38924
|
+
completed += batch.length;
|
|
38925
38925
|
if (onProgress) {
|
|
38926
|
-
onProgress(completed, packages.length,
|
|
38927
|
-
}
|
|
38928
|
-
}
|
|
38929
|
-
const inFlight = /* @__PURE__ */ new Set();
|
|
38930
|
-
while (nextIdx < batches.length && inFlight.size < MAX_CONCURRENT_BATCHES) {
|
|
38931
|
-
const idx = nextIdx++;
|
|
38932
|
-
const p = runBatch(idx).then(() => {
|
|
38933
|
-
inFlight.delete(p);
|
|
38934
|
-
});
|
|
38935
|
-
inFlight.add(p);
|
|
38936
|
-
}
|
|
38937
|
-
while (inFlight.size > 0) {
|
|
38938
|
-
await Promise.race(inFlight);
|
|
38939
|
-
while (nextIdx < batches.length && inFlight.size < MAX_CONCURRENT_BATCHES) {
|
|
38940
|
-
const idx = nextIdx++;
|
|
38941
|
-
const p = runBatch(idx).then(() => {
|
|
38942
|
-
inFlight.delete(p);
|
|
38943
|
-
});
|
|
38944
|
-
inFlight.add(p);
|
|
38926
|
+
onProgress(completed, packages.length, batch.map((p) => p.name));
|
|
38945
38927
|
}
|
|
38928
|
+
results.push(result);
|
|
38946
38929
|
}
|
|
38947
38930
|
return mergeResponses(results, config);
|
|
38948
38931
|
}
|
|
@@ -39001,16 +38984,13 @@ async function callAnalyzeBatch(packages, config) {
|
|
|
39001
38984
|
const timeoutId = setTimeout(() => controller.abort(), 12e4);
|
|
39002
38985
|
let response;
|
|
39003
38986
|
try {
|
|
39004
|
-
const headers = {
|
|
39005
|
-
"Content-Type": "application/json",
|
|
39006
|
-
"User-Agent": "dependency-guardian-cli/1.0.0"
|
|
39007
|
-
};
|
|
39008
|
-
if (config.apiKey) {
|
|
39009
|
-
headers["Authorization"] = `Bearer ${config.apiKey}`;
|
|
39010
|
-
}
|
|
39011
38987
|
response = await fetch(url, {
|
|
39012
38988
|
method: "POST",
|
|
39013
|
-
headers
|
|
38989
|
+
headers: {
|
|
38990
|
+
"Content-Type": "application/json",
|
|
38991
|
+
Authorization: `Bearer ${config.apiKey}`,
|
|
38992
|
+
"User-Agent": "dependency-guardian-cli/1.0.0"
|
|
38993
|
+
},
|
|
39014
38994
|
body: JSON.stringify(payload),
|
|
39015
38995
|
signal: controller.signal
|
|
39016
38996
|
});
|
|
@@ -39032,14 +39012,6 @@ async function callAnalyzeBatch(packages, config) {
|
|
|
39032
39012
|
);
|
|
39033
39013
|
}
|
|
39034
39014
|
if (response.status === 429) {
|
|
39035
|
-
const body = await response.json().catch(() => ({}));
|
|
39036
|
-
if (body.anonymous) {
|
|
39037
|
-
throw new APIError(
|
|
39038
|
-
"Anonymous scan limit reached. Run `dg login` for 200 free scans/month.",
|
|
39039
|
-
429,
|
|
39040
|
-
""
|
|
39041
|
-
);
|
|
39042
|
-
}
|
|
39043
39015
|
throw new APIError(
|
|
39044
39016
|
"Rate limit exceeded. Upgrade your plan at https://westbayberry.com/pricing",
|
|
39045
39017
|
429,
|
|
@@ -39092,16 +39064,13 @@ async function callPyPIBatch(packages, config) {
|
|
|
39092
39064
|
const timeoutId = setTimeout(() => controller.abort(), 12e4);
|
|
39093
39065
|
let response;
|
|
39094
39066
|
try {
|
|
39095
|
-
const headers = {
|
|
39096
|
-
"Content-Type": "application/json",
|
|
39097
|
-
"User-Agent": "dependency-guardian-cli/1.0.0"
|
|
39098
|
-
};
|
|
39099
|
-
if (config.apiKey) {
|
|
39100
|
-
headers["Authorization"] = `Bearer ${config.apiKey}`;
|
|
39101
|
-
}
|
|
39102
39067
|
response = await fetch(url, {
|
|
39103
39068
|
method: "POST",
|
|
39104
|
-
headers
|
|
39069
|
+
headers: {
|
|
39070
|
+
"Content-Type": "application/json",
|
|
39071
|
+
Authorization: `Bearer ${config.apiKey}`,
|
|
39072
|
+
"User-Agent": "dependency-guardian-cli/1.0.0"
|
|
39073
|
+
},
|
|
39105
39074
|
body: JSON.stringify(payload),
|
|
39106
39075
|
signal: controller.signal
|
|
39107
39076
|
});
|
|
@@ -39123,14 +39092,6 @@ async function callPyPIBatch(packages, config) {
|
|
|
39123
39092
|
);
|
|
39124
39093
|
}
|
|
39125
39094
|
if (response.status === 429) {
|
|
39126
|
-
const body = await response.json().catch(() => ({}));
|
|
39127
|
-
if (body.anonymous) {
|
|
39128
|
-
throw new APIError(
|
|
39129
|
-
"Anonymous scan limit reached. Run `dg login` for 200 free scans/month.",
|
|
39130
|
-
429,
|
|
39131
|
-
""
|
|
39132
|
-
);
|
|
39133
|
-
}
|
|
39134
39095
|
throw new APIError(
|
|
39135
39096
|
"Rate limit exceeded. Upgrade your plan at https://westbayberry.com/pricing",
|
|
39136
39097
|
429,
|
|
@@ -39155,7 +39116,7 @@ var init_api = __esm({
|
|
|
39155
39116
|
this.name = "APIError";
|
|
39156
39117
|
}
|
|
39157
39118
|
};
|
|
39158
|
-
BATCH_SIZE =
|
|
39119
|
+
BATCH_SIZE = 15;
|
|
39159
39120
|
MAX_RETRIES = 2;
|
|
39160
39121
|
RETRY_DELAY_MS = 5e3;
|
|
39161
39122
|
}
|
|
@@ -39794,7 +39755,7 @@ function truncate(s, max) {
|
|
|
39794
39755
|
function groupPackages(packages) {
|
|
39795
39756
|
const map = /* @__PURE__ */ new Map();
|
|
39796
39757
|
for (const pkg of packages) {
|
|
39797
|
-
const fingerprint = pkg.findings.length === 0 ? `__clean_${pkg.score}` : pkg.findings.map((f) => `${f.
|
|
39758
|
+
const fingerprint = pkg.findings.length === 0 ? `__clean_${pkg.score}` : pkg.findings.map((f) => `${f.id}:${f.severity}`).sort().join("|") + `|score:${pkg.score}`;
|
|
39798
39759
|
const group = map.get(fingerprint) ?? [];
|
|
39799
39760
|
group.push(pkg);
|
|
39800
39761
|
map.set(fingerprint, group);
|
|
@@ -39876,7 +39837,7 @@ function renderResultStatic(result, config) {
|
|
|
39876
39837
|
const sevLabel = SEVERITY_LABELS[finding.severity] ?? "INFO";
|
|
39877
39838
|
const colorFn = severityColor(finding.severity);
|
|
39878
39839
|
lines.push(
|
|
39879
|
-
` ${colorFn(pad(sevLabel, 10))}${finding.
|
|
39840
|
+
` ${colorFn(pad(sevLabel, 10))}${finding.id} \u2014 ${finding.title}`
|
|
39880
39841
|
);
|
|
39881
39842
|
const evidenceLimit = 3;
|
|
39882
39843
|
for (let i = 0; i < Math.min(finding.evidence.length, evidenceLimit); i++) {
|
|
@@ -39983,11 +39944,6 @@ async function runStatic(config) {
|
|
|
39983
39944
|
);
|
|
39984
39945
|
const output = renderResultStatic(result, config);
|
|
39985
39946
|
process.stdout.write(output + "\n");
|
|
39986
|
-
if (!config.apiKey && !config.json) {
|
|
39987
|
-
process.stderr.write(
|
|
39988
|
-
"\n" + import_chalk4.default.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n") + import_chalk4.default.cyan(" Want this on every PR? ") + "Run " + import_chalk4.default.white("dg login") + import_chalk4.default.dim(" \u2192 free tier, 200 scans/month\n") + import_chalk4.default.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n")
|
|
39989
|
-
);
|
|
39990
|
-
}
|
|
39991
39947
|
if (result.action === "block" && config.mode === "block") {
|
|
39992
39948
|
process.exit(2);
|
|
39993
39949
|
} else if (result.action === "block" || result.action === "warn") {
|
|
@@ -40106,11 +40062,6 @@ async function scanAndInstallStatic(resolved, parsed, config) {
|
|
|
40106
40062
|
}
|
|
40107
40063
|
const output = renderResultStatic(result, config);
|
|
40108
40064
|
process.stdout.write(output + "\n");
|
|
40109
|
-
if (!config.apiKey) {
|
|
40110
|
-
process.stderr.write(
|
|
40111
|
-
"\n" + import_chalk4.default.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n") + import_chalk4.default.cyan(" Want this on every PR? ") + "Run " + import_chalk4.default.white("dg login") + import_chalk4.default.dim(" \u2192 free tier, 200 scans/month\n") + import_chalk4.default.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n")
|
|
40112
|
-
);
|
|
40113
|
-
}
|
|
40114
40065
|
if (result.action === "warn") {
|
|
40115
40066
|
process.stderr.write(
|
|
40116
40067
|
import_chalk4.default.yellow(" Warnings detected. Proceeding with install.\n\n")
|
|
@@ -40651,7 +40602,7 @@ var init_DurationLine = __esm({
|
|
|
40651
40602
|
function groupPackages2(packages) {
|
|
40652
40603
|
const map = /* @__PURE__ */ new Map();
|
|
40653
40604
|
for (const pkg of packages) {
|
|
40654
|
-
const fingerprint = pkg.findings.length === 0 ? `__clean_${pkg.score}` : pkg.findings.map((f) => `${f.
|
|
40605
|
+
const fingerprint = pkg.findings.length === 0 ? `__clean_${pkg.score}` : pkg.findings.map((f) => `${f.id}:${f.severity}`).sort().join("|") + `|score:${pkg.score}`;
|
|
40655
40606
|
const group = map.get(fingerprint) ?? [];
|
|
40656
40607
|
group.push(pkg);
|
|
40657
40608
|
map.set(fingerprint, group);
|
|
@@ -40771,7 +40722,7 @@ var init_ResultsView = __esm({
|
|
|
40771
40722
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { children: [
|
|
40772
40723
|
" ",
|
|
40773
40724
|
colorFn(pad2(sevLabel, 10)),
|
|
40774
|
-
finding.
|
|
40725
|
+
finding.id,
|
|
40775
40726
|
" ",
|
|
40776
40727
|
"\u2014",
|
|
40777
40728
|
" ",
|
|
@@ -40786,7 +40737,7 @@ var init_ResultsView = __esm({
|
|
|
40786
40737
|
import_chalk6.default.dim(`... and ${overflow} more`)
|
|
40787
40738
|
] }),
|
|
40788
40739
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { children: " " })
|
|
40789
|
-
] }, `${finding.
|
|
40740
|
+
] }, `${finding.id}-${idx}`);
|
|
40790
40741
|
}),
|
|
40791
40742
|
safeVersion && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { children: [
|
|
40792
40743
|
" ",
|
|
@@ -41288,7 +41239,7 @@ var init_useTerminalSize = __esm({
|
|
|
41288
41239
|
function groupPackages3(packages) {
|
|
41289
41240
|
const map = /* @__PURE__ */ new Map();
|
|
41290
41241
|
for (const pkg of packages) {
|
|
41291
|
-
const fingerprint = pkg.findings.length === 0 ? `__clean_${pkg.score}` : pkg.findings.map((f) => `${f.
|
|
41242
|
+
const fingerprint = pkg.findings.length === 0 ? `__clean_${pkg.score}` : pkg.findings.map((f) => `${f.id}:${f.severity}`).sort().join("|") + `|score:${pkg.score}`;
|
|
41292
41243
|
const group = map.get(fingerprint) ?? [];
|
|
41293
41244
|
group.push(pkg);
|
|
41294
41245
|
map.set(fingerprint, group);
|
|
@@ -41407,8 +41358,7 @@ var init_InteractiveResultsView = __esm({
|
|
|
41407
41358
|
const viewRef = (0, import_react30.useRef)(view);
|
|
41408
41359
|
viewRef.current = view;
|
|
41409
41360
|
const { rows: termRows, cols: termCols } = useTerminalSize();
|
|
41410
|
-
const
|
|
41411
|
-
const availableRows = Math.max(5, termRows - chromeHeight);
|
|
41361
|
+
const availableRows = Math.max(5, termRows - FIXED_CHROME);
|
|
41412
41362
|
const innerWidth = Math.max(40, termCols - 6);
|
|
41413
41363
|
const getLevel = (idx) => {
|
|
41414
41364
|
return view.expandedIndex === idx ? view.expandLevel : null;
|
|
@@ -41496,9 +41446,6 @@ var init_InteractiveResultsView = __esm({
|
|
|
41496
41446
|
dispatchView({ type: "EXPAND", expandedIndex: newExpIdx, expandLevel: newExpLvl, viewport: newVp });
|
|
41497
41447
|
} else if (input === "e") {
|
|
41498
41448
|
if (expIdx === cursor && expLvl === "detail") {
|
|
41499
|
-
const newVp = adjustViewport(cursor, cursor, "summary", vpStart);
|
|
41500
|
-
dispatchView({ type: "EXPAND", expandedIndex: cursor, expandLevel: "summary", viewport: newVp });
|
|
41501
|
-
} else if (expIdx === cursor && expLvl === "summary") {
|
|
41502
41449
|
const newVp = adjustViewport(cursor, null, null, vpStart);
|
|
41503
41450
|
dispatchView({ type: "EXPAND", expandedIndex: null, expandLevel: null, viewport: newVp });
|
|
41504
41451
|
} else {
|
|
@@ -41620,12 +41567,6 @@ var init_InteractiveResultsView = __esm({
|
|
|
41620
41567
|
]
|
|
41621
41568
|
}
|
|
41622
41569
|
),
|
|
41623
|
-
!config.apiKey && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Box_default, { paddingLeft: 1, paddingRight: 1, width: "100%", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(Text, { children: [
|
|
41624
|
-
import_chalk10.default.cyan("Want this on every PR?"),
|
|
41625
|
-
" Run ",
|
|
41626
|
-
import_chalk10.default.white("dg login"),
|
|
41627
|
-
import_chalk10.default.dim(" \u2192 free tier, 200 scans/month")
|
|
41628
|
-
] }) }),
|
|
41629
41570
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(Text, { dimColor: true, children: [
|
|
41630
41571
|
" ",
|
|
41631
41572
|
groups.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_jsx_runtime10.Fragment, { children: [
|
|
@@ -41678,8 +41619,8 @@ var init_InteractiveResultsView = __esm({
|
|
|
41678
41619
|
" ",
|
|
41679
41620
|
sevColor(pad3(sevLabel, 4)),
|
|
41680
41621
|
" ",
|
|
41681
|
-
import_chalk10.default.dim(f.
|
|
41682
|
-
] }, `${f.
|
|
41622
|
+
import_chalk10.default.dim(f.id)
|
|
41623
|
+
] }, `${f.id}-${idx}`)
|
|
41683
41624
|
);
|
|
41684
41625
|
}
|
|
41685
41626
|
if (hasAffects) {
|
|
@@ -41717,15 +41658,15 @@ var init_InteractiveResultsView = __esm({
|
|
|
41717
41658
|
" ",
|
|
41718
41659
|
sevColor(pad3(sevLabel, 4)),
|
|
41719
41660
|
" ",
|
|
41720
|
-
import_chalk10.default.bold(finding.
|
|
41721
|
-
] }, `${finding.
|
|
41661
|
+
import_chalk10.default.bold(finding.id)
|
|
41662
|
+
] }, `${finding.id}-${idx}-badge`)
|
|
41722
41663
|
);
|
|
41723
41664
|
allLines.push(
|
|
41724
41665
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(Text, { dimColor: true, children: [
|
|
41725
41666
|
continuation,
|
|
41726
41667
|
" ",
|
|
41727
41668
|
finding.title
|
|
41728
|
-
] }, `${finding.
|
|
41669
|
+
] }, `${finding.id}-${idx}-title`)
|
|
41729
41670
|
);
|
|
41730
41671
|
for (let i = 0; i < evidenceSlice.length; i++) {
|
|
41731
41672
|
allLines.push(
|
|
@@ -41735,7 +41676,7 @@ var init_InteractiveResultsView = __esm({
|
|
|
41735
41676
|
import_chalk10.default.dim("\u203A"),
|
|
41736
41677
|
" ",
|
|
41737
41678
|
truncate3(evidenceSlice[i], evidenceWidth)
|
|
41738
|
-
] }, `${finding.
|
|
41679
|
+
] }, `${finding.id}-${idx}-ev-${i}`)
|
|
41739
41680
|
);
|
|
41740
41681
|
}
|
|
41741
41682
|
if (overflow > 0) {
|
|
@@ -41744,7 +41685,7 @@ var init_InteractiveResultsView = __esm({
|
|
|
41744
41685
|
continuation,
|
|
41745
41686
|
" ",
|
|
41746
41687
|
import_chalk10.default.dim(`+${overflow} more`)
|
|
41747
|
-
] }, `${finding.
|
|
41688
|
+
] }, `${finding.id}-${idx}-overflow`)
|
|
41748
41689
|
);
|
|
41749
41690
|
}
|
|
41750
41691
|
}
|
|
@@ -41858,8 +41799,10 @@ var init_App2 = __esm({
|
|
|
41858
41799
|
(0, import_react32.useEffect)(() => {
|
|
41859
41800
|
if (!process.stdout.isTTY) return;
|
|
41860
41801
|
process.stdout.write("\x1B[?1049h");
|
|
41802
|
+
process.stdout.write("\x1B[?1003h");
|
|
41861
41803
|
process.stdout.write("\x1B[2J\x1B[H");
|
|
41862
41804
|
return () => {
|
|
41805
|
+
process.stdout.write("\x1B[?1003l");
|
|
41863
41806
|
process.stdout.write("\x1B[?1049l");
|
|
41864
41807
|
process.stdout.write("\x1B[?25h");
|
|
41865
41808
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@westbayberry/dg",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.17",
|
|
4
4
|
"description": "Supply chain security scanner for npm and Python dependencies — detects malicious packages, typosquatting, dependency confusion, and 26+ attack patterns",
|
|
5
5
|
"bin": {
|
|
6
6
|
"dependency-guardian": "dist/index.mjs",
|