From a084069ad78cb2609b104db4c0674dedb262c777 Mon Sep 17 00:00:00 2001 From: Jamie Mason Date: Sat, 22 Feb 2020 16:57:58 +0000 Subject: [PATCH] refactor(lint): fix eslint warnings --- src/commands/fix-mismatches.spec.ts | 5 ++--- src/commands/fix-mismatches.ts | 16 ++++++++++------ src/commands/format.spec.ts | 4 ++-- src/commands/format.ts | 13 ++++++++----- src/commands/lib/get-highest-version.spec.ts | 2 +- src/commands/lib/get-highest-version.ts | 4 ++-- src/commands/lib/get-installations.spec.ts | 9 +++++++-- src/commands/lib/get-installations.ts | 6 +++--- src/commands/lib/get-wrappers.ts | 16 ++++++++-------- src/commands/lib/is-semver.ts | 6 +++--- src/commands/lib/log.ts | 4 +++- src/commands/lib/write-if-changed.ts | 4 ++-- src/commands/list-mismatches.spec.ts | 5 +++-- src/commands/list-mismatches.ts | 2 +- src/commands/list.spec.ts | 5 +++-- src/commands/list.ts | 4 ++-- src/commands/set-semver-ranges.ts | 19 +++++++++++++++---- src/constants.ts | 12 ++++-------- test/mock.ts | 4 ++-- 19 files changed, 81 insertions(+), 59 deletions(-) diff --git a/src/commands/fix-mismatches.spec.ts b/src/commands/fix-mismatches.spec.ts index 91337e54..335b9598 100644 --- a/src/commands/fix-mismatches.spec.ts +++ b/src/commands/fix-mismatches.spec.ts @@ -1,8 +1,8 @@ import * as mock from '../../test/mock'; +import * as api from './fix-mismatches'; describe('fixMismatches', () => { - let fixMismatches: any; - let log: any; + let fixMismatches: typeof api.fixMismatches; afterEach(() => { jest.restoreAllMocks(); @@ -11,7 +11,6 @@ describe('fixMismatches', () => { beforeEach(() => { jest.mock('./lib/log', () => ({ log: jest.fn() })); fixMismatches = require('./fix-mismatches').fixMismatches; - log = require('./lib/log').log; }); it('sets all dependencies installed with different versions to the highest version', () => { diff --git a/src/commands/fix-mismatches.ts b/src/commands/fix-mismatches.ts index 6e795595..2deb0c86 100644 --- a/src/commands/fix-mismatches.ts +++ b/src/commands/fix-mismatches.ts @@ -9,7 +9,7 @@ import { getMismatchedDependencies } from './lib/get-installations'; import { getWrappers, SourceWrapper } from './lib/get-wrappers'; import { log } from './lib/log'; -interface Options { +export interface Options { dev: boolean; filter: RegExp; indent: string; @@ -18,20 +18,24 @@ interface Options { sources: string[]; } -export const fixMismatches = (dependencyTypes: DependencyType[], filter: RegExp, wrappers: SourceWrapper[]) => { +export const fixMismatches = (dependencyTypes: DependencyType[], filter: RegExp, wrappers: SourceWrapper[]): void => { const iterator = getMismatchedDependencies(dependencyTypes, wrappers); const mismatches = Array.from(iterator).filter(({ name }) => name.search(filter) !== -1); mismatches.forEach((installedPackage) => { - const newest = getHighestVersion(installedPackage.installations.map((installation) => installation.version)); + const versions = installedPackage.installations.map((installation) => installation.version); + const newest = getHighestVersion(versions); installedPackage.installations.forEach(({ type, name, source }) => { - source.contents[type][name] = newest; + const dependencies = source.contents[type]; + if (dependencies) { + dependencies[name] = newest; + } }); }); }; -export const fixMismatchesToDisk = ({ dev, filter, indent, peer, prod, sources }: Options) => { - const toJson = (wrapper: SourceWrapper) => `${JSON.stringify(wrapper.contents, null, indent)}${EOL}`; +export const fixMismatchesToDisk = ({ dev, filter, indent, peer, prod, sources }: Options): void => { + const toJson = (wrapper: SourceWrapper): string => `${JSON.stringify(wrapper.contents, null, indent)}${EOL}`; const dependencyTypes = getDependencyTypes({ dev, peer, prod }); const wrappers = getWrappers({ sources }); const allBefore = wrappers.map(toJson); diff --git a/src/commands/format.spec.ts b/src/commands/format.spec.ts index 0a1772e3..9b78c960 100644 --- a/src/commands/format.spec.ts +++ b/src/commands/format.spec.ts @@ -1,7 +1,7 @@ import { format } from './format'; -import { Source } from './lib/get-wrappers'; +import { Source, SourceWrapper } from './lib/get-wrappers'; -const createWrapper = (contents: Source) => ({ contents, filePath: '' }); +const createWrapper = (contents: Source): SourceWrapper => ({ contents, filePath: '' }); describe('format', () => { it('sorts Array properties alphabetically by value', () => { diff --git a/src/commands/format.ts b/src/commands/format.ts index 7a530751..9d052c38 100644 --- a/src/commands/format.ts +++ b/src/commands/format.ts @@ -12,7 +12,7 @@ interface Options { sources: string[]; } -const sortObject = (sortedKeys: string[] | Set, obj: any) => { +const sortObject = (sortedKeys: string[] | Set, obj: Source | { [key: string]: string }): void => { sortedKeys.forEach((key: string) => { const value = obj[key]; delete obj[key]; @@ -20,15 +20,18 @@ const sortObject = (sortedKeys: string[] | Set, obj: any) => { }); }; -const sortAlphabetically = (value: any) => { +const sortAlphabetically = (value: Source[keyof Source]): void => { if (Array.isArray(value)) { value.sort(); - } else if (Object.prototype.toString.call(value) === '[object Object]') { + } else if (value && typeof value === 'object') { sortObject(Object.keys(value).sort(), value); } }; -export const format = (wrapper: SourceWrapper, { sortAz = SORT_AZ, sortFirst = SORT_FIRST }: FormatConfig = {}) => { +export const format = ( + wrapper: SourceWrapper, + { sortAz = SORT_AZ, sortFirst = SORT_FIRST }: FormatConfig = {}, +): Source => { const { contents } = wrapper; const sortedKeys = Object.keys(contents).sort(); const keys = new Set(sortFirst.concat(sortedKeys)); @@ -50,7 +53,7 @@ export const format = (wrapper: SourceWrapper, { sortAz = SORT_AZ, sortFirst = S return contents; }; -export const formatToDisk = ({ indent, sources: sources }: Options) => { +export const formatToDisk = ({ indent, sources: sources }: Options): void => { getWrappers({ sources }).forEach((wrapper) => { writeIfChanged(indent, wrapper, () => { format(wrapper); diff --git a/src/commands/lib/get-highest-version.spec.ts b/src/commands/lib/get-highest-version.spec.ts index 64a03fbb..18cc0ebe 100644 --- a/src/commands/lib/get-highest-version.spec.ts +++ b/src/commands/lib/get-highest-version.spec.ts @@ -1,6 +1,6 @@ import { getHighestVersion } from './get-highest-version'; -const shuffle = (array: any[]) => { +const shuffle = (array: string[]): string[] => { for (let i = array.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [array[i], array[j]] = [array[j], array[i]]; diff --git a/src/commands/lib/get-highest-version.ts b/src/commands/lib/get-highest-version.ts index b897aa1b..d2ea7624 100644 --- a/src/commands/lib/get-highest-version.ts +++ b/src/commands/lib/get-highest-version.ts @@ -10,9 +10,9 @@ import { RANGE_PATCH, } from '../../constants'; -const getRange = (version: string) => version.slice(0, version.search(/[0-9]/)); +const getRange = (version: string): string => version.slice(0, version.search(/[0-9]/)); -const getRangeScore = (version: string | null) => { +const getRangeScore = (version: string | null): number => { if (version === null) return 0; if (version === RANGE_ANY) return 8; const range = getRange(version); diff --git a/src/commands/lib/get-installations.spec.ts b/src/commands/lib/get-installations.spec.ts index 8f7a2b9b..87401c37 100644 --- a/src/commands/lib/get-installations.spec.ts +++ b/src/commands/lib/get-installations.spec.ts @@ -1,6 +1,6 @@ import 'expect-more-jest'; import { DependencyType } from '../../constants'; -import { getDependencies, getMismatchedDependencies } from './get-installations'; +import { getDependencies, getMismatchedDependencies, Installation } from './get-installations'; import { SourceWrapper } from './get-wrappers'; const mocked = { @@ -14,7 +14,12 @@ const mocked = { types: (): DependencyType[] => ['dependencies', 'devDependencies', 'peerDependencies'], }; -const getShape = (name: string, ...installations: Array<[string, string]>) => ({ +type ExpectedShape = { + installations: Installation[]; + name: string; +}; + +const getShape = (name: string, ...installations: Array<[string, string]>): ExpectedShape => ({ installations: installations.map(([type, version]) => expect.objectContaining({ name, type, version })), name, }); diff --git a/src/commands/lib/get-installations.ts b/src/commands/lib/get-installations.ts index 75ccabff..5b1b2574 100644 --- a/src/commands/lib/get-installations.ts +++ b/src/commands/lib/get-installations.ts @@ -7,7 +7,7 @@ export interface Installation { /** eg 'lodash' */ name: string; /** package.json file contents */ - source: any; + source: SourceWrapper; /** eg '0.1.0' */ version: string; } @@ -40,7 +40,7 @@ function* getInstallationsOf( } export function* getDependencies(types: DependencyType[], wrappers: SourceWrapper[]): Generator { - const visited: any = {}; + const visited: { [name: string]: boolean } = {}; for (const type of types) { for (const wrapper of wrappers) { if (wrapper.contents[type]) { @@ -77,7 +77,7 @@ export function* getMismatchedDependencies( } } -export const sortByName = (a: InstalledPackage, b: InstalledPackage) => { +export const sortByName = (a: InstalledPackage, b: InstalledPackage): 0 | 1 | -1 => { if (a.name < b.name) { return -1; } diff --git a/src/commands/lib/get-wrappers.ts b/src/commands/lib/get-wrappers.ts index d0035ec2..58d5d33c 100644 --- a/src/commands/lib/get-wrappers.ts +++ b/src/commands/lib/get-wrappers.ts @@ -36,14 +36,14 @@ const getPatternsFromConfig = (fileName: string, propName: string): string[] | n : null; }; -const hasCliPatterns = (program: Options) => program.sources && program.sources.length > 0; -const getCliPatterns = (program: Options) => program.sources; -const getYarnPatterns = () => getPatternsFromConfig('package.json', 'workspaces'); -const getLernaPatterns = () => getPatternsFromConfig('lerna.json', 'packages'); -const getDefaultPatterns = () => ALL_PATTERNS; -const resolvePattern = (pattern: string) => sync(pattern, { absolute: true }); -const reduceFlatArray = (all: string[], next: string[]) => all.concat(next); -const createWrapper = (filePath: string) => ({ contents: readJsonSync(filePath), filePath }); +const hasCliPatterns = (program: Options): boolean => program.sources && program.sources.length > 0; +const getCliPatterns = (program: Options): Options['sources'] => program.sources; +const getYarnPatterns = (): string[] | null => getPatternsFromConfig('package.json', 'workspaces'); +const getLernaPatterns = (): string[] | null => getPatternsFromConfig('lerna.json', 'packages'); +const getDefaultPatterns = (): string[] => ALL_PATTERNS; +const resolvePattern = (pattern: string): string[] => sync(pattern, { absolute: true }); +const reduceFlatArray = (all: string[], next: string[]): string[] => all.concat(next); +const createWrapper = (filePath: string): SourceWrapper => ({ contents: readJsonSync(filePath), filePath }); export const getWrappers = (program: Options): SourceWrapper[] => (hasCliPatterns(program) ? getCliPatterns(program) : getYarnPatterns() || getLernaPatterns() || getDefaultPatterns()) diff --git a/src/commands/lib/is-semver.ts b/src/commands/lib/is-semver.ts index bbcdae7a..da979009 100644 --- a/src/commands/lib/is-semver.ts +++ b/src/commands/lib/is-semver.ts @@ -9,7 +9,7 @@ import { RANGE_PATCH, } from '../../constants'; -export const isValidSemverRange = (range: string) => +export const isValidSemverRange = (range: string): boolean => range === RANGE_EXACT || range === RANGE_GT || range === RANGE_GTE || @@ -19,10 +19,10 @@ export const isValidSemverRange = (range: string) => range === RANGE_MINOR || range === RANGE_PATCH; -export const isSemver = (version: string) => { +export const isSemver = (version: string): boolean => { return version.search(/^(~|\^|>=|>|<=|<|)?[0-9]+\.[0-9x]+\.[0-9x]+/) !== -1 && version.indexOf(' ') === -1; }; -export const isLooseSemver = (version: string) => { +export const isLooseSemver = (version: string): boolean => { return isSemver(version) && version.search(/\.x(\.|$)/) !== -1; }; diff --git a/src/commands/lib/log.ts b/src/commands/lib/log.ts index 4a791c4d..31300949 100644 --- a/src/commands/lib/log.ts +++ b/src/commands/lib/log.ts @@ -1 +1,3 @@ -export const log = (...args: any[]) => console.log(...args); +export type Logger = (...args: string[]) => void; + +export const log: Logger = (...args) => console.log(...args); diff --git a/src/commands/lib/write-if-changed.ts b/src/commands/lib/write-if-changed.ts index ae116777..f487450a 100644 --- a/src/commands/lib/write-if-changed.ts +++ b/src/commands/lib/write-if-changed.ts @@ -5,8 +5,8 @@ import { relative } from 'path'; import { SourceWrapper } from './get-wrappers'; import { log } from './log'; -export const writeIfChanged = (indent: string, wrapper: SourceWrapper, mutateContents: (...args: any[]) => any) => { - const toJson = () => `${JSON.stringify(wrapper.contents, null, indent)}${EOL}`; +export const writeIfChanged = (indent: string, wrapper: SourceWrapper, mutateContents: () => void): void => { + const toJson = (): string => `${JSON.stringify(wrapper.contents, null, indent)}${EOL}`; const shortPath = relative(process.cwd(), wrapper.filePath); const before = toJson(); mutateContents(); diff --git a/src/commands/list-mismatches.spec.ts b/src/commands/list-mismatches.spec.ts index 2a2fec5d..69ef6d66 100644 --- a/src/commands/list-mismatches.spec.ts +++ b/src/commands/list-mismatches.spec.ts @@ -1,8 +1,9 @@ import * as mock from '../../test/mock'; +import * as api from './list-mismatches'; describe('listMismatches', () => { - let listMismatches: any; - let log: any; + let listMismatches: typeof api.listMismatches; + let log: jest.Mock; afterEach(() => { jest.restoreAllMocks(); diff --git a/src/commands/list-mismatches.ts b/src/commands/list-mismatches.ts index 8b0ec546..cf6cada0 100644 --- a/src/commands/list-mismatches.ts +++ b/src/commands/list-mismatches.ts @@ -31,7 +31,7 @@ export const listMismatches = ( return mismatches; }; -export const listMismatchesFromDisk = ({ dev, filter, peer, prod, sources: sources }: Options) => { +export const listMismatchesFromDisk = ({ dev, filter, peer, prod, sources: sources }: Options): void | never => { const dependencyTypes = getDependencyTypes({ dev, peer, prod }); const wrappers = getWrappers({ sources }); const mismatches = listMismatches(dependencyTypes, filter, wrappers); diff --git a/src/commands/list.spec.ts b/src/commands/list.spec.ts index 65dff61d..2c081daf 100644 --- a/src/commands/list.spec.ts +++ b/src/commands/list.spec.ts @@ -1,8 +1,9 @@ import * as mock from '../../test/mock'; +import * as api from './list'; describe('list', () => { - let list: any; - let log: any; + let list: typeof api.list; + let log: jest.Mock; afterEach(() => { jest.restoreAllMocks(); diff --git a/src/commands/list.ts b/src/commands/list.ts index ccce351f..38177258 100644 --- a/src/commands/list.ts +++ b/src/commands/list.ts @@ -13,7 +13,7 @@ interface Options { sources: string[]; } -export const list = (dependencyTypes: DependencyType[], filter: RegExp, wrappers: SourceWrapper[]) => { +export const list = (dependencyTypes: DependencyType[], filter: RegExp, wrappers: SourceWrapper[]): void => { const iterator = getDependencies(dependencyTypes, wrappers); const packages = Array.from(iterator).filter(({ name }) => name.search(filter) !== -1); @@ -29,7 +29,7 @@ export const list = (dependencyTypes: DependencyType[], filter: RegExp, wrappers }); }; -export const listFromDisk = ({ dev, filter, peer, prod, sources: sources }: Options) => { +export const listFromDisk = ({ dev, filter, peer, prod, sources: sources }: Options): void => { const dependencyTypes = getDependencyTypes({ dev, peer, prod }); const wrappers = getWrappers({ sources }); diff --git a/src/commands/set-semver-ranges.ts b/src/commands/set-semver-ranges.ts index 2925d56b..63853621 100644 --- a/src/commands/set-semver-ranges.ts +++ b/src/commands/set-semver-ranges.ts @@ -15,7 +15,7 @@ interface Options { sources: string[]; } -export const setSemverRange = (range: string, version: string) => { +export const setSemverRange = (range: string, version: string): string => { if (!isSemver(version) || !isValidSemverRange(range)) { return version; } @@ -32,19 +32,30 @@ export const setSemverRanges = ( dependencyTypes: DependencyType[], filter: RegExp, wrapper: SourceWrapper, -) => { +): void => { const iterator = getDependencies(dependencyTypes, [wrapper]); for (const installedPackage of iterator) { if (installedPackage.name.search(filter) !== -1) { for (const installation of installedPackage.installations) { const { name, type, version } = installation; - installation.source.contents[type][name] = setSemverRange(semverRange, version); + const dependencies = installation.source.contents[type]; + if (dependencies) { + dependencies[name] = setSemverRange(semverRange, version); + } } } } }; -export const setSemverRangesToDisk = ({ dev, filter, indent, peer, prod, semverRange, sources: sources }: Options) => { +export const setSemverRangesToDisk = ({ + dev, + filter, + indent, + peer, + prod, + semverRange, + sources: sources, +}: Options): void => { const dependencyTypes = getDependencyTypes({ dev, peer, prod }); getWrappers({ sources }).forEach((wrapper) => { writeIfChanged(indent, wrapper, () => { diff --git a/src/constants.ts b/src/constants.ts index 2ac13d3b..d1fcd233 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -44,6 +44,8 @@ const MONOREPO_PATTERN = 'package.json'; const PACKAGES_PATTERN = 'packages/*/package.json'; export const ALL_PATTERNS = [MONOREPO_PATTERN, PACKAGES_PATTERN]; +const collect = (value: string, values: string[] = []): string[] => [...values, value]; + interface OptionsByName { dev: [string, string]; filter: [string, string]; @@ -51,7 +53,7 @@ interface OptionsByName { peer: [string, string]; prod: [string, string]; semverRange: [string, string]; - source: [string, string, (...args: any) => any]; + source: [string, string, typeof collect]; } export const option: OptionsByName = { @@ -61,11 +63,5 @@ export const option: OptionsByName = { peer: ['-P, --peer', 'include peerDependencies'], prod: ['-p, --prod', 'include dependencies'], semverRange: ['-r, --semver-range ', `see supported ranges below. defaults to "${DEFAULT_SEMVER_RANGE}"`], - source: [ - '-s, --source [pattern]', - 'glob pattern for package.json files to read from', - function collect(value: string, values: string[] = []) { - return [...values, value]; - }, - ], + source: ['-s, --source [pattern]', 'glob pattern for package.json files to read from', collect], }; diff --git a/test/mock.ts b/test/mock.ts index 30acf6f8..ed70134b 100644 --- a/test/mock.ts +++ b/test/mock.ts @@ -1,7 +1,7 @@ import { SourceWrapper } from '../src/commands/lib/get-wrappers'; -const toObject = (identifiers: string[]) => - identifiers.reduce((memo: any, dep) => { +const toObject = (identifiers: string[]): { [key: string]: string } => + identifiers.reduce<{ [key: string]: string }>((memo, dep) => { const [name, version] = dep.split('@'); memo[name] = version; return memo;