snyk-nodejs-lockfile-parser
Version:
Generate a dep tree given a lockfile
94 lines • 4.4 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.parseDescriptor = parseDescriptor;
exports.parseRange = parseRange;
exports.stringifyIdent = stringifyIdent;
/*
* Ported from Yarn Berry's @yarnpkg/core@4.9.0 structUtils:
* https://github.com/yarnpkg/berry/blob/%40yarnpkg/core/4.9.0/packages/yarnpkg-core/sources/structUtils.ts
*
* Only the three helpers this library uses are ported (parseDescriptor,
* parseRange and stringifyIdent), preserving the upstream regexes, thrown
* error messages and return shapes. The identHash/descriptorHash fields are
* omitted from the returned descriptors as no caller reads them, and
* parseDescriptor only supports upstream's loose mode as no caller uses
* strict.
*
* BSD 2-Clause License
*
* Copyright (c) 2016-present, Yarn Contributors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
const querystring = require("querystring");
const DESCRIPTOR_REGEX_LOOSE = /^(?:@([^/]+?)\/)?([^@/]+?)(?:@(.+))?$/;
const DESCRIPTOR_RANGE_UNSPECIFIED = 'unknown';
// Parses a descriptor string (eg. `lodash@^1.0.0`) into its scope, name and
// range. The range is optional and falls back to the `unknown` sentinel,
// matching upstream's loose mode. The parameter is named `string` to mirror
// the upstream source exactly.
function parseDescriptor(string) {
const match = string.match(DESCRIPTOR_REGEX_LOOSE);
if (!match) {
throw new Error(`Invalid descriptor (${string})`);
}
const [, scope, name, range] = match;
if (range === DESCRIPTOR_RANGE_UNSPECIFIED) {
throw new Error(`Invalid range (${string})`);
}
const realScope = typeof scope !== 'undefined' ? scope : null;
if (realScope?.startsWith('@')) {
throw new Error(`Invalid scope: don't prefix it with '@'`);
}
const realRange = typeof range !== 'undefined' ? range : DESCRIPTOR_RANGE_UNSPECIFIED;
return { scope: realScope, name, range: realRange };
}
const RANGE_REGEX = /^([^#:]*:)?((?:(?!::)[^#])*)(?:#((?:(?!::).)*))?(?:::(.*))?$/;
// Parses a range into its constituents. Ranges typically follow these forms,
// with both `protocol` and `bindings` being optionals:
//
// <protocol>:<selector>::<bindings>
// <protocol>:<source>#<selector>::<bindings>
function parseRange(range) {
const match = range.match(RANGE_REGEX);
if (match === null) {
throw new Error(`Invalid range (${range})`);
}
const protocol = typeof match[1] !== 'undefined' ? match[1] : null;
const source = typeof match[3] !== 'undefined' ? decodeURIComponent(match[2]) : null;
const selector = typeof match[3] !== 'undefined'
? decodeURIComponent(match[3])
: decodeURIComponent(match[2]);
const params = typeof match[4] !== 'undefined' ? querystring.parse(match[4]) : null;
return { protocol, source, selector, params };
}
// Returns a string from an ident (eg. `@types/lodash`).
function stringifyIdent(ident) {
if (ident.scope) {
return `@${ident.scope}/${ident.name}`;
}
else {
return `${ident.name}`;
}
}
//# sourceMappingURL=yarn-structs.js.map