Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add parsePackage method, bump dependencies, target Node 16 #29

Merged
merged 13 commits into from
Apr 7, 2023
18 changes: 16 additions & 2 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const getPackagePath = cwd => {
const _readPackage = (file, normalize) => {
const json = typeof file === 'string'
? parseJson(file)
: file; // TODO: ensure `file` is an object here
: file;

if (normalize) {
normalizePackageData(json);
Expand All @@ -35,5 +35,19 @@ export function readPackageSync({cwd, normalize = true} = {}) {
}

export function parsePackage(packageFile, {normalize = true} = {}) {
return _readPackage(packageFile, normalize);
const isObject = packageFile !== null && typeof packageFile === 'object' && !Array.isArray(packageFile);
const isString = typeof packageFile === 'string';

if (!isObject && !isString) {
throw new TypeError('`packageFile` should be either an `object` or a `string`.');
}

// Input should not be modified - if `structuredClone` is available, do a deep clone, shallow otherwise
tommy-mitchell marked this conversation as resolved.
Show resolved Hide resolved
const clonedPackageFile = isObject
? (structuredClone === undefined
? {...packageFile}
: structuredClone(packageFile))
: packageFile;

return _readPackage(clonedPackageFile, normalize);
}
5 changes: 0 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,5 @@
"ava": "^5.2.0",
"tsd": "^0.28.1",
"xo": "^0.54.0"
},
"xo": {
"ignores": [
"test/test.js"
]
}
}
2 changes: 2 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ Default: `true`

Parses an object or string into JSON.

Note: `packageFile` is cloned using [`structuredClone`](https://developer.mozilla.org/en-US/docs/Web/API/structuredClone) to prevent modification to the input object. In environments without `structuredClone`, a shallow spread is used instead, which can cause deep properties of the object to be modified. Consider cloning the object before using `parsePackage` if that's the case.
tommy-mitchell marked this conversation as resolved.
Show resolved Hide resolved

#### packageFile

Type: `object | string`\
Expand Down
28 changes: 26 additions & 2 deletions test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
);
});

test('sync - normalize option', async t => {

Check failure on line 44 in test/test.js

View workflow job for this annotation

GitHub Actions / Node.js 19

Function was declared as `async` but doesn't use `await`.

Check failure on line 44 in test/test.js

View workflow job for this annotation

GitHub Actions / Node.js 18

Function was declared as `async` but doesn't use `await`.

Check failure on line 44 in test/test.js

View workflow job for this annotation

GitHub Actions / Node.js 16

Function was declared as `async` but doesn't use `await`.
const package_ = readPackageSync({normalize: false});
t.is(package_.name, 'unicorn ');
});
Expand All @@ -53,7 +53,7 @@
};

test('parsePackage - json input', t => {
const package_ = parsePackage({...pkgJson});
const package_ = parsePackage(pkgJson);
t.is(package_.name, 'unicorn');
t.deepEqual(
readPackageSync(),
Expand All @@ -71,10 +71,34 @@
});

test('parsePackage - normalize option', t => {
const package_ = parsePackage({...pkgJson}, {normalize: false});
const package_ = parsePackage(pkgJson, {normalize: false});
t.is(package_.name, 'unicorn ');
t.deepEqual(
readPackageSync({normalize: false}),
package_,
);
});

test('parsePackage - errors on invalid input', t => {
t.throws(
() => parsePackage(['foo', 'bar']),
{message: '`packageFile` should be either an `object` or a `string`.'},
);

t.throws(
() => parsePackage(null),
{message: '`packageFile` should be either an `object` or a `string`.'},
);

t.throws(
() => parsePackage(() => ({name: 'unicorn'})),
{message: '`packageFile` should be either an `object` or a `string`.'},
);
});

test('parsePackage - does not modify source object', t => {
const pkgObject = {name: 'unicorn', version: '1.0.0'};
const package_ = parsePackage(pkgObject);

t.not(pkgObject, package_);
});