JamieMason/syncpack

View on GitHub
src/semver-group/with-range.ts

Summary

Maintainability
A
25 mins
Test Coverage
A
100%
import { Data, Effect, pipe } from 'effect';
import type { SemverGroupConfig } from '../config/types.js';
import type { Instance } from '../get-instances/instance.js';
import { setSemverRange } from '../lib/set-semver-range.js';
import { Report } from '../report.js';
import { Specifier } from '../specifier/index.js';
import type { NonSemverError } from '../specifier/lib/non-semver-error.js';

export class WithRangeSemverGroup extends Data.TaggedClass('WithRange')<{
  config: SemverGroupConfig.WithRange;
  instances: Instance[];
  isCatchAll: boolean;
}> {
  groupType = 'semverGroup';

  constructor(isCatchAll: boolean, config: SemverGroupConfig.WithRange) {
    super({
      config,
      instances: [],
      isCatchAll,
    });
    this.getFixed = this.getFixed.bind(this);
  }

  canAdd(_: Instance): boolean {
    return true;
  }

  getFixed(specifier: Specifier.Any): Effect.Effect<Specifier.Any, NonSemverError> {
    return pipe(
      specifier.getSemver(),
      Effect.map((semver) => setSemverRange(this.config.range, semver)),
      Effect.flatMap((nextSemver) => specifier.setSemver(nextSemver)),
    );
  }

  inspectAll() {
    return Effect.all(this.instances.map((instance) => this.inspect(instance)));
  }

  inspect(
    instance: Instance,
  ): Effect.Effect<Report.UnsupportedMismatch | Report.SemverRangeMismatch | Report.Valid> {
    const current = Specifier.create(instance, instance.rawSpecifier.raw);
    return pipe(
      this.getFixed(current),
      Effect.match({
        // if range is fixable
        onSuccess: (valid) =>
          // if it is pinned and matches its pin
          instance.versionGroup._tag === 'Pinned' &&
          instance.rawSpecifier.raw === instance.versionGroup.config.pinVersion
            ? // the pinned version takes precendence and is a match
              new Report.Valid(current)
            : // if it is already like this on disk
              instance.rawSpecifier.raw === valid.raw
              ? // it is a match
                new Report.Valid(current)
              : // it is a mismatch and should be this one
                new Report.SemverRangeMismatch(valid),

        // if range is NOT fixable, it is a mismatch we can't auto-fix
        // as it seems to not be semver
        onFailure: () => new Report.UnsupportedMismatch(instance),
      }),
    );
  }
}