From c80424ffd81efd515382c10705f0848154c44005 Mon Sep 17 00:00:00 2001 From: Pelle Wessman Date: Mon, 18 Mar 2024 17:57:02 +0100 Subject: [PATCH] feat!: support checking workspaces Fixes #95 And removes `getInstalledData()`, which now lives in `list-installed` instead --- .gitignore | 1 + README.md | 100 ++++++++++-------- declaration.tsconfig.json | 1 + index.d.ts | 9 ++ index.js | 13 --- lib/check-package-versions.js | 4 +- lib/check-version-range.js | 10 +- lib/check-versions.js | 4 +- lib/get-installed-data.js | 46 -------- lib/installed-check.js | 47 ++++++-- lib/lookup-types.d.ts | 11 ++ lib/perform-installed-check.js | 16 ++- package.json | 8 +- .../workspace/node_modules/bar/package.json | 6 ++ .../workspace/node_modules/foo/package.json | 6 ++ test/fixtures/workspace/package.json | 8 ++ .../packages/a/node_modules/abc/package.json | 6 ++ .../packages/a/node_modules/bar/package.json | 6 ++ .../workspace/packages/a/package.json | 10 ++ test/get-installed-data.spec.js | 48 --------- test/installed-check.spec.js | 45 +++++++- test/package.test-d.ts | 9 +- 22 files changed, 222 insertions(+), 192 deletions(-) create mode 100644 index.d.ts delete mode 100644 lib/get-installed-data.js create mode 100644 lib/lookup-types.d.ts create mode 100644 test/fixtures/workspace/node_modules/bar/package.json create mode 100644 test/fixtures/workspace/node_modules/foo/package.json create mode 100644 test/fixtures/workspace/package.json create mode 100644 test/fixtures/workspace/packages/a/node_modules/abc/package.json create mode 100644 test/fixtures/workspace/packages/a/node_modules/bar/package.json create mode 100644 test/fixtures/workspace/packages/a/package.json delete mode 100644 test/get-installed-data.spec.js diff --git a/.gitignore b/.gitignore index c20a5d9..8cc502a 100644 --- a/.gitignore +++ b/.gitignore @@ -13,5 +13,6 @@ *.d.ts *.d.ts.map !/lib/**/*-types.d.ts +!/index.d.ts # Library specific ones diff --git a/README.md b/README.md index f3b299c..3429149 100644 --- a/README.md +++ b/README.md @@ -50,9 +50,9 @@ checkVersionRange(pkg, key, installed, [options]) => VersionRangeResult #### Arguments -* `pkg`: Type `PackageJsonLike` – the content of the `package.json` file to check, see [`getInstalledData()`](#getinstalleddata) +* `pkg`: Type [`PackageJsonLike`](#packagejsonlike) – the content of the `package.json` file to check * `key`: Type `string` – the key of the version range to check, eg `engines.node` -* `installed`: Type `InstalledDependencies` – the installed dependencies to use when checking, see [`getInstalledData()`](#getinstalleddata) +* `installed`: Type [`InstalledDependencies`](#installeddependencies) – the `package.json` files of the installed dependencies * `options`: Type `VersionRangeOptions` – optional options #### Types @@ -80,9 +80,16 @@ type VersionRangeResult = VersionRangeItem & { #### Example ```javascript -import { checkVersionRange, getInstalledData } from 'installed-check-core'; +import { checkVersionRange } from 'installed-check-core'; +import { listInstalled } from 'list-installed'; +import { readPackage } from 'read-pkg'; -const { installed, pkg } = await getInstalledData(cwd); +const cwd = '.'; + +const [pkg, installed] = await Promise.all([ + readPackage({ cwd }), + listInstalled(cwd), +]); const result = await checkVersionRange( pkg, @@ -134,44 +141,6 @@ checkVersionRangeCollection(pkg, key, installed, [options]) => VersionRangesResu See main description of [`checkVersionRangeCollection()`](#checkversionrangecollection) and full docs for [`checkVersionRange()`](#checkversionrange). -### getInstalledData() - -Companion method to eg. `checkVersionRange()` that which makes it easy to get the correct data required. Not meant for any other use. - -Is a simple wrapper around [`read-pkg`](https://github.com/sindresorhus/read-pkg) and [`list-installed`](https://github.com/voxpelli/list-installed) – those or similar modules can be used directly just as well. - -#### Syntax - -```ts -getInstalledData(cwd = '.') => Promise -``` - -#### Arguments - -* `cwd` – specifies the path of the package to be checked, with its `package.json` expected to exist in that path and its installed `node_modules` as well. - -#### Types - -```ts -// Subset of import('type-fest').PackageJson / import('read-pkg').NormalizedPackageJson -export type PackageJsonLike = { - name?: string | undefined; - version?: string | undefined; - engines?: Record; - dependencies?: Record; - devDependencies?: Record; - optionalDependencies?: Record; - peerDependencies?: Record; -}; - -// A map is allowed since that's what import('list-installed).listInstalled returns -export type InstalledDependencies = Map | Record; -``` - -#### Example - -See example of [`checkVersionRange()`](#checkversionrange) - ### installedCheck() The full on `installed-check` experience, returning error and warning strings only. @@ -179,18 +148,31 @@ The full on `installed-check` experience, returning error and warning strings on #### Syntax ```ts -installedCheck(checks, options) => Promise +installedCheck(checks, [lookupOptions], [options]) => Promise ``` #### Arguments * `checks`: Type `InstalledChecks[]` – the checks to run, an array of one or more of: `'engine'`, `'peer'`, `'version'` -* `options`: Type `InstalledCheckOptions` +* `lookupOptions`: Type `LookupOptions` – optional – defaults to `cwd='.'` and `includeWorkspaceRoot: true` +* `options`: Type `InstalledCheckOptions` – optional #### Types ```ts +type LookupOptions = { + includeWorkspaceRoot?: boolean; + cwd?: string; + skipWorkspaces?: boolean; + workspace?: string[]; +}; type InstalledChecks = 'engine' | 'peer' | 'version' +type InstalledCheckOptions = { + ignore?: string[] | undefined; + noDev?: boolean | undefined; + prefix?: string | undefined; + strict?: boolean | undefined; +}; type InstalledCheckResult = { errors: string[], warnings: string[] } ``` @@ -221,7 +203,7 @@ const { errors, warnings } = await installedCheck(['engine', 'version'], { ### performInstalledCheck() -Same as [`installedCheck()`](#installedcheck) but without looking up any data on its own but instead expects the data from [`getInstalledData()`](#getinstalleddata) or similar to be given to it. +Similar to [`installedCheck()`](#installedcheck) but expects to be given package data instead of looking it up itself.. #### Syntax @@ -232,10 +214,34 @@ performInstalledCheck(checks, pkg, installed, options) => Promise; + dependencies?: Record; + devDependencies?: Record; + optionalDependencies?: Record; + peerDependencies?: Record; +}; +``` + +### InstalledDependencies + +```ts +// A map is allowed since that's what import('list-installed).listInstalled returns +export type InstalledDependencies = Map | Record; +``` + ## Used by * Used by the [`installed-check`](https://github.com/voxpelli/node-installed-check) CLI tool diff --git a/declaration.tsconfig.json b/declaration.tsconfig.json index 9e810af..4d21677 100644 --- a/declaration.tsconfig.json +++ b/declaration.tsconfig.json @@ -1,6 +1,7 @@ { "extends": "./tsconfig", + "files": [], "exclude": [ "test/**/*" ], diff --git a/index.d.ts b/index.d.ts new file mode 100644 index 0000000..74c5fd5 --- /dev/null +++ b/index.d.ts @@ -0,0 +1,9 @@ +export type * from './lib/lookup-types.d.ts'; + +export type { VersionRangeItem, VersionRangeOptions, VersionRangeResult, VersionRangesOptions } from './lib/check-version-range.js'; +export type { LookupOptions } from './lib/installed-check.js'; +export type { InstalledChecks, InstalledCheckOptions, InstalledCheckResult } from './lib/perform-installed-check.js'; + +export { checkVersionRange, checkVersionRangeCollection } from './lib/check-version-range.js'; +export { installedCheck } from './lib/installed-check.js'; +export { performInstalledCheck } from './lib/perform-installed-check.js'; diff --git a/index.js b/index.js index 261416e..7e17a8a 100644 --- a/index.js +++ b/index.js @@ -1,16 +1,3 @@ -/** @typedef {import('./lib/check-version-range.js').VersionRangeItem} VersionRangeItem */ -/** @typedef {import('./lib/check-version-range.js').VersionRangeOptions} VersionRangeOptions */ -/** @typedef {import('./lib/check-version-range.js').VersionRangeResult} VersionRangeResult */ -/** @typedef {import('./lib/check-version-range.js').VersionRangeOptions} VersionRangesOptions */ - -/** @typedef {import('./lib/get-installed-data.js').PackageJsonLike} PackageJsonLike */ -/** @typedef {import('./lib/get-installed-data.js').InstalledDependencies} InstalledDependencies */ - -/** @typedef {import('./lib/perform-installed-check.js').InstalledChecks} InstalledChecks */ -/** @typedef {import('./lib/perform-installed-check.js').InstalledCheckOptions} InstalledCheckOptions */ -/** @typedef {import('./lib/perform-installed-check.js').InstalledCheckResult} InstalledCheckResult */ - export { checkVersionRange, checkVersionRangeCollection } from './lib/check-version-range.js'; -export { getInstalledData } from './lib/get-installed-data.js'; export { installedCheck } from './lib/installed-check.js'; export { performInstalledCheck } from './lib/perform-installed-check.js'; diff --git a/lib/check-package-versions.js b/lib/check-package-versions.js index 0d25445..4b46d53 100644 --- a/lib/check-package-versions.js +++ b/lib/check-package-versions.js @@ -1,8 +1,8 @@ import semver from 'semver'; /** - * @param {import('./get-installed-data.js').PackageJsonLike} pkg - * @param {import('./get-installed-data.js').InstalledDependencies} installedDependencies + * @param {import('./lookup-types.d.ts').PackageJsonLike} pkg + * @param {import('./lookup-types.d.ts').InstalledDependencies} installedDependencies * @returns {{ errors: string[], warnings: string[] }} */ export function checkPackageVersions (pkg, installedDependencies) { diff --git a/lib/check-version-range.js b/lib/check-version-range.js index 3a06e86..33c8621 100644 --- a/lib/check-version-range.js +++ b/lib/check-version-range.js @@ -17,9 +17,9 @@ import { getObjectValueByPath, getStringValueByPath } from './utils.js'; /** @typedef {VersionRangeItem & { packageNotes: Array }} VersionRangeResult */ /** - * @param {import('./get-installed-data.js').PackageJsonLike} pkg + * @param {import('./lookup-types.d.ts').PackageJsonLike} pkg * @param {string} key - * @param {import('./get-installed-data.js').InstalledDependencies} installed + * @param {import('./lookup-types.d.ts').InstalledDependencies} installed * @param {VersionRangeOptions} [options] * @returns {VersionRangeResult} */ @@ -93,9 +93,9 @@ export function checkVersionRange (pkg, key, installed, options) { /** @typedef {VersionRangeOptions & { defaultKeys?: string[] }} VersionRangesOptions */ /** - * @param {import('./get-installed-data.js').PackageJsonLike} pkg + * @param {import('./lookup-types.d.ts').PackageJsonLike} pkg * @param {string} topKey - * @param {import('./get-installed-data.js').InstalledDependencies} installed + * @param {import('./lookup-types.d.ts').InstalledDependencies} installed * @param {VersionRangesOptions} [options] * @returns {{ [key: string]: VersionRangeResult }} */ @@ -123,7 +123,7 @@ export function checkVersionRangeCollection (pkg, topKey, installed, options) { /** * @param {string} referenceRange * @param {string} key - * @param {import('./get-installed-data.js').PackageJsonLike|undefined} dependencyPackage + * @param {import('./lookup-types.d.ts').PackageJsonLike|undefined} dependencyPackage * @param {boolean} [isOptional] * @param {Omit} [options] * @returns {(VersionRangeItem & { valid: false | undefined }) | undefined} diff --git a/lib/check-versions.js b/lib/check-versions.js index ad3ac2f..86c3f76 100644 --- a/lib/check-versions.js +++ b/lib/check-versions.js @@ -1,9 +1,9 @@ import { checkVersionRangeCollection } from './check-version-range.js'; /** - * @param {import('./get-installed-data.js').PackageJsonLike} pkg + * @param {import('./lookup-types.d.ts').PackageJsonLike} pkg * @param {string} key - * @param {import('./get-installed-data.js').InstalledDependencies} installed + * @param {import('./lookup-types.d.ts').InstalledDependencies} installed * @param {import('./check-version-range.js').VersionRangesOptions} options * @returns {{ errors: string[], warnings: string[] }} */ diff --git a/lib/get-installed-data.js b/lib/get-installed-data.js deleted file mode 100644 index f65293e..0000000 --- a/lib/get-installed-data.js +++ /dev/null @@ -1,46 +0,0 @@ -import { listInstalled } from 'list-installed'; -import { ErrorWithCause } from 'pony-cause'; -import { readPackage } from 'read-pkg'; - -/** - * @typedef PackageJsonLike - * @property {string | undefined} [name] - * @property {string | undefined} [version] - * @property {Record} [engines] - * @property {Record} [dependencies] - * @property {Record} [devDependencies] - * @property {Record} [optionalDependencies] - * @property {Record} [peerDependencies] - */ - -/** @typedef {Map | Record} InstalledDependencies */ - -/** - * @typedef InstalledData - * @property {Map} installed - * @property {import('read-pkg').NormalizedPackageJson} pkg - */ - -/** - * @throws {Error} - * @param {string} [cwd] Specifies the path to the package to be checked, with its `package.json` expected to be there and its installed `node_modules` as well - * @returns {Promise} - */ -export async function getInstalledData (cwd = '.') { - const [ - pkg, - installed, - ] = await Promise.all([ - readPackage({ cwd }).catch(/** @param {Error} err */ err => { - throw new ErrorWithCause('Failed to read package.json', { cause: err }); - }), - listInstalled(cwd).catch(/** @param {Error} err */ err => { - throw new ErrorWithCause('Failed to list installed modules', { cause: err }); - }), - ]); - - return { - installed, - pkg, - }; -} diff --git a/lib/installed-check.js b/lib/installed-check.js index 99733bf..4890335 100644 --- a/lib/installed-check.js +++ b/lib/installed-check.js @@ -1,15 +1,50 @@ -import { getInstalledData } from './get-installed-data.js'; +import { workspaceLookup } from 'list-installed'; + import { performInstalledCheck } from './perform-installed-check.js'; +/** @typedef {Omit & { cwd?: string }} LookupOptions */ + +const ROOT = Symbol('workspace root'); + /** * @param {import('./perform-installed-check.js').InstalledChecks[]} checks - * @param {import('./perform-installed-check.js').InstalledCheckOptions & { cwd?: string }} [options] + * @param {LookupOptions} [lookupOptions] + * @param {import('./perform-installed-check.js').InstalledCheckOptions} [options] * @returns {Promise} */ -export async function installedCheck (checks, options) { - const { cwd = '.', ...checkOptions } = options || {}; +export async function installedCheck (checks, lookupOptions, options) { + const { cwd = '.', ...lookupOptionsRest } = lookupOptions || {}; + + /** @type {Map} */ + const errors = new Map(); + /** @type {Map} */ + const warnings = new Map(); + + for await (const item of workspaceLookup({ ...lookupOptionsRest, path: cwd })) { + const result = await performInstalledCheck(checks, item.pkg, item.installed, options); - const { installed, pkg } = await getInstalledData(cwd); + const key = 'workspace' in item ? item.workspace : ROOT; - return performInstalledCheck(checks, pkg, installed, checkOptions); + errors.set(key, result.errors); + warnings.set(key, result.warnings); + } + + return { + errors: prefixNotes(errors, lookupOptions), + warnings: prefixNotes(warnings, lookupOptions), + }; +} + +/** + * @param {Map} notes + * @param {LookupOptions} [lookupOptions] + * @returns {string[]} + */ +function prefixNotes (notes, lookupOptions) { + if (lookupOptions?.includeWorkspaceRoot !== false && notes.size === 1) { + return [...notes.values()].flat(); + } + return [...notes].flatMap(([key, items]) => + items.map(item => `${key === ROOT ? 'root' : key}: ${item}`) + ); } diff --git a/lib/lookup-types.d.ts b/lib/lookup-types.d.ts new file mode 100644 index 0000000..3925fc8 --- /dev/null +++ b/lib/lookup-types.d.ts @@ -0,0 +1,11 @@ +export type PackageJsonLike = { + name?: string | undefined; + version?: string | undefined; + engines?: Record; + dependencies?: Record; + devDependencies?: Record; + optionalDependencies?: Record; + peerDependencies?: Record; +}; + +export type InstalledDependencies = Map | Record; diff --git a/lib/perform-installed-check.js b/lib/perform-installed-check.js index e0814a5..a517f84 100644 --- a/lib/perform-installed-check.js +++ b/lib/perform-installed-check.js @@ -25,14 +25,15 @@ const checkTypes = typedObjectKeys(checkTypeMap); * @typedef InstalledCheckOptions * @property {string[]|undefined} [ignore] * @property {boolean|undefined} [noDev] + * @property {string|undefined} [prefix] * @property {boolean|undefined} [strict] */ /** * @param {InstalledChecks[]} checks - * @param {import('./get-installed-data.js').PackageJsonLike} pkg - * @param {import('./get-installed-data.js').InstalledDependencies} installed - * @param {InstalledCheckOptions} options + * @param {import('./lookup-types.d.ts').PackageJsonLike} pkg + * @param {import('./lookup-types.d.ts').InstalledDependencies} installed + * @param {InstalledCheckOptions} [options] * @returns {Promise} */ export async function performInstalledCheck (checks, pkg, installed, options) { @@ -45,11 +46,8 @@ export async function performInstalledCheck (checks, pkg, installed, options) { if (!installed || typeof installed !== 'object') { throw new TypeError('Expected a "installed" object, got: ' + explainVariable(installed)); } - if (!options || typeof options !== 'object') { - throw new TypeError('Expected a "options" object, got :' + explainVariable(options)); - } - const { ignore, ...passthroughOptions } = options; + const { ignore, prefix, ...passthroughOptions } = options || {}; const resolvedIgnores = ( ignore?.some(value => isGlob(value)) @@ -80,8 +78,8 @@ export async function performInstalledCheck (checks, pkg, installed, options) { for (const result of results) { if (result) { hasCheck = true; - errors = [...errors, ...result.errors]; - warnings = [...warnings, ...result.warnings]; + errors = [...errors, ...(prefix ? result.errors.map(note => prefix + ': ' + note) : result.errors)]; + warnings = [...warnings, ...(prefix ? result.warnings.map(note => prefix + ': ' + note) : result.warnings)]; } } diff --git a/package.json b/package.json index d88c19c..512aa0a 100644 --- a/package.json +++ b/package.json @@ -22,13 +22,13 @@ "build:0": "run-s clean", "build:1-declaration": "tsc -p declaration.tsconfig.json", "build": "run-s build:*", - "check:installed-check": "installed-check -i eslint-plugin-jsdoc -i knip -i linemod", + "check:installed-check": "installed-check", "check:knip": "knip", "check:lint": "eslint --report-unused-disable-directives .", "check:tsc": "tsc", "check:type-coverage": "type-coverage --detail --strict --at-least 99 --ignore-files 'test/*'", "check": "run-s clean && run-p check:*", - "clean:declarations-top": "rm -rf $(find . -maxdepth 1 -type f -name '*.d.ts*')", + "clean:declarations-top": "rm -rf $(find . -maxdepth 1 -type f -name '*.d.ts*' ! -name 'index.d.ts')", "clean:declarations-lib": "rm -rf $(find lib -type f -name '*.d.ts*' ! -name '*-types.d.ts')", "clean": "run-p clean:*", "prepare": "husky", @@ -41,13 +41,13 @@ "author": "Pelle Wessman (http://kodfabrik.se/)", "license": "MIT", "engines": { - "node": ">=18.0.0" + "node": ">=18.6.0" }, "dependencies": { "@voxpelli/semver-set": "^5.0.2", "@voxpelli/typed-utils": "^1.6.0", "is-glob": "^4.0.3", - "list-installed": "^4.2.1", + "list-installed": "^5.1.0", "picomatch": "^4.0.1", "pony-cause": "^2.1.10", "read-pkg": "^9.0.1", diff --git a/test/fixtures/workspace/node_modules/bar/package.json b/test/fixtures/workspace/node_modules/bar/package.json new file mode 100644 index 0000000..b5d4324 --- /dev/null +++ b/test/fixtures/workspace/node_modules/bar/package.json @@ -0,0 +1,6 @@ +{ + "private": true, + "name": "bar", + "version": "1.0.0", + "engines": { "node": ">=12.0.0" } +} diff --git a/test/fixtures/workspace/node_modules/foo/package.json b/test/fixtures/workspace/node_modules/foo/package.json new file mode 100644 index 0000000..24ec43f --- /dev/null +++ b/test/fixtures/workspace/node_modules/foo/package.json @@ -0,0 +1,6 @@ +{ + "private": true, + "name": "foo", + "version": "1.0.0", + "engines": { "node": ">=10.4.0" } +} diff --git a/test/fixtures/workspace/package.json b/test/fixtures/workspace/package.json new file mode 100644 index 0000000..8ab2054 --- /dev/null +++ b/test/fixtures/workspace/package.json @@ -0,0 +1,8 @@ +{ + "workspaces": ["packages/*"], + "engines": { "node": ">=8.0.0" }, + "dependencies": { + "foo": "^1.0.0", + "bar": "^1.0.0" + } +} diff --git a/test/fixtures/workspace/packages/a/node_modules/abc/package.json b/test/fixtures/workspace/packages/a/node_modules/abc/package.json new file mode 100644 index 0000000..299844b --- /dev/null +++ b/test/fixtures/workspace/packages/a/node_modules/abc/package.json @@ -0,0 +1,6 @@ +{ + "private": true, + "name": "abc", + "version": "1.0.0", + "engines": { "node": ">=10.8.0" } +} diff --git a/test/fixtures/workspace/packages/a/node_modules/bar/package.json b/test/fixtures/workspace/packages/a/node_modules/bar/package.json new file mode 100644 index 0000000..af3f8e9 --- /dev/null +++ b/test/fixtures/workspace/packages/a/node_modules/bar/package.json @@ -0,0 +1,6 @@ +{ + "private": true, + "name": "bar", + "version": "2.0.0", + "engines": { "node": ">=10.5.0" } +} diff --git a/test/fixtures/workspace/packages/a/package.json b/test/fixtures/workspace/packages/a/package.json new file mode 100644 index 0000000..9db8a78 --- /dev/null +++ b/test/fixtures/workspace/packages/a/package.json @@ -0,0 +1,10 @@ +{ + "private": true, + "name": "@voxpelli/workspace-a", + "engines": { "node": ">=10.0.0" }, + "dependencies": { + "foo": "^1.0.0", + "bar": "^2.0.0", + "abc": "^1.0.0" + } +} diff --git a/test/get-installed-data.spec.js b/test/get-installed-data.spec.js deleted file mode 100644 index 7afd5f9..0000000 --- a/test/get-installed-data.spec.js +++ /dev/null @@ -1,48 +0,0 @@ -import chai from 'chai'; -import { join } from 'desm'; -import { ErrorWithCause } from 'pony-cause'; - -import { getInstalledData } from '../lib/get-installed-data.js'; - -chai.should(); - -process.on('unhandledRejection', cause => { - throw new ErrorWithCause('Unhandled rejection', { cause }); -}); - -describe('getInstalledData', () => { - it('should return data', async () => { - await getInstalledData().should.eventually - .be.an('object') - .with.keys('installed', 'pkg') - .and.have.nested.property('pkg.name', 'installed-check-core'); - }); - - it('should return data from cwd when specified', async () => { - const result = await getInstalledData(join(import.meta.url, 'fixtures/valid')); - - result.should.be.an('object').with.keys('installed', 'pkg'); - - result.pkg.should.deep.equal({ - _id: '@', - engines: { node: '>=8.0.0' }, - dependencies: { foo: '^1.0.0' }, - name: '', - readme: 'ERROR: No README data found!', - version: '', - }); - - [...result.installed.entries()].should.deep.equal([ - ['foo', { - '_id': 'foo@1.0.0', - 'engines': { - 'node': '>=8.0.0', - }, - 'name': 'foo', - 'private': true, - 'readme': 'ERROR: No README data found!', - 'version': '1.0.0', - }], - ]); - }); -}); diff --git a/test/installed-check.spec.js b/test/installed-check.spec.js index a7ef483..9ade02e 100644 --- a/test/installed-check.spec.js +++ b/test/installed-check.spec.js @@ -132,10 +132,11 @@ describe('installedCheck()', () => { }); it('should handle ignores', async () => { - await installedCheck(['engine'], { - cwd: join(import.meta.url, 'fixtures/invalid'), - ignore: ['invalid-alias*', 'invalid-dependency-definition'], - }) + await installedCheck( + ['engine'], + { cwd: join(import.meta.url, 'fixtures/invalid') }, + { ignore: ['invalid-alias*', 'invalid-dependency-definition'] } + ) .should.eventually.deep.equal({ 'errors': [ 'invalid-engine: Narrower "engines.node" is needed: >=10.0.0', @@ -166,5 +167,41 @@ describe('installedCheck()', () => { ], }); }); + + it('should check workspaces', async () => { + await installedCheck(['engine'], { + cwd: join(import.meta.url, 'fixtures/workspace'), + }) + .should.eventually.deep.equal({ + 'errors': [ + 'root: foo: Narrower "engines.node" is needed: >=10.4.0', + 'root: bar: Narrower "engines.node" is needed: >=12.0.0', + 'root: Combined "engines.node" needs to be narrower: >=12.0.0', + '@voxpelli/workspace-a: foo: Narrower "engines.node" is needed: >=10.4.0', + '@voxpelli/workspace-a: bar: Narrower "engines.node" is needed: >=10.5.0', + '@voxpelli/workspace-a: abc: Narrower "engines.node" is needed: >=10.8.0', + '@voxpelli/workspace-a: Combined "engines.node" needs to be narrower: >=10.8.0', + ], + warnings: [ + ], + }); + }); + + it('should support lookup options when checking workspaces', async () => { + await installedCheck(['engine'], { + cwd: join(import.meta.url, 'fixtures/workspace'), + includeWorkspaceRoot: false, + }) + .should.eventually.deep.equal({ + 'errors': [ + '@voxpelli/workspace-a: foo: Narrower "engines.node" is needed: >=10.4.0', + '@voxpelli/workspace-a: bar: Narrower "engines.node" is needed: >=10.5.0', + '@voxpelli/workspace-a: abc: Narrower "engines.node" is needed: >=10.8.0', + '@voxpelli/workspace-a: Combined "engines.node" needs to be narrower: >=10.8.0', + ], + warnings: [ + ], + }); + }); }); }); diff --git a/test/package.test-d.ts b/test/package.test-d.ts index b8ed962..465153a 100644 --- a/test/package.test-d.ts +++ b/test/package.test-d.ts @@ -3,13 +3,10 @@ import { expectTypeOf } from 'expect-type'; import type { NormalizedPackageJson, PackageJson } from 'read-pkg'; import type { NormalizedPackageJson as ListInstalledNormalizedPackageJson } from 'list-installed'; -import type { PackageJsonLike, InstalledDependencies } from '../lib/get-installed-data.js'; -import { getInstalledData } from '../lib/get-installed-data.js'; +import type { PackageJsonLike, InstalledDependencies } from '../lib/lookup-types.d.ts'; -const { pkg, installed } = await getInstalledData(); - -expectTypeOf(pkg).toEqualTypeOf(); -expectTypeOf(installed).toEqualTypeOf>(); +const pkg = {} as NormalizedPackageJson; +const installed: Map = new Map(); expectTypeOf(pkg).toMatchTypeOf(); expectTypeOf(installed).toMatchTypeOf();