1.0.6 β€’ Published 12 months ago

@randajan/revert v1.0.6

Weekly downloads
-
License
MIT
Repository
github
Last release
12 months ago

@randajan/revert

NPM JavaScript Style Guide

Reversible, reliable, readable.
A tiny utility for managing forward-backward processes with automatic rollback on error.

Supports both synchronous and asynchronous workflows with optional value passing between steps.


πŸ“¦ Installation

npm install @randajan/revert

or

yarn install @randajan/revert

🧭 Package Variants

Package PathTypeDescription
@randajan/revert/asyncESM / CJSAsynchronous version with logging, flow, utils
@randajan/revert/async/utilsESM / CJSUtility functions: revertable, sleep, attempt
@randajan/revert/syncESM / CJSSynchronous version of the core logic
@randajan/revert/sync/utilsESM / CJSSync utilities: revertable only (no sleep, attempt)

πŸš€ Quick Example

import { Revertable } from "@randajan/revert/async";

const task = new Revertable({ logger:(msg) => log2.push(msg) })
  .pushNamed("s1", (log) => log("do1"), "r1", (log) =>{ log("undo1"); throw new Error("rollback")})
  .pushNamed("s2", (log) => log("do2"))
  .pushNamed("s3", (log) => log("do3"), "r3", (log) => log("undo3"))
  .pushNamed("s4", (log) => { log("do4"); throw new Error("main"); }, "r4", (log) => log("undo4"));

const result = await task.run();
console.log(result);

πŸ“ˆ Log Output Example

↓ 1/4 [info] s1
↓ 1/4 [info] do1
↓ 2/4 [info] s2
↓ 2/4 [info] do2
↓ 3/4 [info] s3
↓ 3/4 [info] do3
↓ 4/4 [info] s4
↓ 4/4 [info] do4
─ 4/4 [error] main
↑ 3/4 [info] r3
↑ 3/4 [info] undo3
↑ 1/4 [info] r1
↑ 1/4 [info] undo1
‫ 1/4 [error] rolback

πŸ“˜ Class: Revertable

A class-based interface built over the core revertable function.

Constructor

new Revertable(options?: {
  pass?: "omit" | "keep" | "reduce",
  logger?: (text: string, kind: string, dir: boolean, step: number, count: number) => void,
  logFormat?: (data: any, kind: string, dir: boolean, step: number, count: number) => string
})

Modes (pass)

ModeDescription
"omit"No value is passed between steps (default)
"keep"A static value is passed to each step but not modified
"reduce"Each step receives and returns a value (like a reducer)

Method: push

push(
  fwd: (...args) => any | Promise<any>,
  rwd: (...args) => any | Promise<any>
): this

Adds a step to the process. Both forward and rollback handlers are required.

Method: run

async run(initialValue?: any): Promise<{
  status: "pass" | "undo" | "fail",
  pass?: any,
  undo?: Error,
  undoStep?: number,
  fail?: Error,
  failStep?: number
}>

Runs the sequence and handles rollback automatically.


🧰 Utility Functions (in utils)

import { revertable, sleep, attempt } from "@randajan/revert/async/utils";

revertable

Core engine function.

async revertable(
  value: any,
  stepCount: number,
  fn: (value, dir, stepIndex, totalSteps) => any,
  onError?: (err, dir, stepIndex, totalSteps) => void
): Promise<{
  status: "pass" | "undo" | "fail",
  pass?: any,
  undo?: Error,
  undoStep?: number,
  fail?: Error,
  failStep?: number
}>

Handles the entire flow + rollback mechanism. Minimal, flexible and fully decoupled from logging.


sleep

async sleep(ms: number): Promise<void>

Simple delay utility using Promise + setTimeout.

without sync alternative


attempt

async attempt(
  fn: (attempt: number) => any,
  attempts: number = 3,
  delay: number = 2000
): Promise<any>

Attempts the function multiple times until it succeeds, with delay between retries. sync attempts are without delay


πŸ§ͺ Synchronous Variant

Available under:

  • @randajan/revert/sync
  • @randajan/revert/sync/utils

Same API, but no sleep and limited attempt (as they’re async-only).
Use revertable() directly for immediate rollback logic.


Support

If you have any questions or suggestions for improvements, feel free to open an issue in the repository.

πŸ“„ License

MIT Β© randajan