Skip to content

Commit

Permalink
fix(local): allow missing .version if not depended on
Browse files Browse the repository at this point in the history
Closes #183
  • Loading branch information
JamieMason committed Dec 29, 2023
1 parent 45f1731 commit 419a254
Show file tree
Hide file tree
Showing 2 changed files with 175 additions and 107 deletions.
164 changes: 116 additions & 48 deletions src/version-group/standard.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,67 +9,133 @@ import { list } from '../bin-list/list';

describe('the "local" dependency type', () => {
describe('when local package is missing a version property', () => {
const getScenario = createScenario({
'.syncpackrc': {
dependencyTypes: ['local', 'prod'],
},
'package.json': {
name: 'foo',
},
'packages/a/package.json': {
name: 'a',
dependencies: {
foo: '0.2.0',
describe('when local package IS depended on', () => {
const getScenario = createScenario({
'.syncpackrc': {
dependencyTypes: ['local', 'prod'],
},
},
});
'package.json': {
name: 'foo',
},
'packages/a/package.json': {
name: 'a',
dependencies: {
foo: '0.2.0',
},
},
});

describe('version report', () => {
it('is broken and unfixable', () => {
const reports = getScenario().getVersionReports();
expect(reports).toHaveLength(2);
expect(reports).toHaveProperty('1.name', 'foo');
expect(reports).toHaveProperty('0.reports.0._tag', 'MissingLocalVersion');
describe('version report', () => {
it('is broken and unfixable', () => {
const reports = getScenario().getVersionReports();
expect(reports).toHaveLength(2);
expect(reports).toHaveProperty('1.name', 'foo');
expect(reports).toHaveProperty('1.reports.0._tag', 'MissingLocalVersion');
expect(reports).toHaveProperty('1.reports.1._tag', 'MissingLocalVersion');
});
});
});

describe('lint', () => {
it('exits 1', () => {
const scenario = getScenario();
Effect.runSyncExit(lint(scenario));
expect(scenario.io.process.exit).toHaveBeenCalledWith(1);
describe('lint', () => {
it('exits 1', () => {
const scenario = getScenario();
Effect.runSyncExit(lint(scenario));
expect(scenario.io.process.exit).toHaveBeenCalledWith(1);
});
});
});

describe('lintSemverRanges', () => {
it('exits 0', () => {
const scenario = getScenario();
Effect.runSyncExit(lintSemverRanges(scenario));
expect(scenario.io.process.exit).not.toHaveBeenCalled();
describe('lintSemverRanges', () => {
it('exits 0', () => {
const scenario = getScenario();
Effect.runSyncExit(lintSemverRanges(scenario));
expect(scenario.io.process.exit).not.toHaveBeenCalled();
});
});
});

describe('list', () => {
it('exits 1', () => {
const scenario = getScenario();
Effect.runSyncExit(list(scenario));
expect(scenario.io.process.exit).toHaveBeenCalledWith(1);
describe('list', () => {
it('exits 1', () => {
const scenario = getScenario();
Effect.runSyncExit(list(scenario));
expect(scenario.io.process.exit).toHaveBeenCalledWith(1);
});
});
});

describe('list-mismatches', () => {
it('exits 1', () => {
const scenario = getScenario();
Effect.runSyncExit(listMismatches(scenario));
expect(scenario.io.process.exit).toHaveBeenCalledWith(1);
describe('list-mismatches', () => {
it('exits 1', () => {
const scenario = getScenario();
Effect.runSyncExit(listMismatches(scenario));
expect(scenario.io.process.exit).toHaveBeenCalledWith(1);
});
});

describe('fix-mismatches', () => {
it('exits 1', () => {
const scenario = getScenario();
Effect.runSyncExit(fixMismatches(scenario));
expect(scenario.io.process.exit).toHaveBeenCalledWith(1);
});
});
});

describe('fix-mismatches', () => {
it('exits 1', () => {
const scenario = getScenario();
Effect.runSyncExit(fixMismatches(scenario));
expect(scenario.io.process.exit).toHaveBeenCalledWith(1);
describe('when local package is NOT depended on', () => {
const getScenario = createScenario({
'.syncpackrc': {
dependencyTypes: ['local', 'prod'],
},
'package.json': {
name: 'foo',
},
'packages/a/package.json': {
name: 'a',
},
});

describe('version report', () => {
it('is valid', () => {
const reports = getScenario().getVersionReports();
expect(reports).toHaveLength(2);
expect(reports).toHaveProperty('1.name', 'foo');
expect(reports).toHaveProperty('1.reports.0._tag', 'Valid');
});
});

describe('lint', () => {
it('exits 0', () => {
const scenario = getScenario();
Effect.runSyncExit(lint(scenario));
expect(scenario.io.process.exit).not.toHaveBeenCalled();
});
});

describe('lintSemverRanges', () => {
it('exits 0', () => {
const scenario = getScenario();
Effect.runSyncExit(lintSemverRanges(scenario));
expect(scenario.io.process.exit).not.toHaveBeenCalled();
});
});

describe('list', () => {
it('exits 0', () => {
const scenario = getScenario();
Effect.runSyncExit(list(scenario));
expect(scenario.io.process.exit).not.toHaveBeenCalled();
});
});

describe('list-mismatches', () => {
it('exits 0', () => {
const scenario = getScenario();
Effect.runSyncExit(listMismatches(scenario));
expect(scenario.io.process.exit).not.toHaveBeenCalled();
});
});

describe('fix-mismatches', () => {
it('exits 0', () => {
const scenario = getScenario();
Effect.runSyncExit(fixMismatches(scenario));
expect(scenario.io.process.exit).not.toHaveBeenCalled();
});
});
});
});
Expand Down Expand Up @@ -98,6 +164,8 @@ describe('the "local" dependency type', () => {
expect(reports).toHaveProperty('1.name', 'foo');
expect(reports).toHaveProperty('1.reports.0._tag', 'MissingLocalVersion');
expect(reports).toHaveProperty('1.reports.0.unfixable.rawSpecifier', '~0.2.0');
expect(reports).toHaveProperty('1.reports.1._tag', 'MissingLocalVersion');
expect(reports).toHaveProperty('1.reports.1.unfixable.rawSpecifier', '~0.2.0');
});
});

Expand Down
118 changes: 59 additions & 59 deletions src/version-group/standard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,66 +33,66 @@ export class StandardVersionGroup extends Data.TaggedClass('Standard')<{

if (localInstance) {
const localVersion = localInstance?.rawSpecifier;
return localVersion === 'PACKAGE_JSON_HAS_NO_VERSION'
? Effect.succeed({
name,
reports: instances.map(
(instance) =>
// ! dependency is a package developed in this repo
// ✘ local package is missing a .version property
// ✘ is a mismatch we can't auto-fix
new Report.MissingLocalVersion(instance, localInstance),
),
})
: pipe(
Effect.succeed(Specifier.create(localInstance, localVersion)),
Effect.flatMap((local) =>
Effect.all(
local._tag !== 'VersionSpecifier'
? instances.map((instance) =>
// ! dependency is a package developed in this repo
// ✘ local package has an invalid .version property
// ✘ is a mismatch we can't auto-fix
Effect.succeed(new Report.MissingLocalVersion(instance, localInstance)),
)
: instances.flatMap((instance) =>
pipe(
Effect.succeed(Specifier.create(instance, instance.rawSpecifier)),
Effect.flatMap((specifier) =>
specifier.instance === localInstance
? // ✓ this is the local package which the others should match
// ! its version must always remain as exact semver
// ! other instances need to be adjusted for their semver groups
Effect.succeed(new Report.Valid(specifier))
: pipe(
specifier.replaceWith(local),
specifier.instance.semverGroup.getFixed,
Effect.match({
onFailure: /* istanbul ignore next */ () =>
// ! is not the local package instance
// ✘ local version is not fixable by this semver group
// ✘ is a mismatch we can't auto-fix
// ✘ this should be impossible - we already proved the local version is exact semver
new Report.UnsupportedMismatch(specifier.instance),
onSuccess: (valid) =>
specifier.instance.rawSpecifier === valid.raw
? // ! is not the local package instance
// ✓ local version matches this semver group
// ✓ current version matches local
new Report.Valid(specifier)
: // ! is not the local package instance
// ✓ local version matches this semver group
// ✘ current version mismatches local
new Report.LocalPackageMismatch(valid, localInstance),
}),
),
),
),
return pipe(
Effect.succeed(Specifier.create(localInstance, localVersion)),
Effect.flatMap((local) =>
Effect.all(
local._tag !== 'VersionSpecifier' && instances.length > 1
? instances.map((instance) =>
// ! dependency is a package developed in this repo
// ✘ local package has an invalid .version property
// ✘ is a mismatch we can't auto-fix
Effect.succeed(new Report.MissingLocalVersion(instance, localInstance)),
)
: instances.flatMap((instance) =>
// instances.flatMap((instance) =>
pipe(
Effect.succeed(Specifier.create(instance, instance.rawSpecifier)),
Effect.flatMap((specifier) =>
specifier.instance === localInstance
? // ✓ this is the local package which the others should match
// ! its version must always remain as exact semver
// ! other instances need to be adjusted for their semver groups
Effect.succeed(new Report.Valid(specifier))
: pipe(
specifier.replaceWith(local),
specifier.instance.semverGroup.getFixed,
Effect.match({
onFailure: /* istanbul ignore next */ () =>
// ! is not the local package instance
// ✘ local version is not fixable by this semver group
// ✘ is a mismatch we can't auto-fix
// ✘ this should be impossible - we already proved the local version is exact semver
new Report.UnsupportedMismatch(specifier.instance),
onSuccess: (valid) =>
specifier.instance.rawSpecifier === valid.raw
? // ! is not the local package instance
// ✓ local version matches this semver group
// ✓ current version matches local
new Report.Valid(specifier)
: localVersion === 'PACKAGE_JSON_HAS_NO_VERSION'
? // ! is not the local package instance
// ✘ local package has a version defined
// ✓ local version matches this semver group
// ✘ current version mismatches local
new Report.MissingLocalVersion(
specifier.instance,
localInstance,
)
: // ! is not the local package instance
// ✓ local package has a version defined
// ✓ local version matches this semver group
// ✘ current version mismatches local
new Report.LocalPackageMismatch(valid, localInstance),
}),
),
),
),
),
Effect.map((reports) => ({ name, reports })),
);
),
),
),
),
Effect.map((reports) => ({ name, reports })),
);
}

const PreferredMismatch =
Expand Down

0 comments on commit 419a254

Please sign in to comment.