@propero/action-history

Typesafe, extensible history for user defined actions

Usage no npm install needed!

<script type="module">
  import properoActionHistory from 'https://cdn.skypack.dev/@propero/action-history';
</script>

README

Action History

Maintainability Test Coverage Build Status

npm i @propero/action-history
yarn add @propero/action-history
pnpm i @propero/action-history

Documentation

In progress... maybe... hopefully... within the next decade or so... no guarantees though!

Example

import { createHistory, HistoryMeta } from "@propero/action-history";

// interface for type safety inside handlers, calls, etc.
// can later be augmented for extensibility
interface Events extends HistoryMeta {
  "myapp:myaction": {
    parameters: { param?: number },
    context: { context: number },
  },
  "myapp:otheraction": {
    reversible: false,
  },
  "myapp:lateaction": {
    context: { latecontext: number },
  }
}

const history = createHistory<Events>();

history.context({ context: 2 });

let myNumber = 0;

history.action("myapp:myaction", async ({ param = 5 }, { context }) => {
  const previous = myNumber;
  myNumber += param;
  myNumber /= context;
  return async () => {
    myNumber = previous;
  };
});

history.action("myapp:otheraction", async () => {
  console.log("other action");
});

await history.exec("myapp:myaction", { param: 2 });
// myNumber = (0 + 2) / 2 = 1
await history.exec("myapp:otheraction");
// myNumber unchanged
await history.exec("myapp:myaction");
// myNumber = (1 + 5) / 2 = 3

await history.exec("history:undo", { steps: 2 });
// myNumber = 0
await history.exec("history:redo");
// myNumber = 1

const actionPromise = history.exec("myapp:lateaction");
// actionPromise waits for action to be registered

history.action("myapp:lateaction", ({}, { latecontext }) => {
  myNumber *= latecontext;
  () => myNumber /= latecontext;
}, ["latecontext"]);
// actionPromise waits for dependent context to be defined

history.context({ latecontext: 10 });
// action is executed

await actionPromise;
// myNumber = 1 * 10 = 10