UNPKG

syncpack

Version:

Consistent dependency versions in large JavaScript Monorepos

53 lines (52 loc) 2.87 kB
import { Effect, Option, pipe } from 'effect'; import { isNonEmptyObject } from 'tightrope/guard/is-non-empty-object.js'; import { isNonEmptyString } from 'tightrope/guard/is-non-empty-string.js'; import { get } from '../lib/get.js'; import { DELETE } from '../version-group/lib/delete.js'; import { getNonEmptyStringProp } from './lib/get-non-empty-string-prop.js'; const getOptionOfNonEmptyString = Option.liftPredicate(isNonEmptyString); const getOptionOfNonEmptyObject = Option.liftPredicate((isNonEmptyObject)); export class NamedVersionStringStrategy { _tag = 'name@version'; name; path; constructor(name, path) { this.name = name; this.path = path; } read(file) { const path = this.path; return pipe( // get version prop getNonEmptyStringProp(path, file), // if it is a non empty string, we can read it Effect.map(value => value.split(/@(.*)/)), // check the string was properly formed Effect.flatMap(([name, version]) => Effect.all([ getOptionOfNonEmptyString(name), getOptionOfNonEmptyString(version), ])), // return an array of one entry if valid Effect.map(([name, version]) => [[name, version]]), Effect.tapError(() => Effect.logDebug(`NamedVersionStringStrategy#${this.name} found nothing at <${file.jsonFile.shortPath}>.${this.path}`)), // if value is invalid, default to empty Effect.catchAll(() => Effect.succeed([]))); } write(file, [name, version]) { const { contents } = file.jsonFile; const isNestedPath = this.path.includes('.'); const nextValue = version === DELETE ? undefined : `${name}@${version}`; if (isNestedPath) { const fullPath = this.path.split('.'); const pathToParent = fullPath.slice(0, fullPath.length - 1).join('.'); const key = fullPath.slice(-1).join(''); return pipe(get(contents, ...pathToParent.split('.')), Effect.flatMap(getOptionOfNonEmptyObject), Effect.flatMap(parent => Effect.try(() => { parent[key] = nextValue; file.applyEdit(fullPath, nextValue); })), Effect.tapError(() => Effect.logDebug(`strategy ${this._tag} with name ${this.name} failed to write to <${file.jsonFile.shortPath}>.${this.path}`)), Effect.catchAll(() => Effect.succeed(file)), Effect.map(() => file)); } return pipe(getOptionOfNonEmptyObject(contents), Effect.flatMap(parent => Effect.try(() => { parent[this.path] = nextValue; file.applyEdit([this.path], nextValue); })), Effect.tapError(() => Effect.logDebug(`strategy ${this._tag} with name ${this.name} failed to write to <${file.jsonFile.shortPath}>.${this.path}`)), Effect.catchAll(() => Effect.succeed(file)), Effect.map(() => file)); } }