@nodesecure/tarball
Version:
NodeSecure tarball scanner
99 lines • 3.49 kB
JavaScript
// Import Node.js Dependencies
import path from "node:path";
// Import Third-party Dependencies
import { EntryFilesAnalyser, AstAnalyser, DefaultCollectableSet } from "@nodesecure/js-x-ray";
import {} from "@nodesecure/mama";
export class SourceCodeReport {
#isConsumed = false;
path = "NONE";
warnings = [];
dependencies = Object.create(null);
minified = [];
flags = {
hasExternalCapacity: false
};
get consumed() {
return this.#isConsumed;
}
push(report) {
this.#isConsumed = true;
this.warnings.push(...report.warnings.map((warning) => {
return { ...warning, file: report.file };
}));
if (report.ok) {
if (report.flags.has("fetch")) {
this.flags.hasExternalCapacity = true;
}
report.flags.has("is-minified") && this.minified.push(report.file);
}
}
}
export class SourceCodeScanner {
#astAnalyser;
#initNewReport;
manifest;
constructor(manifest, options = {}) {
const { reportInitiator = () => new SourceCodeReport(), astAnalyser = new AstAnalyser({
collectables: [
new DefaultCollectableSet("dependency")
]
}) } = options;
this.manifest = manifest;
this.#astAnalyser = astAnalyser;
this.#initNewReport = reportInitiator;
}
async iterate(entries) {
const report = this.#initNewReport();
if (entries.manifest.length === 0 &&
entries.javascript.length === 0) {
return report;
}
return entries.manifest.length > 0 ?
this.#iterateWithEntries(report, entries) :
this.#iterateAll(report, entries.javascript);
}
async #iterateWithEntries(report, entries) {
report.path = "EntryFileAnalyser";
const { location } = this.manifest;
const efa = new EntryFilesAnalyser({
astAnalyzer: this.#astAnalyser,
rootPath: location,
ignoreENOENT: true
});
const absoluteEntryFiles = entries.manifest.map((filePath) => path.join(location, filePath));
for await (const fileReport of efa.analyse(absoluteEntryFiles, {
metadata: {
spec: this.manifest.spec
},
fileMetadata: (absoluteFile) => {
const relativeFile = path.relative(location, absoluteFile);
return { relativeFile };
}
})) {
report.push(fileReport);
}
return report.consumed ?
report :
this.#iterateAll(report, entries.javascript);
}
async #iterateAll(report, sourceFiles) {
if (sourceFiles.length === 0) {
return report;
}
report.path = report.path === "EntryFileAnalyser" ? "Both" : "All";
const { location, document: { name: packageName } } = this.manifest;
await Promise.allSettled(sourceFiles.map(async (relativeFile) => {
const filePath = path.join(location, relativeFile);
const fileReport = await this.#astAnalyser.analyseFile(filePath, {
packageName,
metadata: {
spec: this.manifest.spec,
relativeFile
}
});
report.push({ ...fileReport, file: relativeFile });
}));
return report;
}
}
//# sourceMappingURL=SourceCodeScanner.class.js.map