Skip to content

Commit

Permalink
refactor(versions): replace how versions are read/written
Browse files Browse the repository at this point in the history
  • Loading branch information
JamieMason committed Feb 13, 2023
1 parent 240685e commit e02bc87
Show file tree
Hide file tree
Showing 36 changed files with 926 additions and 262 deletions.
4 changes: 2 additions & 2 deletions src/bin-lint-semver-ranges/lint-semver-ranges-cli.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ describe('lintSemverRanges', () => {
['✘ c'],
[` 0.1.0 → ~0.1.0 in overrides of ${a}`],
['✘ d'],
[` 0.1.0 → ~0.1.0 in pnpmOverrides of ${a}`],
[` 0.1.0 → ~0.1.0 in pnpm.overrides of ${a}`],
['✘ e'],
[` 0.1.0 → ~0.1.0 in peerDependencies of ${a}`],
['✘ f'],
Expand All @@ -36,7 +36,7 @@ describe('lintSemverRanges', () => {
['✘ c'],
[` 0.1.0 → * in overrides of ${a}`],
['✘ d'],
[` 0.1.0 → * in pnpmOverrides of ${a}`],
[` 0.1.0 → * in pnpm.overrides of ${a}`],
['✘ e'],
[` 0.1.0 → * in peerDependencies of ${a}`],
['✘ f'],
Expand Down
4 changes: 2 additions & 2 deletions src/bin-lint-semver-ranges/lint-semver-ranges.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,11 @@ export function lintSemverRanges(ctx: Syncpack.Ctx): Syncpack.Ctx {
}

function logSemverRangeMismatch(instance: Instance, semverGroup: SemverGroup) {
const type = instance.dependencyType;
const path = instance.pathDef.path;
const shortPath = instance.packageJsonFile.shortPath;
const actual = instance.version;
const expected = setSemverRange(semverGroup.range, actual);
console.log(
chalk` {red ${actual}} ${ICON.rightArrow} {green ${expected}} {dim in ${type} of ${shortPath}}`,
chalk` {red ${actual}} ${ICON.rightArrow} {green ${expected}} {dim in ${path} of ${shortPath}}`,
);
}
2 changes: 1 addition & 1 deletion src/bin-list-mismatches/list-mismatches.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ export function listMismatches(ctx: Syncpack.Ctx): Syncpack.Ctx {
}

function logVersionMismatch(instance: Instance): void {
const type = instance.dependencyType;
const type = instance.pathDef.path;
const shortPath = instance.packageJsonFile.shortPath;
const actual = instance.version;
console.log(chalk` {red ${actual}} {dim in ${type} of ${shortPath}}`);
Expand Down
14 changes: 0 additions & 14 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,6 @@ export const ICON = {
tick: '✓',
} as const;

/**
* Aliases for locations of versions within package.json files, it is looped
* over by each command to operate on each are as defined by the user.
*/
export const ALL_DEPENDENCY_TYPES = [
'dependencies',
'devDependencies',
'overrides',
'peerDependencies',
'pnpmOverrides',
'resolutions',
'workspace',
] as const;

export const RANGE = {
ANY: '*',
EXACT: '',
Expand Down
6 changes: 6 additions & 0 deletions src/get-context/$R.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { R } from '@mobily/ts-belt';
import { BaseError } from '../lib/error';
import { verbose } from '../lib/log';

/** Additional helpers for https://mobily.github.io/ts-belt/api/result */
export const $R = {
Expand All @@ -23,4 +24,9 @@ export const $R = {
: R.Error(new BaseError('No R.Ok() returned by $R.onlyOk'));
};
},
/** Log verbose only when R.Result is an R.Err */
tapErrVerbose<T extends R.Result<unknown, BaseError>>(result: T) {
if (R.isError(result)) verbose(result._0.message);
return result;
},
};
94 changes: 94 additions & 0 deletions src/get-context/get-config/get-core-paths.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import 'expect-more-jest';
import { getCorePaths } from './get-core-paths';

describe('getCorePaths', () => {
const fn = getCorePaths;
const dev = {
name: 'dev',
path: 'devDependencies',
strategy: 'versionsByName',
};

const overrides = {
name: 'overrides',
path: 'overrides',
strategy: 'versionsByName',
};

const peer = {
name: 'peer',
path: 'peerDependencies',
strategy: 'versionsByName',
};

const pnpmOverrides = {
name: 'pnpmOverrides',
path: 'pnpm.overrides',
strategy: 'versionsByName',
};

const prod = {
name: 'prod',
path: 'dependencies',
strategy: 'versionsByName',
};

const resolutions = {
name: 'resolutions',
path: 'resolutions',
strategy: 'versionsByName',
};

const workspace = {
name: 'workspace',
namePath: 'name',
path: 'version',
strategy: 'name~version',
};

const allTypes = [
dev,
overrides,
peer,
pnpmOverrides,
prod,
resolutions,
workspace,
];

it('includes all if none are set', () => {
expect(
fn({
dev: true,
overrides: true,
peer: true,
pnpmOverrides: true,
prod: true,
resolutions: true,
workspace: true,
}),
).toEqual(allTypes);
});

it('includes all if all are set', () => {
expect(fn({})).toEqual(allTypes);
});

it('enables one if it is the only one set', () => {
expect(fn({ dev: true })).toEqual([dev]);
expect(fn({ overrides: true })).toEqual([overrides]);
expect(fn({ peer: true })).toEqual([peer]);
expect(fn({ pnpmOverrides: true })).toEqual([pnpmOverrides]);
expect(fn({ prod: true })).toEqual([prod]);
expect(fn({ resolutions: true })).toEqual([resolutions]);
expect(fn({ workspace: true })).toEqual([workspace]);
});

it('enables some if only those are set', () => {
expect(fn({ dev: true, prod: true, workspace: true })).toEqual([
dev,
prod,
workspace,
]);
});
});
54 changes: 54 additions & 0 deletions src/get-context/get-config/get-core-paths.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { isBoolean, isObject } from 'expect-more';
import type { Syncpack } from '../../types';

type CorePaths = typeof corePaths;
export type CorePathName = keyof CorePaths;

const corePaths = {
dev: {
path: 'devDependencies',
strategy: 'versionsByName',
},
overrides: {
path: 'overrides',
strategy: 'versionsByName',
},
peer: {
path: 'peerDependencies',
strategy: 'versionsByName',
},
pnpmOverrides: {
path: 'pnpm.overrides',
strategy: 'versionsByName',
},
prod: {
path: 'dependencies',
strategy: 'versionsByName',
},
resolutions: {
path: 'resolutions',
strategy: 'versionsByName',
},
workspace: {
namePath: 'name',
path: 'version',
strategy: 'name~version',
},
} as const;

export function getCorePaths(
fromCli: Pick<Partial<Syncpack.Config.Cli>, CorePathName>,
): Syncpack.PathDefinition[] {
const corePathNames = Object.keys(corePaths) as CorePathName[];
const hasOverride = corePathNames.some((name) => isBoolean(fromCli[name]));

return corePathNames
.filter((name) => !hasOverride || fromCli[name] === true)
.map(getByName)
.filter(isObject<Syncpack.PathDefinition>);

function getByName(key: CorePathName): Syncpack.PathDefinition | undefined {
const obj = corePaths[key];
if (obj) return { ...obj, name: key };
}
}
42 changes: 0 additions & 42 deletions src/get-context/get-config/get-dependency-types.ts

This file was deleted.

9 changes: 6 additions & 3 deletions src/get-context/get-config/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { Disk } from '../../lib/disk';
import { verbose } from '../../lib/log';
import type { Syncpack } from '../../types';
import { getDependencyTypes } from './get-dependency-types';
import { getCorePaths } from './get-core-paths';
import * as ConfigSchema from './schema';

/**
Expand All @@ -16,9 +16,10 @@ export const getConfig = (

const fromRcFile = disk.readConfigFileSync(fromCli.configPath);

verbose('rcfile contents:', fromCli);
verbose('rcfile contents:', fromRcFile);

const fromPublic = ConfigSchema.Public.parse({
customPaths: getConfigByName('customPaths'),
dev: getConfigByName('dev'),
filter: getConfigByName('filter'),
indent: getConfigByName('indent'),
Expand All @@ -36,8 +37,11 @@ export const getConfig = (
workspace: getConfigByName('workspace'),
});

verbose('user config:', fromPublic);

const allConfig = ConfigSchema.Private.parse({
...fromPublic,
corePaths: getCorePaths(fromCli),
defaultSemverGroup: {
dependencies: ['**'],
isDefault: true,
Expand All @@ -49,7 +53,6 @@ export const getConfig = (
isDefault: true,
packages: ['**'],
},
dependencyTypes: getDependencyTypes(fromCli, fromPublic),
});

allConfig.semverGroups.push(allConfig.defaultSemverGroup);
Expand Down
18 changes: 18 additions & 0 deletions src/get-context/get-config/path-strategy/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { BaseError } from '../../../lib/error';
import { nameAndVersionProps } from './name-and-version-props';
import { nameAndVersionString } from './name-and-version-string';
import { versionString } from './version-string';
import { versionsByName } from './versions-by-name';

export type StrategyByName = typeof strategyByName;

export const strategyByName = {
'name@version': nameAndVersionString,
'name~version': nameAndVersionProps,
'version': versionString,
'versionsByName': versionsByName,
} as const;

export function exhaustiveCheck(strategyName: never): never {
throw new BaseError(`Unrecognised strategy "${strategyName}"`);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import type { R } from '@mobily/ts-belt';
import { O, pipe } from '@mobily/ts-belt';
import { isNonEmptyString } from 'expect-more';
import { BaseError } from '../../../../lib/error';
import { props } from '../../../get-package-json-files/get-patterns/props';
import type { PackageJsonFile } from '../../../get-package-json-files/package-json-file';

// const root: any = this.packageJsonFile.contents;
// if (this.pathDef.name === 'pnpmOverrides') {
// root.pnpm.overrides[this.name] = version;
// } else if (this.pathDef.name !== 'workspace') {
// root[(this.pathDef as any).path][this.name] = version;
// }

export function getNonEmptyStringProp(
propPath: string,
file: PackageJsonFile,
): R.Result<string, BaseError> {
return pipe(
file.contents,
props(propPath, isNonEmptyString),
O.toResult<string, BaseError>(
new BaseError(`Failed to get ${propPath} in ${file.shortPath}`),
),
);
}

0 comments on commit e02bc87

Please sign in to comment.