Skip to content

Commit

Permalink
[bugfix]: removing whitespace from malformed version ranges (#37)
Browse files Browse the repository at this point in the history
* replace replaceAll with global regex replace

* better whitespace regex, account for AND ranges

* make regex better

* package-lock version bump

* one last regex improvement

* fix comment

* one more comment fix

* one last filter

* actually probably the last regex version

* implement invalid range handling

* update README
  • Loading branch information
kindoflew authored Mar 3, 2023
1 parent 0a9458f commit 5961124
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 24 deletions.
11 changes: 10 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ And it returns a promise that resolves to:
type DepngnReturn = Record<string, CompatData>;

interface CompatData {
compatible: boolean | undefined;
compatible: boolean | 'invalid' | undefined;
range: string;
}
```
Expand All @@ -95,6 +95,15 @@ const generateReport = async () => {
};
```

There's also a chance there *is* an `engines` field specified in the package, but the range is invalid in some way. Since RegEx for SemVer can be tricky, we return the folling, if that's the case:

```javascript
{
compatible: 'invalid',
range: '1 .2 . 0not-a-valid-range'
}
```

## Supported Package Managers

For now, this package supports `npm` and `yarn`. If you want support for
Expand Down
27 changes: 18 additions & 9 deletions src/cli/reporter/html.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
import { writeFile } from '../../utils';
import { CompatData } from '../../types';

export async function createHtml(compatData: Record<string, CompatData>, version: string, path: string = 'compat.html') {
export async function createHtml(
compatData: Record<string, CompatData>,
version: string,
path: string = 'compat.html'
) {
const compatDataKeys = Object.keys(compatData);
const classGreen = "green";
const classRed = "red";
const classYellow = "yellow";
const classGreen = 'green';
const classRed = 'red';
const classYellow = 'yellow';

const style = `
h1{
Expand All @@ -32,21 +36,26 @@ export async function createHtml(compatData: Record<string, CompatData>, version
}
.${classYellow}{
color: #ce8d02;
}`
}`;

const tableData = compatDataKeys
.map((key) => {
const compatible = compatData[key].compatible;
const compatibleClass = compatible === undefined ? classYellow : compatible ? classGreen : classRed;
const compatibleClass =
compatible === undefined || compatible === 'invalid'
? classYellow
: compatible
? classGreen
: classRed;
return `
<tr>
<td>${key}</td>
<td class="${compatibleClass}">${compatible}</td>
<td>${compatData[key].range}</td>
</tr>
`
`;
})
.join("");
.join('');

const out = `<!DOCTYPE html>
<html lang="en">
Expand All @@ -67,7 +76,7 @@ export async function createHtml(compatData: Record<string, CompatData>, version
${tableData}
</table>
</body>
</html>`
</html>`;

await writeFile(path, out);
console.log(`File generated at ${path}`);
Expand Down
4 changes: 2 additions & 2 deletions src/cli/reporter/table.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ export function createTable(compatData: Record<string, CompatData>, version: str
console.log(table(out, config));
}

function toColorString(value: boolean | undefined) {
if (value === undefined) return yellow('undefined');
function toColorString(value: boolean | string | undefined) {
if (value === undefined || value === 'invalid') return yellow(`${value}`);
const outputColor = value ? green : red;
return outputColor(value.toString());
}
46 changes: 35 additions & 11 deletions src/queries/getPackageData.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { satisfies } from 'compare-versions';
import { EnginesData } from '../types';
import { CompatData, EnginesData } from '../types';

export function getPackageData(dep: EnginesData, version: string) {
export function getPackageData(dep: EnginesData, version: string): CompatData {
const range = dep.range ? dep.range : 'n/a';
const compatible = isCompatible(version, dep.range);
return { compatible, range };
Expand All @@ -13,14 +13,38 @@ function isCompatible(nodeVersion: string, depRange: string) {
// if a dependency has `*` for the node version, it's always compatible
if (['x', '*'].includes(depRange)) return true;

let compatible;

const logicalOrRegEx = /\|\|/;
if (depRange && logicalOrRegEx.test(depRange)) {
const rangeArray = depRange.split('||').map((range) => range.replaceAll(' ', ''));
compatible = rangeArray.some((range) => satisfies(nodeVersion, range));
} else {
compatible = satisfies(nodeVersion, depRange.replaceAll(' ', ''));
try {
return depRange
.split('||')
.map((range) => removeWhitespace(range))
.some((range) => safeSatisfies(nodeVersion, range));
} catch (error) {
if ((error as Error).message.match(/Invalid argument not valid semver/)) {
return 'invalid';
}
throw error;
}
return compatible;
}

// accounts for `AND` ranges -- ie, `'>=1.2.9 <2.0.0'`
function safeSatisfies(nodeVersion: string, range: string) {
return (
range
.split(' ')
// filter out any whitespace we may have missed with the RegEx -- ie, `'>4 <8'`
.filter((r) => !!r)
.every((r) => satisfies(nodeVersion, r))
);
}

// trims leading and trailing whitespace and whitespace
// between the comparator operators and the actual version number
// version number. ie, ' > = 12.0.0 ' becomes '>=12.0.0'
function removeWhitespace(range: string) {
const comparatorWhitespace = /((?<=(<|>))(\s+)(?=(=)))/g;
const comparatorAndVersionWhiteSpace = /(?<=(<|>|=|\^|~))(\s+)(?=\d)/g;
return range
.trim()
.replace(comparatorWhitespace, '')
.replace(comparatorAndVersionWhiteSpace, '');
}
2 changes: 1 addition & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export interface EnginesData {
export type EnginesDataArray = Array<EnginesData>;

export interface CompatData {
compatible: boolean | undefined;
compatible: boolean | 'invalid' | undefined;
range: string;
}

Expand Down

0 comments on commit 5961124

Please sign in to comment.