Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
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
- Host: GitHub
- URL: https://github.com/itemconsulting/enonic-wizardry
- Owner: ItemConsulting
- License: mit
- Created: 2015-11-25T08:50:35.000Z (about 9 years ago)
- Default Branch: main
- Last Pushed: 2023-07-18T20:15:47.000Z (over 1 year ago)
- Last Synced: 2024-12-21T16:43:14.451Z (20 days ago)
- Topics: enonic, enonic-xp, functional-programming, typescript
- Language: TypeScript
- Size: 667 KB
- Stars: 1
- Watchers: 15
- Forks: 0
- Open Issues: 3
-
Metadata Files:
- Readme: README.md
- License: LICENSE
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`