Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/itemconsulting/enonic-wizardry

Functional utility library for Enonic XP
https://github.com/itemconsulting/enonic-wizardry

enonic enonic-xp functional-programming typescript

Last synced: 20 days ago
JSON representation

Functional utility library for Enonic XP

Awesome Lists containing this project

README

        

# Enonic Wizardry

[![npm version](https://badge.fury.io/js/enonic-wizardry.svg)](https://badge.fury.io/js/enonic-wizardry)

Functional utility library for Enonic XP. This library is intended to house reusable and tested code blocks based on
[enonic-fp](https://github.com/ItemConsulting/enonic-fp) that can be used in every project.

## Enonic-fp

*Enonic-wizardry* is intended to supplement *enonic-fp* with common patterns.

## Code generation

We recommend using this library together with the
[xp-codegen-plugin](https://github.com/ItemConsulting/xp-codegen-plugin) Gradle plugin. *xp-codegen-plugin* will create TypeScript
`interfaces` for your content-types. Those interfaces will be very useful together with this library.

## Building the project

```bash
npm run build
```

## Usage

### Get content by key service

In this example we have a service that returns an article by the `key` as json. Or if something goes wrong, we return
an _Internal Server Error_ instead.

```typescript
import {fold} from "fp-ts/lib/IOEither";
import {pipe} from "fp-ts/lib/pipeable";
import {Request, Response} from "enonic-types/controller";
import {errorResponse, ok} from "enonic-fp/controller";
import {Article} from "../../site/content-types/article/article"; // 1
import {getContentByIds} from "enonic-wizardry/content";
import {forceArray} from "enonic-fp/array";

export function get(req: Request): Response { // 2
const keys: Array = forceArray(req.params.key); // ["key1", "key2", "key3"]

const program = pipe( // 3
getContentByIds(keys), // 4
fold( // 5
errorResponse(req), // 7
ok // 8
)
);

return program(); // 9
}

```

1. We import an `interface Article { ... }` generated by
[xp-codegen-plugin](https://github.com/ItemConsulting/xp-codegen-plugin).
2. We use the imported `Request` and `Response` to control the shape of our controller.
3. We use the `pipe` function from *fp-ts* to pipe the result of one function into the next one.
4. We can use the `getContentByIds` function from `content` that query for the `Content` where the id is one
of the strings in the `keys`-Array. The return type here is `IOEither>>`
6. The last thing we usually do in `pipe` is to unpack the `IOEither`. This is done with
`fold(handleError, handleSuccess)`.
7. The `errorResponse(req: Request)` function returns a new function that can be used as a _callback_ by `fold`.
This "new function", takes the `EnonicError` object as a parameter, and creates a Json `Response` with the correct
status number, based on the `errorKey` of the `EnonicError`.
8. We pass the `ok` function to `fold` as the second parameter. The `ok` creates a `Response` where the `status` is
`200`, and the parameter is the `body`. In this case the `ReadonlyArray>` is assigned to the`body`.
9. We have so far constructed a constant `program` of type `IO`, but we have not yet performed a single
side effect. It's time to perform those side effects, so we run the `IO` by calling it, and a `Response` is returned
which out controller function can return.

## API

* [Content](./src/content.ts)
* `getContentByIds`
* `createAll`
* `createAndPublish`
* `deleteAndPublish`
* `modifyAndPublish`
* `applyChangesToData`
* `createMediaFromAttachment`

* [Context](./src/context.ts)
* `runAsSuperUser`
* `runInDraftContext`

* [Menu](./src/menu.ts)
* `getSubMenuByKey`

* [Validation](./src/validation.ts)
* `validate`