Skip to content

Commit

Permalink
chore: deno task dev
Browse files Browse the repository at this point in the history
  • Loading branch information
roziscoding committed Mar 28, 2023
1 parent b01e475 commit a690a6e
Showing 1 changed file with 37 additions and 23 deletions.
60 changes: 37 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,30 +7,37 @@ Standalone implementation of the "Chain of Command" pattern. Heavily inspired by

### Getting started

You start by creating an instance of the `Composer` class, passing as a type param the type of your context. You then register your middleware functions and call the `execute` function, passing the value of the context. The resulting promise will contain the context as returned by the middleware tree.
You start by creating an instance of the `Composer` class, passing as a type param the type of your context. You then
register your middleware functions and call the `execute` function, passing the value of the context. The resulting
promise will contain the context as returned by the middleware tree.

> Important: you must **always** call `next`. If you don't, your middleware tree will stay stuck and will not finish execution. Also, the call to `next` should always be awaited or returned, so you don't run into concurrency problems.
> Important: you must **always** call `next`. If you don't, your middleware tree will stay stuck and will not finish
> execution. Also, the call to `next` should always be awaited or returned, so you don't run into concurrency problems.
```typescript
import { Composer } from 'https://deno.land/x/composer/mod.ts'
import { Composer } from "https://deno.land/x/composer/mod.ts";

type Context = {
steps: number
}
steps: number;
};

const composer = new Composer()
composer.use((ctx, next) => next({ ...ctx, steps: ctx.steps + 1 }))
const composer = new Composer();
composer.use((ctx, next) => next({ ...ctx, steps: ctx.steps + 1 }));

composer.execute({ steps: 0 }).then(console.log) // { steps: 1 }
composer.execute({ steps: 0 }).then(console.log); // { steps: 1 }
```

### Timeshift Methods

Composer offers two methods, which we call Timeshift Methods, that allow you to register middleware to be run either `after` or `before` the regularly registered middleware. This allows you to ensure execution order and make your code clearer.
Composer offers two methods, which we call Timeshift Methods, that allow you to register middleware to be run either
`after` or `before` the regularly registered middleware. This allows you to ensure execution order and make your code
clearer.

#### Deferring execution

Sometimes you need a middleware function to perform tasks after all the other middleware has finished running. To do that, you have two options: you can either `await next(ctx)` and perform your tasks after that; or you can use the `after` method, like so:
Sometimes you need a middleware function to perform tasks after all the other middleware has finished running. To do
that, you have two options: you can either `await next(ctx)` and perform your tasks after that; or you can use the
`after` method, like so:

```typescript
import { Composer } from 'https://deno.land/x/composer/mod.ts'
Expand All @@ -50,11 +57,14 @@ composer.execute({ steps: 0 }).then(console.log)
// { steps: 1 }
```

The `after` method registers the middleware function in a special way that makes sure that it **always** runs after all the other middleware. As with regular middleware, middleware registered using `after` can modify the context by passing the mutated context, or a mutated clone of it, to the `next` function.
The `after` method registers the middleware function in a special way that makes sure that it **always** runs after all
the other middleware. As with regular middleware, middleware registered using `after` can modify the context by passing
the mutated context, or a mutated clone of it, to the `next` function.

#### Forwarding execution

Opposite to the `after` method, there is the `before` method for when you need to run things before any registered middleware:
Opposite to the `after` method, there is the `before` method for when you need to run things before any registered
middleware:

```typescript
import { Composer } from 'https://deno.land/x/composer/mod.ts'
Expand All @@ -75,23 +85,27 @@ composer.execute({ steps: 0 }).then(console.log)
// { steps: 1 }
```

The `before` method works similarly to the `after` method in that it registers the middleware function in a special way that makes sure it will **always** run before any other middleware registered regularly. As with any other middleware, you can also modify the context by passing its new version to `next`, be it a new object or the mutated existing one.
The `before` method works similarly to the `after` method in that it registers the middleware function in a special way
that makes sure it will **always** run before any other middleware registered regularly. As with any other middleware,
you can also modify the context by passing its new version to `next`, be it a new object or the mutated existing one.

#### Order matters

As you've seen with the examples, `before` middleware will always run at the beginning of the execution, and `after` middleware will always run at the end of the execution, no matter if you call them before or after `use`. However, when you call timeshift functions multiple times, they will be executed in the order they were registered. For example:
As you've seen with the examples, `before` middleware will always run at the beginning of the execution, and `after`
middleware will always run at the end of the execution, no matter if you call them before or after `use`. However, when
you call timeshift functions multiple times, they will be executed in the order they were registered. For example:

```typescript
type Context = {
steps: number[]
}
steps: number[];
};

const composer = new Composer<Steps>()
const composer = new Composer<Steps>();

composer.before((ctx, next) => next({ ...ctx, steps: ctx.steps.concat([1]) }))
composer.before((ctx, next) => next({ ...ctx, steps: ctx.steps.concat([2]) }))
composer.after((ctx, next) => next({ ...ctx, steps: ctx.steps.concat([3]) }))
composer.after((ctx, next) => next({ ...ctx, steps: ctx.steps.concat([4]) }))
composer.before((ctx, next) => next({ ...ctx, steps: ctx.steps.concat([1]) }));
composer.before((ctx, next) => next({ ...ctx, steps: ctx.steps.concat([2]) }));
composer.after((ctx, next) => next({ ...ctx, steps: ctx.steps.concat([3]) }));
composer.after((ctx, next) => next({ ...ctx, steps: ctx.steps.concat([4]) }));

composer.execute({ steps: [] }).then(console.log) // [1, 2, 3, 4]
```
composer.execute({ steps: [] }).then(console.log); // [1, 2, 3, 4]
```

0 comments on commit a690a6e

Please sign in to comment.