codec-js-manifest: Make npm dependency pattern parsing more resillient and add tests - fixes
ADD
packages/@romejs/codec-js-manifest/__rtests__/__rsnapshots__/dependencies.ts.rsnap
+{
+ "can parse npm dependency patterns": "npm {\n name: 'foo'\n range: undefined\n}",
+ "can parse npm dependency patterns: 1": "npm {\n name: '@foo/bar'\n range: undefined\n}",
+ "can parse npm dependency patterns: 2": "npm {\n name: 'foo'\n range: AbsoluteVersion {\n build: Array []\n major: 1\n minor: 0\n patch: 0\n prerelease: Array []\n loc: Object {\n filename: undefined\n end: Object {\n column: 5\n index: 5\n line: 1\n }\n start: Object {\n column: 1\n index: 0\n line: 1\n }\n }\n }\n}",
+ "can parse npm dependency patterns: 3": "npm {\n name: '@foo/bar'\n range: AbsoluteVersion {\n build: Array []\n major: 1\n minor: 0\n patch: 0\n prerelease: Array []\n loc: Object {\n filename: undefined\n end: Object {\n column: 5\n index: 5\n line: 1\n }\n start: Object {\n column: 1\n index: 0\n line: 1\n }\n }\n }\n}"
+}
\ No newline at end of file

ADD
packages/@romejs/codec-js-manifest/__rtests__/dependencies.ts
+/**
+ * Copyright (c) Facebook, Inc. and its affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+import test from '@romejs/test';
+import {parseDependencyPattern} from '../dependencies';
+import {consumeUnknown} from '@romejs/consume';
+
+test('can parse npm dependency patterns', t => {
+ t.snapshot(parseDependencyPattern(consumeUnknown('npm:foo'), false));
+ t.snapshot(parseDependencyPattern(consumeUnknown('npm:@foo/bar'), false));
+ t.snapshot(parseDependencyPattern(consumeUnknown('npm:foo@1.0.0'), false));
+ t.snapshot(
+ parseDependencyPattern(consumeUnknown('npm:@foo/bar@1.0.0'), false),
+ );
+});

MODIFY
packages/@romejs/codec-js-manifest/dependencies.ts
packages/@romejs/codec-js-manifest/dependencies.ts
@@ -298,17 +298,64 @@ type NpmPattern = {
range: undefined | SemverRangeNode;
};
-function parseNpm(pattern: string, consumer: Consumer): NpmPattern {
+function parseNpm(
+ pattern: string,
+ consumer: Consumer,
+ loose: boolean,
+): NpmPattern {
// Prune prefix
let offset = NPM_PREFIX.length;
pattern = pattern.slice(NPM_PREFIX.length);
+ if (pattern === '') {
+ consumer.unexpected('Missing rest of pattern');
+ return {
+ type: 'npm',
+ name: 'unknown',
+ range: undefined,
+ };
+ }
+
// Split and verify count
- const [name, rangeRaw, ...parts] = pattern.split('@');
+ const parts = pattern.split('@');
+ let nameRaw = '';
+ let rangeRaw: undefined | string;
+
+ // Org signifier
+ if (parts[0] === '') {
+ nameRaw += '@';
+ parts.shift();
+ }
+
+ // Name - We know there'll be at least two due to the empty string conditional
+ nameRaw = String(parts.shift());
+
+ // Range
+ rangeRaw = parts.shift();
+
if (parts.length > 0) {
consumer.unexpected('Too many @ signs');
}
+ const name = normalizeName({
+ name: nameRaw,
+ loose,
+ unexpected({message, at, start, end, advice}) {
+ consumer.unexpected(message, {
+ advice,
+ at,
+ loc:
+ start === undefined
+ ? undefined
+ : consumer.getLocationRange(
+ add(start, offset),
+ end === undefined ? undefined : add(end, offset),
+ 'inner-value',
+ ),
+ });
+ },
+ });
+
// Increase offset passed name
offset += name.length;
offset++;
@@ -317,7 +364,7 @@ function parseNpm(pattern: string, consumer: Consumer): NpmPattern {
if (rangeRaw !== undefined) {
range = tryParseWithOptionalOffsetPosition(
{
- loose: false,
+ loose,
path: consumer.path,
input: rangeRaw,
},
@@ -382,7 +429,7 @@ export function parseDependencyPattern(
}
if (pattern.startsWith(NPM_PREFIX)) {
- return parseNpm(pattern, consumer);
+ return parseNpm(pattern, consumer, loose);
}
if (pattern.startsWith(LINK_PREFIX)) {

codec-js-manifest: Make npm dependency pattern parsing more resillient and add tests - fixes #79