1.0.25 • Published 3 years ago

@idiosync/fswitch v1.0.25

Weekly downloads
177
License
ISC
Repository
github
Last release
3 years ago

NPM Version

fSwitch

Initially created for handling server statuses in a nice readable way, it generalises as a system for implementing complex conditional code in a easy-to-read and self-documenting manner.

// use with redux-saga
yield fSwitch(res.status,
  [SUCCESS, () => put(successAction)],
  [FAIL, () => put(failAction)],
  () => put({ type: 'error', error: new Error('summin went wrong') })
)

Installation

yarn:

$ yarn add @idiosync/fswitch

npm:

$ npm i @idiosync/fswitch

Basic use

The fSwich function accepts an input followed by a series of conditional functions and callbacks. Like a switch statement the first passing case terminates the process. Finally, a default callback can be passed.

import { fSwitch, fCase, fDefault } from "@idiosync/fswitch"

const person = { age: 45, name: James };

const NAME_IS_RICHARD = person => person.name === 'rechard'
const IS_YOUNGER_THAN_18 = person => person.age < 18

fSwitch(person,
  fCase(NAME_IS_RICHARD, person => saveToRichardPool(person)),
  fCase(IS_YOUNGER_THAN_18, person => tooYoung(person),
  fDefault(person => person.isHappy = true)
)

The above statement can also be written in a short from

fSwitch(
  person,
  [NAME_IS_RICHARD, (person) => saveToRichardPool(person)],
  [IS_YOUNGER_THAN_18, (person) => tooYoung(person)],
  (person) => (person.isHappy = true)
);

The fSwitch function returns whatever is returned by the successful callback. Amongst other things this can useful for asynchronous effects.

// await promise returned by successful callback
await fSwitch(
  input,
  fCase(SOME_STATE, async (input) => fetch(input)),
  fDefault(async (input) => fetch(input))
);

Server status codes

fSwitch was initially created for dealing with server status codes in redux-saga, so I will use that as an example.

All common server codes are supported and listed here: responses.

// import some error cases
import { SUCCESS, FAIL } from "@idiosync/fswitch";

// create our own conditional if we needed
// (although 404 and all other common codes are actually in above file too)
const IS_404 = (status) => status === 404;

function* fetchUserInfoSaga() {
  const res = yield fetch(url);

  yield fSwitch(
    res.status,
    [SUCCESS, () => put(successAction)],
    [IS_404, () => put(server404Action)],
    [FAIL, () => put(failAction)],
    () => put({ type: "error", error: new Error("summin went wrong") })
  );
}

If you need a more complex callback you can return a generator or another saga. This allows you to effectively yield from the callback

import { fSwitch, SUCCESS } from "fswitch";
import { put, call } from "redux-saga/effects";

function* fetchUserInfoSaga() {
  const res = yield fetch(url);

  yield fSwitch(
    res.status,
    [
      SUCCESS,
      // callback returns a generator wrapped with saga's "call" function
      (status) =>
        call(function* () {
          if (status === 202) {
            yield put(someAction);
          } else {
            yield put(someOtherAction);
          }
        }),
    ],
    () => put(failAction)
  );
}

Remember that once a case passes the later ones are not called, so if you want to use SUCCESS or FAIL conditions then you will have to handle individaul calls first.

fSwitch(
  res.status,
  [SUCCESS, handleSuccess],
  [s200, handle200] // <--- this line will never be reached
);

Combiners

These are functions that combine multiple conditions with and / or logic.

fSwitch(
  status,
  [or(s200, s202), handleSuccess],
  [and(isMoreThan202, isLessThan300), handleSuccessDifferently],
  [FAIL, handleFail]
);

Try/Catch

For the sake of pretty syntax I have added an optional try/catch wrapper. If you use this you MUST use the catch function returned by try or fSwitch will never be called

  yield fSwitch.try(res.status,
    [ SUCCESS, () => throw new Error("error")],
    () => defaultAction()
  ).catch(
    error => handleError(error)   // <-- error is caught here
  )
1.0.25

3 years ago

1.0.22

3 years ago

1.0.21

3 years ago

1.0.24

3 years ago

1.0.23

3 years ago

1.0.20

4 years ago

1.0.19

4 years ago

1.0.18

4 years ago

1.0.17

4 years ago

1.0.16

4 years ago

1.0.15

4 years ago

1.0.14

4 years ago

1.0.9

4 years ago

1.0.8

4 years ago

1.0.11

4 years ago

1.0.10

4 years ago

1.0.13

4 years ago

1.0.12

4 years ago

1.0.7

4 years ago

1.0.6

4 years ago

1.0.5

4 years ago

1.0.4

4 years ago

1.0.3

4 years ago

1.0.2

4 years ago

1.0.1

4 years ago

1.0.0

4 years ago