Skip to content

Commit

Permalink
refactor(core): add more verbose logging
Browse files Browse the repository at this point in the history
  • Loading branch information
JamieMason committed Jun 3, 2022
1 parent 25c1836 commit a3edcf2
Show file tree
Hide file tree
Showing 9 changed files with 87 additions and 83 deletions.
2 changes: 1 addition & 1 deletion src/bin-list/list.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ describe('list', () => {
expect(scenario.disk.process.exit).toHaveBeenCalledWith(1);
});

it('lists mismatching pnpm overrides', () => {
it.only('lists mismatching pnpm overrides', () => {
const scenario = scenarios.dependentDoesNotMatchPnpmOverrideVersion();
list(getInput(scenario.disk, scenario.config), scenario.disk);
expect(scenario.log.mock.calls).toEqual([['✕ c 0.1.0, 0.2.0']]);
Expand Down
4 changes: 2 additions & 2 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ export interface VersionGroup {
dependencyTypes?: DependencyType[];
}

export type SyncpackConfig = Readonly<{
export interface SyncpackConfig {
/**
* which dependency properties to search within
*/
Expand Down Expand Up @@ -137,7 +137,7 @@ export type SyncpackConfig = Readonly<{
* your workspace/monorepo as part of the search for versions to sync
*/
workspace: boolean;
}>;
}

export const ALL_PATTERNS = ['package.json', 'packages/*/package.json'];

Expand Down
35 changes: 22 additions & 13 deletions src/lib/get-input/get-instances.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import type {
SyncpackConfig,
VersionGroup,
} from '../../constants';
import { verbose } from '../log';
import type { SourceWrapper } from './get-wrappers';

export interface Instance {
Expand Down Expand Up @@ -46,38 +47,46 @@ export function getInstances(
if (dependencyType === 'workspace') {
const name = wrapper.contents?.name;
const version = wrapper.contents?.version;
addInstance(wrapper, dependencyType, pkgName, name, version);
addInstance({ dependencyType, name, pkgName, version, wrapper });
} else if (dependencyType === 'pnpmOverrides') {
const versionsByName = wrapper.contents?.pnpm?.overrides;
if (!isObject<Record<string, string>>(versionsByName)) continue;
const pkgs = Object.entries(versionsByName);
for (const [name, version] of pkgs) {
addInstance(wrapper, dependencyType, pkgName, name, version);
addInstance({ dependencyType, name, pkgName, version, wrapper });
}
} else {
const versionsByName = wrapper.contents?.[dependencyType];
if (!isObject<Record<string, string>>(versionsByName)) continue;
const pkgs = Object.entries(versionsByName);
for (const [name, version] of pkgs) {
addInstance(wrapper, dependencyType, pkgName, name, version);
addInstance({ dependencyType, name, pkgName, version, wrapper });
}
}
}
}

return allInstances;

function addInstance(
wrapper: SourceWrapper,
dependencyType: DependencyType,
pkgName: string,
name?: string,
version?: string,
): void {
if (!isNonEmptyString(name)) return;
if (name.search(new RegExp(options.filter)) === -1) return;
if (!isNonEmptyString(version)) return;
function addInstance(input: {
dependencyType: DependencyType;
name?: string;
pkgName: string;
version?: string;
wrapper: SourceWrapper;
}): void {
const { dependencyType, name, pkgName, version, wrapper } = input;
if (!isNonEmptyString(name)) {
return verbose('skip instance, no name', input);
}
if (name.search(new RegExp(options.filter)) === -1) {
return verbose('skip instance, name does not match filter', input);
}
if (!isNonEmptyString(version)) {
return verbose('skip instance, no version', input);
}
const instance = { dependencyType, name, version, wrapper };
verbose(`add ${name}@${version} to ${dependencyType} ${wrapper.filePath}`);
allInstances.all.push(instance);
groupInstancesBy('semverGroups', dependencyType, pkgName, instance);
groupInstancesBy('versionGroups', dependencyType, pkgName, instance);
Expand Down
44 changes: 15 additions & 29 deletions src/lib/get-input/get-wrappers/get-file-paths.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
import { isArrayOfStrings } from 'expect-more';
import * as A from 'fp-ts/lib/Array';
import * as E from 'fp-ts/lib/Either';
import { flow, pipe } from 'fp-ts/lib/function';
import * as O from 'fp-ts/lib/Option';
import * as S from 'fp-ts/lib/string';
import type { SyncpackConfig } from '../../../constants';
import type { Disk } from '../../../lib/disk';
import { getPatterns } from './get-patterns';
import { removeReadonlyType } from './readonly';
import { tapNone } from './tap';
import { tapOption } from './tap';
import { getErrorOrElse } from './try-catch';

type MaybeFilePaths = O.Option<string[]>;
type EitherMaybeFilePaths = E.Either<Error, MaybeFilePaths>;

/**
* Using --source options and/or config files on disk from npm/pnpm/yarn/lerna,
* return an array of absolute paths to every package.json file the user is
Expand All @@ -22,44 +21,31 @@ type EitherMaybeFilePaths = E.Either<Error, MaybeFilePaths>;
export function getFilePaths(
disk: Disk,
program: SyncpackConfig,
): EitherMaybeFilePaths {
): E.Either<Error, O.Option<string[]>> {
return pipe(
getPatterns(disk, program),
program,
getPatterns(disk),
O.getOrElse<string[]>(() => []),
E.traverseArray(resolvePattern),
E.map(
flow(
removeReadonlyType,
mergeArrayOfOptionsIntoOne,
O.filter(isArrayOfStrings),
),
),
E.map(removeReadonlyType),
E.map(flow(A.flatten, A.uniq(S.Eq))),
E.map(O.fromPredicate(isArrayOfStrings)),
E.map(tapOption<string[]>('package.json files found')),
);

function resolvePattern(pattern: string): EitherMaybeFilePaths {
function resolvePattern(pattern: string): E.Either<Error, string[]> {
return pipe(
E.tryCatch(
() => disk.globSync(pattern),
getErrorOrElse(`npm package "glob" threw on pattern "${pattern}"`),
),
E.map(
flow(
O.of,
O.filter(isArrayOfStrings),
tapNone<string[]>(`found 0 files matching pattern "${pattern}"`),
O.fromPredicate(isArrayOfStrings),
tapOption(`files found matching pattern "${pattern}"`),
O.getOrElse<string[]>(() => []),
),
),
);
}

function mergeArrayOfOptionsIntoOne(
options: MaybeFilePaths[],
): MaybeFilePaths {
const unwrap = O.getOrElse<string[]>(() => []);
return O.of(
options.reduce<string[]>(
(values, option) => values.concat(unwrap(option)),
[],
),
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,18 @@ import * as E from 'fp-ts/lib/Either';
import { flow, pipe } from 'fp-ts/lib/function';
import * as O from 'fp-ts/lib/Option';
import { join } from 'path';
import type { MaybePatterns } from '.';
import { CWD } from '../../../../constants';
import type { Disk } from '../../../../lib/disk';
import { props } from './props';
import { readJsonSafe } from './read-json-safe';

export function getLernaPatterns(disk: Disk): () => MaybePatterns {
export function getLernaPatterns(disk: Disk): () => O.Option<string[]> {
return () =>
pipe(
readJsonSafe(disk)(join(CWD, 'lerna.json')),
E.map(flow(props('contents.packages'), O.filter(isArrayOfStrings))),
E.match(
(): MaybePatterns => O.none,
(): O.Option<string[]> => O.none,
(value) => value,
),
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import * as E from 'fp-ts/lib/Either';
import { flow, pipe } from 'fp-ts/lib/function';
import * as O from 'fp-ts/lib/Option';
import { join } from 'path';
import type { MaybePatterns } from '.';
import { CWD } from '../../../../constants';
import type { Disk } from '../../../../lib/disk';
import { props } from './props';
Expand All @@ -13,7 +12,7 @@ interface PnpmWorkspace {
packages?: string[];
}

export function getPnpmPatterns(disk: Disk): () => MaybePatterns {
export function getPnpmPatterns(disk: Disk): () => O.Option<string[]> {
return () =>
pipe(
// packages:
Expand All @@ -23,7 +22,7 @@ export function getPnpmPatterns(disk: Disk): () => MaybePatterns {
readYamlSafe<PnpmWorkspace>(disk)(join(CWD, 'pnpm-workspace.yaml')),
E.map(flow(props('packages'), O.filter(isArrayOfStrings))),
E.match(
(): MaybePatterns => O.none,
(): O.Option<string[]> => O.none,
(value) => value,
),
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,13 @@ import * as E from 'fp-ts/lib/Either';
import { pipe } from 'fp-ts/lib/function';
import * as O from 'fp-ts/lib/Option';
import { join } from 'path';
import type { MaybePatterns } from '.';
import type { Source } from '..';
import { CWD } from '../../../../constants';
import type { Disk } from '../../../../lib/disk';
import { props } from './props';
import { readJsonSafe } from './read-json-safe';

export function getYarnPatterns(disk: Disk): () => MaybePatterns {
export function getYarnPatterns(disk: Disk): () => O.Option<string[]> {
return () =>
pipe(
readJsonSafe(disk)(join(CWD, 'package.json')),
Expand All @@ -19,14 +18,14 @@ export function getYarnPatterns(disk: Disk): () => MaybePatterns {
O.flatten,
);

function findPackages(yarn: Source): MaybePatterns {
function findPackages(yarn: Source): O.Option<string[]> {
return pipe(
getArrayOfStrings('workspaces', yarn),
O.fold(() => getArrayOfStrings('workspaces.packages', yarn), O.some),
);
}

function getArrayOfStrings(paths: string, yarn: Source): MaybePatterns {
function getArrayOfStrings(paths: string, yarn: Source): O.Option<string[]> {
return pipe(yarn, props(paths), O.filter(isArrayOfStrings));
}
}
46 changes: 19 additions & 27 deletions src/lib/get-input/get-wrappers/get-patterns/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,47 +4,39 @@ import * as O from 'fp-ts/lib/Option';
import type { SyncpackConfig } from '../../../../constants';
import { ALL_PATTERNS } from '../../../../constants';
import type { Disk } from '../../../../lib/disk';
import { tapNone } from '../tap';
import { tapNone, tapOption } from '../tap';
import { getLernaPatterns } from './get-lerna-patterns';
import { getPnpmPatterns } from './get-pnpm-patterns';
import { getYarnPatterns } from './get-yarn-patterns';

type Patterns = string[];

export type MaybePatterns = O.Option<Patterns>;

/**
* Find every glob pattern which should be used to find package.json files for
* this monorepo.
*
* @returns `['./package.json', './packages/* /package.json']`
*/
export function getPatterns(disk: Disk, program: SyncpackConfig): Patterns {
return pipe(
O.of(program.source),
O.filter(isArrayOfStrings),
tapNone<Patterns>('no --source patterns found'),
O.fold(
flow(
getYarnPatterns(disk),
tapNone<Patterns>('no yarn workspaces found'),
O.fold(getPnpmPatterns(disk), O.of),
tapNone<Patterns>('no pnpm workspaces found'),
O.fold(getLernaPatterns(disk), O.of),
tapNone<Patterns>('no lerna packages found'),
O.map(flow(addRootDir, limitToPackageJson)),
),
O.of,
),
tapNone<Patterns>('no patterns found, using defaults'),
O.getOrElse(() => ALL_PATTERNS),
);
export function getPatterns(disk: Disk) {
return (program: SyncpackConfig): O.Option<string[]> =>
pipe(
O.of(program.source),
O.filter(isArrayOfStrings),
tapOption('--source patterns found'),
O.fold(flow(getYarnPatterns(disk), O.map(addRootDir)), O.of),
tapOption('yarn workspaces found'),
O.fold(flow(getPnpmPatterns(disk), O.map(addRootDir)), O.of),
tapOption('pnpm workspaces found'),
O.fold(flow(getLernaPatterns(disk), O.map(addRootDir)), O.of),
tapOption('lerna packages found'),
O.map(limitToPackageJson),
tapNone('no patterns found, using defaults'),
O.fold(() => O.some(ALL_PATTERNS), O.of),
);

function addRootDir(patterns: Patterns): Patterns {
function addRootDir(patterns: string[]): string[] {
return ['.', ...patterns];
}

function limitToPackageJson(patterns: Patterns): Patterns {
function limitToPackageJson(patterns: string[]): string[] {
return patterns.map((pattern) =>
pattern.includes('package.json') ? pattern : `${pattern}/package.json`,
);
Expand Down
22 changes: 21 additions & 1 deletion src/lib/get-input/get-wrappers/tap.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,32 @@
import { flow } from 'fp-ts/lib/function';
import * as O from 'fp-ts/lib/Option';
import { verbose } from '../../log';

type Fn<T> = (ma: O.Option<T>) => O.Option<T>;

/**
* Log a message when a pipeline contains `None` and let it continue unchanged.
*/
export function tapNone<T>(message: string): (ma: O.Option<T>) => O.Option<T> {
export function tapNone<T>(message: string): Fn<T> {
return O.fold<T, O.Option<T>>(function logNoneValue() {
verbose(message);
return O.none;
}, O.of);
}

/**
* Log a message when a pipeline contains `Some` and let it continue unchanged.
*/
export function tapSome<T>(message: string): Fn<T> {
return O.map(function logSomeValue(value) {
verbose(message, value);
return value;
});
}

/**
* Log both possibilities of an `Option` and let it continue unchanged.
*/
export function tapOption<T>(message: string): Fn<T> {
return flow(tapSome(message), tapNone(`no ${message}`));
}

0 comments on commit a3edcf2

Please sign in to comment.