UNPKG

@nodesecure/mama

Version:
188 lines 6.3 kB
// Import Node.js Dependencies import fs from "node:fs/promises"; import fsSync from "node:fs"; import path from "node:path"; // Import Third-party Dependencies import { parseAuthor } from "@nodesecure/utils"; // Import Internal Dependencies import { packageJSONIntegrityHash, inspectModuleType } from "./utils/index.js"; // CONSTANTS const kNativeNpmPackages = new Set([ "node-gyp", "node-pre-gyp", "node-gyp-build", "node-addon-api" ]); /** * @see https://www.nerdycode.com/prevent-npm-executing-scripts-security/ */ export const kUnsafeNPMScripts = new Set([ "install", "preinstall", "postinstall", "preuninstall", "postuninstall" ]); export class ManifestManager { static Default = Object.freeze({ dependencies: {}, devDependencies: {}, scripts: {}, gypfile: false }); /** * Type guard to check if a ManifestManager instance has a location */ static isLocated(mama) { return typeof mama.location !== "undefined"; } metadata = Object.create(null); document; location; flags = Object.seal({ hasUnsafeScripts: false, isNative: false }); constructor(document, options = {}) { const { location } = options; this.document = Object.assign({ ...ManifestManager.Default }, structuredClone(document)); if (location) { this.location = location.endsWith("package.json") ? path.dirname(location) : location; } this.flags.isNative = [ ...this.dependencies, ...this.devDependencies ].some((pkg) => kNativeNpmPackages.has(pkg)) || this.document.gypfile; this.flags.hasUnsafeScripts = Object .keys(this.document.scripts) .some((script) => kUnsafeNPMScripts.has(script.toLowerCase())); } get moduleType() { return inspectModuleType(this.document); } get hasZeroSemver() { if (typeof this.document.version === "string") { return /^0(\.\d+)*$/ .test(this.document.version); } return false; } get nodejsImports() { return this.document.imports ?? {}; } get dependencies() { return Object.keys(this.document.dependencies); } get devDependencies() { return Object.keys(this.document.devDependencies); } get spec() { const hasBothProperties = ["name", "version"] .every((key) => key in this.document); if (this.isWorkspace && !hasBothProperties) { throw new Error("spec is not available for the given workspace"); } return `${this.document.name}@${this.document.version}`; } get author() { return parseAuthor(this.document.author); } get isWorkspace() { return "workspaces" in this.document; } get integrity() { if (this.isWorkspace) { throw new Error("integrity is not available for workspaces"); } return packageJSONIntegrityHash(this.document); } get license() { if (this.document.license) { if (typeof this.document.license === "string") { return this.document.license; } if (typeof this.document.license === "object") { return this.document.license.type ?? null; } } if (this.document.licenses) { if (Array.isArray(this.document.licenses)) { return this.document.licenses[0]?.type ?? null; } if (typeof this.document.licenses === "object") { return this.document.licenses.type ?? null; } } return null; } *getEntryFiles() { if (this.document.main) { yield this.document.main; } if (!this.document.exports) { return; } if (typeof this.document.exports === "string") { yield this.document.exports; } else { yield* this.extractNodejsExport(this.document.exports); } } *extractNodejsExport(exports) { for (const node of Object.values(exports)) { if (node === null) { continue; } if (typeof node === "string") { yield node; } else { yield* this.extractNodejsExport(node); } } } static async fromPackageJSON(locationOrManifest) { if (locationOrManifest instanceof ManifestManager) { return locationOrManifest; } if (typeof locationOrManifest !== "string") { throw new TypeError("locationOrManifest must be a string or a ManifestManager instance"); } const location = locationOrManifest; const packageLocation = location.endsWith("package.json") ? location : path.join(location, "package.json"); const packageStr = await fs.readFile(packageLocation, "utf-8"); try { const packageJSON = JSON.parse(packageStr); return new ManifestManager(packageJSON, { location }); } catch (cause) { throw new Error(`Failed to parse package.json located at: ${packageLocation}`, { cause }); } } static fromPackageJSONSync(locationOrManifest) { if (locationOrManifest instanceof ManifestManager) { return locationOrManifest; } if (typeof locationOrManifest !== "string") { throw new TypeError("locationOrManifest must be a string or a ManifestManager instance"); } const location = locationOrManifest; const packageLocation = location.endsWith("package.json") ? location : path.join(location, "package.json"); const packageStr = fsSync.readFileSync(packageLocation, "utf-8"); try { const packageJSON = JSON.parse(packageStr); return new ManifestManager(packageJSON, { location }); } catch (cause) { throw new Error(`Failed to parse package.json located at: ${packageLocation}`, { cause }); } } } //# sourceMappingURL=ManifestManager.class.js.map