sonda 0.12.0 → 0.13.0
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/CHANGELOG.md +17 -0
- package/dist/index.d.ts +4 -1
- package/dist/index.html +1 -1
- package/dist/index.js +127 -5
- package/package.json +17 -2
package/dist/index.js
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import { styleText } from "util";
|
|
2
2
|
import { access, mkdir, readFile, readdir, writeFile } from "fs/promises";
|
|
3
|
-
import { basename, dirname, extname, format, join, parse, posix, relative, resolve, win32 } from "path";
|
|
3
|
+
import { basename, dirname, extname, format, isAbsolute, join, parse, posix, relative, resolve, win32 } from "path";
|
|
4
4
|
import { isBuiltin } from "module";
|
|
5
|
-
import open from "open";
|
|
5
|
+
import open from "tiny-open";
|
|
6
6
|
import { fileURLToPath } from "url";
|
|
7
7
|
import { brotliCompressSync, gzipSync } from "zlib";
|
|
8
|
-
import { readFileSync } from "fs";
|
|
9
|
-
import { loadCodeAndMap } from "load-source-map";
|
|
8
|
+
import { existsSync, readFileSync, statSync } from "fs";
|
|
10
9
|
import remapping from "@jridgewell/remapping";
|
|
11
10
|
//#region src/config.ts
|
|
12
11
|
var Config = class Config {
|
|
@@ -169,7 +168,7 @@ function hasIgnoredExtension(name) {
|
|
|
169
168
|
}
|
|
170
169
|
//#endregion
|
|
171
170
|
//#region package.json
|
|
172
|
-
var version = "0.
|
|
171
|
+
var version = "0.13.0";
|
|
173
172
|
//#endregion
|
|
174
173
|
//#region src/report/formatters/Formatter.ts
|
|
175
174
|
var Formatter = class {
|
|
@@ -230,6 +229,108 @@ var JsonFormatter = class extends Formatter {
|
|
|
230
229
|
}
|
|
231
230
|
};
|
|
232
231
|
//#endregion
|
|
232
|
+
//#region ../load-source-map/dist/index.js
|
|
233
|
+
/**
|
|
234
|
+
* Strip any JSON XSSI avoidance prefix from the string (as documented in the source maps specification),
|
|
235
|
+
* and parses the string as JSON.
|
|
236
|
+
*
|
|
237
|
+
* https://github.com/mozilla/source-map/blob/3cb92cc3b73bfab27c146bae4ef2bc09dbb4e5ed/lib/util.js#L162-L164
|
|
238
|
+
*/
|
|
239
|
+
function parseSourceMapInput(str) {
|
|
240
|
+
return JSON.parse(str.replace(/^\)]}'[^\n]*\n/, ""));
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
sourceMappingURL=data:application/json;charset=utf-8;base64,data
|
|
244
|
+
sourceMappingURL=data:application/json;base64,data
|
|
245
|
+
sourceMappingURL=data:application/json;uri,data
|
|
246
|
+
sourceMappingURL=map-file-comment.css.map
|
|
247
|
+
sourceMappingURL=map-file-comment.css.map?query=value
|
|
248
|
+
*/
|
|
249
|
+
const sourceMappingRegExp = /[@#]\s*sourceMappingURL=(\S+)\b/g;
|
|
250
|
+
/**
|
|
251
|
+
* Checks if the given path is a file.
|
|
252
|
+
*/
|
|
253
|
+
function isFile(path) {
|
|
254
|
+
try {
|
|
255
|
+
return statSync(path).isFile();
|
|
256
|
+
} catch {
|
|
257
|
+
return false;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Default path normalizer that resolves the path relative to the source root.
|
|
262
|
+
*/
|
|
263
|
+
function defaultPathNormalizer(path, sourceRoot) {
|
|
264
|
+
return isAbsolute(path) ? path : resolve(sourceRoot, path);
|
|
265
|
+
}
|
|
266
|
+
function loadCodeAndMap(codePath, sourcesPathNormalizer) {
|
|
267
|
+
if (!isFile(codePath)) return null;
|
|
268
|
+
const code = readFileSync(codePath, "utf-8");
|
|
269
|
+
const maybeMap = loadMap(codePath, code);
|
|
270
|
+
if (!maybeMap) return { code };
|
|
271
|
+
const { map, mapPath } = maybeMap;
|
|
272
|
+
const sourceRoot = resolve(dirname(mapPath), map.sourceRoot ?? ".");
|
|
273
|
+
const normalizer = sourcesPathNormalizer || defaultPathNormalizer;
|
|
274
|
+
map.sources = map.sources.map((source) => source && normalizer(source, sourceRoot));
|
|
275
|
+
map.sourcesContent = loadMissingSourcesContent(map);
|
|
276
|
+
delete map.sourceRoot;
|
|
277
|
+
return {
|
|
278
|
+
code,
|
|
279
|
+
map
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
function loadMap(codePath, code) {
|
|
283
|
+
/**
|
|
284
|
+
* Because in most cases the source map has the same name as the code file,
|
|
285
|
+
* we can try to append `.map` to the code path and check if the file exists.
|
|
286
|
+
*/
|
|
287
|
+
try {
|
|
288
|
+
const possibleMapPath = codePath + ".map";
|
|
289
|
+
return {
|
|
290
|
+
map: parseSourceMapInput(readFileSync(possibleMapPath, "utf-8")),
|
|
291
|
+
mapPath: possibleMapPath
|
|
292
|
+
};
|
|
293
|
+
} catch {}
|
|
294
|
+
/**
|
|
295
|
+
* If the source map is not found by file name, we can try to extract it from the code.
|
|
296
|
+
* The path to the source map is usually in a comment at the end of the file, but it can
|
|
297
|
+
* also be inlined in the code itself.
|
|
298
|
+
*/
|
|
299
|
+
const extractedComment = code.includes("sourceMappingURL") && Array.from(code.matchAll(sourceMappingRegExp)).at(-1);
|
|
300
|
+
if (!extractedComment || !extractedComment.length) return null;
|
|
301
|
+
const sourceMappingURL = extractedComment[1];
|
|
302
|
+
if (sourceMappingURL.startsWith("data:")) return {
|
|
303
|
+
map: parseSourceMapInput(parseDataUrl(sourceMappingURL)),
|
|
304
|
+
mapPath: codePath
|
|
305
|
+
};
|
|
306
|
+
const sourceMapFilename = new URL(sourceMappingURL, "file://").pathname;
|
|
307
|
+
const mapPath = join(dirname(codePath), sourceMapFilename);
|
|
308
|
+
if (!existsSync(mapPath)) return null;
|
|
309
|
+
return {
|
|
310
|
+
map: parseSourceMapInput(readFileSync(mapPath, "utf-8")),
|
|
311
|
+
mapPath
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
function parseDataUrl(url) {
|
|
315
|
+
const [prefix, payload] = url.split(",");
|
|
316
|
+
const encoding = prefix.split(";").at(-1);
|
|
317
|
+
switch (encoding) {
|
|
318
|
+
case "base64": return Buffer.from(payload, "base64").toString();
|
|
319
|
+
case "uri": return decodeURIComponent(payload);
|
|
320
|
+
default: throw new Error("Unsupported source map encoding: " + encoding);
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* Loop through the sources and try to load missing `sourcesContent` from the file system.
|
|
325
|
+
*/
|
|
326
|
+
function loadMissingSourcesContent(map) {
|
|
327
|
+
return map.sources.map((source, index) => {
|
|
328
|
+
if (map.sourcesContent?.[index]) return map.sourcesContent[index];
|
|
329
|
+
if (source && existsSync(source)) return readFileSync(source, "utf-8");
|
|
330
|
+
return null;
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
//#endregion
|
|
233
334
|
//#region src/report/processors/sourcemap.ts
|
|
234
335
|
const UNASSIGNED = "[unassigned]";
|
|
235
336
|
function getBytesPerSource(code, map, assetSizes, config) {
|
|
@@ -586,10 +687,16 @@ function SondaRollupPlugin(userOptions = {}) {
|
|
|
586
687
|
const options = new Config(userOptions, { integration: "rollup" });
|
|
587
688
|
if (!options.enabled) return { name: "sonda/rollup" };
|
|
588
689
|
const report = new Report(options);
|
|
690
|
+
const dynamicImportSources = /* @__PURE__ */ new Set();
|
|
589
691
|
return {
|
|
590
692
|
name: "sonda/rollup",
|
|
693
|
+
resolveDynamicImport(specifier, importer) {
|
|
694
|
+
if (typeof specifier === "string") dynamicImportSources.add(connectionKey(importer, specifier));
|
|
695
|
+
return null;
|
|
696
|
+
},
|
|
591
697
|
async resolveId(source, importer, options) {
|
|
592
698
|
if (!importer) return;
|
|
699
|
+
if (dynamicImportSources.has(connectionKey(importer, source))) return;
|
|
593
700
|
const resolved = await this.resolve(source, importer, {
|
|
594
701
|
...options,
|
|
595
702
|
skipSelf: true
|
|
@@ -612,6 +719,18 @@ function SondaRollupPlugin(userOptions = {}) {
|
|
|
612
719
|
uncompressed: module.code ? Buffer.byteLength(module.code) : 0
|
|
613
720
|
});
|
|
614
721
|
},
|
|
722
|
+
buildEnd() {
|
|
723
|
+
for (const id of this.getModuleIds()) {
|
|
724
|
+
const module = this.getModuleInfo(id);
|
|
725
|
+
if (!module) continue;
|
|
726
|
+
for (const target of module.dynamicallyImportedIds) report.addConnection({
|
|
727
|
+
kind: "dynamic-import",
|
|
728
|
+
source: normalizePath(module.id),
|
|
729
|
+
target: normalizePath(target),
|
|
730
|
+
original: null
|
|
731
|
+
});
|
|
732
|
+
}
|
|
733
|
+
},
|
|
615
734
|
async writeBundle({ dir, file }, bundle) {
|
|
616
735
|
const outputDir = resolve(process.cwd(), dir ?? dirname(file));
|
|
617
736
|
for (const [path, asset] of Object.entries(bundle)) report.addAsset(resolve(outputDir, path), asset.type === "chunk" && asset.facadeModuleId ? [asset.facadeModuleId] : void 0);
|
|
@@ -622,6 +741,9 @@ function SondaRollupPlugin(userOptions = {}) {
|
|
|
622
741
|
}
|
|
623
742
|
};
|
|
624
743
|
}
|
|
744
|
+
function connectionKey(importer, source) {
|
|
745
|
+
return `${importer}\0${source}`;
|
|
746
|
+
}
|
|
625
747
|
function getModuleFormat(name, module) {
|
|
626
748
|
if (getTypeByName(name) !== "script") return "other";
|
|
627
749
|
const ext = extname(module.id);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sonda",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
4
4
|
"description": "Universal bundle analyzer and visualizer that works with most popular bundlers and frameworks.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"analyzer",
|
|
@@ -91,9 +91,24 @@
|
|
|
91
91
|
},
|
|
92
92
|
"dependencies": {
|
|
93
93
|
"@jridgewell/remapping": "^2.3.5",
|
|
94
|
-
"open": "^
|
|
94
|
+
"tiny-open": "^1.3.0"
|
|
95
95
|
},
|
|
96
96
|
"engines": {
|
|
97
97
|
"node": ">=22.12"
|
|
98
|
+
},
|
|
99
|
+
"compatiblePackages": {
|
|
100
|
+
"schemaVersion": 1,
|
|
101
|
+
"vite": {
|
|
102
|
+
"type": "compatible",
|
|
103
|
+
"versions": "^7.0.0 || ^8.0.0"
|
|
104
|
+
},
|
|
105
|
+
"rollup": {
|
|
106
|
+
"type": "compatible",
|
|
107
|
+
"versions": "^4.0.0"
|
|
108
|
+
},
|
|
109
|
+
"rolldown": {
|
|
110
|
+
"type": "compatible",
|
|
111
|
+
"versions": "^1.0.0"
|
|
112
|
+
}
|
|
98
113
|
}
|
|
99
114
|
}
|