Comparing version 0.3.1 to 0.3.2
@@ -11,5 +11,4 @@ module.exports = { | ||
rules: { | ||
"@typescript-eslint/no-explicit-any": "off", | ||
"@typescript-eslint/ban-types": "off" | ||
}, | ||
}; |
@@ -1,3 +0,3 @@ | ||
import { IOEither } from "fp-ts/lib/IOEither"; | ||
import { Option } from "fp-ts/lib/Option"; | ||
import { IOEither } from "fp-ts/IOEither"; | ||
import { Option } from "fp-ts/Option"; | ||
import { AuthLibrary, ChangePasswordParams, CreateGroupParams, CreateRoleParams, CreateUserParams, FindPrincipalsParams, FindPrincipalsResult, FindUsersParams, GetProfileParams, Group, LoginParams, LoginResult, ModifyGroupParams, ModifyProfileParams, ModifyRoleParams, ModifyUserParams, Principal, Role, User, UserQueryResult } from "enonic-types/auth"; | ||
@@ -4,0 +4,0 @@ import { EnonicError } from "./errors"; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.getMemberships = exports.getMembers = exports.modifyGroup = exports.createGroup = exports.modifyRole = exports.hasRole = exports.createRole = exports.getPrincipal = exports.findPrincipals = exports.deletePrincipal = exports.removeMembers = exports.addMembers = exports.createUser = exports.modifyUser = exports.findUsers = exports.getIdProviderConfig = exports.modifyProfile = exports.getProfile = exports.getUser = exports.generatePassword = exports.changePassword = exports.logout = exports.login = exports.setLibrary = void 0; | ||
var Option_1 = require("fp-ts/lib/Option"); | ||
var Option_1 = require("fp-ts/Option"); | ||
var errors_1 = require("./errors"); | ||
@@ -6,0 +6,0 @@ var authLib = __non_webpack_require__("/lib/xp/auth"); |
@@ -55,3 +55,3 @@ import { IOEither } from "fp-ts/IOEither"; | ||
export declare function getTypes(): IOEither<EnonicError, ReadonlyArray<ContentType>>; | ||
export declare function isContent(value: any): value is Content; | ||
export declare function isContent(value: unknown): value is Content; | ||
export {}; |
@@ -1,3 +0,3 @@ | ||
import { IO } from "fp-ts/lib/IO"; | ||
import { IOEither } from "fp-ts/lib/IOEither"; | ||
import { IO } from "fp-ts/IO"; | ||
import { IOEither } from "fp-ts/IOEither"; | ||
import { Context, ContextLibrary, RunContext } from "enonic-types/context"; | ||
@@ -4,0 +4,0 @@ import { EnonicError } from "./errors"; |
import { Request, Response, ResponseType } from "enonic-types/controller"; | ||
import { IO } from "fp-ts/lib/IO"; | ||
import { IO } from "fp-ts/IO"; | ||
import { ResourceKey } from "enonic-types/thymeleaf"; | ||
@@ -4,0 +4,0 @@ import { EnonicError } from "./errors"; |
@@ -16,7 +16,7 @@ "use strict"; | ||
var i18n_1 = require("./i18n"); | ||
var Option_1 = require("fp-ts/lib/Option"); | ||
var IO_1 = require("fp-ts/lib/IO"); | ||
var Option_1 = require("fp-ts/Option"); | ||
var IO_1 = require("fp-ts/IO"); | ||
var thymeleaf_1 = require("./thymeleaf"); | ||
var errors_1 = require("./errors"); | ||
var function_1 = require("fp-ts/lib/function"); | ||
var function_1 = require("fp-ts/function"); | ||
var utils_1 = require("./utils"); | ||
@@ -23,0 +23,0 @@ exports.ok = asResponseFromStatus(200); |
import { ByteSource } from "enonic-types/content"; | ||
import { IOEither } from "fp-ts/lib/IOEither"; | ||
import { IOEither } from "fp-ts/IOEither"; | ||
import { EnonicError } from "./errors"; | ||
import { EncodingLibrary } from "enonic-types/encoding"; | ||
/** | ||
* Replace the library with a mocked version | ||
*/ | ||
export declare function setLibrary(library: any): void; | ||
export declare function setLibrary(library: EncodingLibrary): void; | ||
export declare function base64Encode(stream: ByteSource | string): string; | ||
@@ -9,0 +10,0 @@ export declare function base64Decode(text: string): IOEither<EnonicError, ByteSource>; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.hmacSha512AsStream = exports.hmacSha512AsHex = exports.hmacSha256AsStream = exports.hmacSha256AsHex = exports.hmacSha1AsStream = exports.hmacSha1AsHex = exports.sha512 = exports.sha256 = exports.sha1 = exports.md5 = exports.htmlUnescape = exports.htmlEscape = exports.urlUnescape = exports.urlEscape = exports.xmlUnescape = exports.xmlEscape = exports.charsetEncode = exports.charsetDecode = exports.hexDecode = exports.hexEncode = exports.base32Decode = exports.base32Encode = exports.base64UrlDecode = exports.base64UrlEncode = exports.base64Decode = exports.base64Encode = exports.setLibrary = void 0; | ||
var IOEither_1 = require("fp-ts/lib/IOEither"); | ||
var IOEither_1 = require("fp-ts/IOEither"); | ||
var utils_1 = require("./utils"); | ||
var pipeable_1 = require("fp-ts/lib/pipeable"); | ||
var pipeable_1 = require("fp-ts/pipeable"); | ||
var errors_1 = require("./errors"); | ||
@@ -8,0 +8,0 @@ var encodingLib = __non_webpack_require__("/lib/text-encoding"); |
@@ -1,2 +0,2 @@ | ||
import { IOEither } from "fp-ts/lib/IOEither"; | ||
import { IOEither } from "fp-ts/IOEither"; | ||
import { HttpLibrary, HttpRequestParams, HttpResponse } from "enonic-types/http"; | ||
@@ -3,0 +3,0 @@ import { EnonicError } from "./errors"; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.bodyAsJson = exports.request = exports.setLibrary = void 0; | ||
var IOEither_1 = require("fp-ts/IOEither"); | ||
var errors_1 = require("./errors"); | ||
var utils_1 = require("./utils"); | ||
var pipeable_1 = require("fp-ts/pipeable"); | ||
var httpLib = __non_webpack_require__("/lib/http-client"); | ||
@@ -21,3 +23,3 @@ /** | ||
function bodyAsJson(res) { | ||
return utils_1.parseJSON(res.body, function (reason) { | ||
return pipeable_1.pipe(res.body, utils_1.fromNullable(errors_1.badGatewayError), IOEither_1.chain(function (str) { return utils_1.parseJSON(str, function (reason) { | ||
return ({ | ||
@@ -29,4 +31,4 @@ type: "https://itemconsulting.github.io/problems/bad-gateway", | ||
}); | ||
}); | ||
}); })); | ||
} | ||
exports.bodyAsJson = bodyAsJson; |
@@ -1,2 +0,2 @@ | ||
import { Option } from "fp-ts/lib/Option"; | ||
import { Option } from "fp-ts/Option"; | ||
import { I18nLibrary, LocalizeParams } from "enonic-types/i18n"; | ||
@@ -3,0 +3,0 @@ /** |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.localizeFirst = exports.localize = exports.localizeUnsafe = exports.getSupportedLocales = exports.getPhrases = exports.setLibrary = void 0; | ||
var Option_1 = require("fp-ts/lib/Option"); | ||
var pipeable_1 = require("fp-ts/lib/pipeable"); | ||
var Option_1 = require("fp-ts/Option"); | ||
var pipeable_1 = require("fp-ts/pipeable"); | ||
var utils_1 = require("./utils"); | ||
@@ -7,0 +7,0 @@ var Array_1 = require("fp-ts/Array"); |
@@ -1,4 +0,4 @@ | ||
import { IO } from "fp-ts/lib/IO"; | ||
export declare function info(...args: ReadonlyArray<any>): IO<void>; | ||
export declare function warn(...args: ReadonlyArray<any>): IO<void>; | ||
export declare function error(...args: ReadonlyArray<any>): IO<void>; | ||
import { IO } from "fp-ts/IO"; | ||
export declare function info(...args: ReadonlyArray<unknown>): IO<void>; | ||
export declare function warn(...args: ReadonlyArray<unknown>): IO<void>; | ||
export declare function error(...args: ReadonlyArray<unknown>): IO<void>; |
@@ -1,2 +0,2 @@ | ||
import { IOEither } from "fp-ts/lib/IOEither"; | ||
import { IOEither } from "fp-ts/IOEither"; | ||
import { EmailParams, MailLibrary } from "enonic-types/mail"; | ||
@@ -3,0 +3,0 @@ import { EnonicError } from "./errors"; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.send = exports.setLibrary = void 0; | ||
var IOEither_1 = require("fp-ts/lib/IOEither"); | ||
var pipeable_1 = require("fp-ts/lib/pipeable"); | ||
var IOEither_1 = require("fp-ts/IOEither"); | ||
var pipeable_1 = require("fp-ts/pipeable"); | ||
var errors_1 = require("./errors"); | ||
@@ -7,0 +7,0 @@ var mailLib = __non_webpack_require__("/lib/xp/mail"); |
import { BreadcrumbMenu, GetBreadcrumbMenuParams, MenuItem, MenuLibrary } from "enonic-types/menu"; | ||
import { Content } from "enonic-types/content"; | ||
import { IOEither } from "fp-ts/lib/IOEither"; | ||
import { IOEither } from "fp-ts/IOEither"; | ||
import { EnonicError } from "./errors"; | ||
@@ -11,2 +11,2 @@ /** | ||
export declare function getMenuTree(levels: number): IOEither<EnonicError, ReadonlyArray<MenuItem>>; | ||
export declare function getSubMenus(levels: number): (parentContent: Content<any>) => IOEither<EnonicError, ReadonlyArray<MenuItem>>; | ||
export declare function getSubMenus(levels: number): (parentContent: Content) => IOEither<EnonicError, ReadonlyArray<MenuItem>>; |
@@ -1,3 +0,3 @@ | ||
import { IOEither } from "fp-ts/lib/IOEither"; | ||
import { DiffParams, DiffResponse, FindVersionsParams, MultiRepoConnection, MultiRepoConnectParams, NodeCreateParams, NodeFindChildrenParams, NodeGetParams, NodeModifyParams, NodeQueryParams, NodeQueryResponse, NodeVersionQueryResult, RepoConnection, RepoNode, Source } from "enonic-types/node"; | ||
import { IOEither } from "fp-ts/IOEither"; | ||
import { DiffParams, DiffResponse, FindVersionsParams, MultiRepoConnection, MultiRepoConnectParams, NodeCreateParams, NodeFindChildrenParams, NodeGetParams, NodeLibrary, NodeModifyParams, NodeQueryParams, NodeQueryResponse, NodeVersionQueryResult, RepoConnection, RepoNode, Source } from "enonic-types/node"; | ||
import { EnonicError } from "./errors"; | ||
@@ -7,3 +7,3 @@ /** | ||
*/ | ||
export declare function setLibrary(library: any): void; | ||
export declare function setLibrary(library: NodeLibrary): void; | ||
/** | ||
@@ -46,3 +46,3 @@ * Creates a connection to a repository with a given branch and authentication info. | ||
*/ | ||
export declare function query(repo: RepoConnection, params: NodeQueryParams): IOEither<EnonicError, NodeQueryResponse>; | ||
export declare function query<B extends string>(repo: RepoConnection, params: NodeQueryParams<B>): IOEither<EnonicError, NodeQueryResponse<B>>; | ||
/** | ||
@@ -55,2 +55,2 @@ * This function modifies a node. | ||
*/ | ||
export declare function findChildren(repo: RepoConnection, params: NodeFindChildrenParams): IOEither<EnonicError, NodeQueryResponse>; | ||
export declare function findChildren(repo: RepoConnection, params: NodeFindChildrenParams): IOEither<EnonicError, NodeQueryResponse<never>>; |
{ | ||
"name": "enonic-fp", | ||
"version": "0.3.1", | ||
"version": "0.3.2", | ||
"sideEffects": false, | ||
@@ -27,12 +27,12 @@ "description": "Functional programming helpers for Enonic XP", | ||
"dependencies": { | ||
"enonic-types": "^0.1.2", | ||
"fp-ts": "^2.8.2" | ||
"enonic-types": "^0.1.4", | ||
"fp-ts": "^2.8.5" | ||
}, | ||
"devDependencies": { | ||
"@typescript-eslint/eslint-plugin": "^4.1.1", | ||
"@typescript-eslint/parser": "^4.1.1", | ||
"eslint": "^7.9.0", | ||
"@typescript-eslint/eslint-plugin": "^4.6.0", | ||
"@typescript-eslint/parser": "^4.6.0", | ||
"eslint": "^7.12.1", | ||
"rimraf": "^3.0.2", | ||
"typescript": "^4.0.3" | ||
"typescript": "^4.0.5" | ||
} | ||
} |
@@ -1,2 +0,2 @@ | ||
import { IOEither } from "fp-ts/lib/IOEither"; | ||
import { IOEither } from "fp-ts/IOEither"; | ||
import { EnonicError } from "./errors"; | ||
@@ -3,0 +3,0 @@ import { ByteSource, Content, Site } from "enonic-types/content"; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.sanitizeHtml = exports.processHtml = exports.url = exports.pageUrl = exports.logoutUrl = exports.loginUrl = exports.imageUrl = exports.serviceUrl = exports.componentUrl = exports.attachmentUrl = exports.assetUrl = exports.imagePlaceholder = exports.idProviderUrl = exports.getSiteConfig = exports.getSite = exports.getMultipartText = exports.getMultipartStream = exports.getMultipartItem = exports.getMultipartForm = exports.getIdProviderKey = exports.getComponent = exports.getContent = exports.setLibrary = void 0; | ||
var IOEither_1 = require("fp-ts/lib/IOEither"); | ||
var IOEither_1 = require("fp-ts/IOEither"); | ||
var errors_1 = require("./errors"); | ||
var utils_1 = require("./utils"); | ||
var pipeable_1 = require("fp-ts/lib/pipeable"); | ||
var pipeable_1 = require("fp-ts/pipeable"); | ||
var portalLib = __non_webpack_require__("/lib/xp/portal"); | ||
@@ -9,0 +9,0 @@ /** |
138
README.md
@@ -6,9 +6,9 @@ # Enonic FP | ||
Functional programming helpers for Enonic XP. This library provides [fp-ts](https://github.com/gcanti/fp-ts) wrappers | ||
around the Enonic-interfaces provided by [enonic-types](https://github.com/ItemConsulting/enonic-types) and the official | ||
standard libraries. | ||
around the Enonic-interfaces provided by [enonic-types](https://github.com/ItemConsulting/enonic-types), which again | ||
wraps the official standard libraries (in jars). | ||
## Code generation | ||
We recommend using this library together with its sister library: | ||
[enonic-ts-codegen](https://github.com/ItemConsulting/enonic-ts-codegen). *enonic-ts-codegen* will create TypeScript | ||
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. | ||
@@ -18,3 +18,3 @@ | ||
1. Enonic 7 setup with Webpack | ||
1. [Enonic 7 setup with Webpack](https://github.com/enonic/starter-webpack) | ||
2. Individual Enonic client libraries installed (this library only contains wrappers around the interfaces) | ||
@@ -31,3 +31,3 @@ | ||
2. It allows us to `pipe` the results from one operation into the next using `chain` (or `map`). Chain expects another | ||
`IOEither<EnonicError, A>` to be returned, and when the first `left<EnonicError>` is returned, the pipe will short | ||
`IOEither<EnonicError, A>` to be returned. When the first `left<EnonicError>` is returned, the pipe will short | ||
circuit to the error case in `fold`. | ||
@@ -39,6 +39,6 @@ | ||
### Get content by key service | ||
### Example 1: 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. | ||
In this example we have a service that returns Article content – that has a `key` as id – as json. Or if something goes | ||
wrong, we return an _Internal Server Error_ instead. | ||
@@ -57,8 +57,8 @@ ```typescript | ||
fold( // 5 | ||
internalServerError, // 6 | ||
ok // 7 | ||
internalServerError, | ||
ok | ||
) | ||
); | ||
return program(); // 8 | ||
return program(); // 6 | ||
} | ||
@@ -68,3 +68,3 @@ ``` | ||
1. We import an `interface Article { ... }` generated by | ||
[enonic-ts-codegen](https://github.com/ItemConsulting/enonic-ts-codegen). | ||
[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. | ||
@@ -75,7 +75,6 @@ 3. We use the `pipe` function from *fp-ts* to pipe the result of one function into the next one. | ||
5. The last thing we usually do in a controller is to unpack the `IOEither`. This is done with | ||
`fold(handleError, handleSuccess)`. We create two functions (`handleError`, and `handleSuccess`), that both return | ||
`IO<Response>`. | ||
6. We create the `Response` object for the error case | ||
7. We create the `Response` object for the success case | ||
8. We have so far constructed a constant `program` of type `IO<Response>`, but we have not yet performed a single | ||
`fold(handleError, handleSuccess)`. _enonic-fp_ comes with a set of functions that creates an `IO<Response>` with | ||
the data. There are pre-configured functions that can be used in `fold` for some of the most common http status | ||
numbers. Like `ok()` and `internalServerError()`. | ||
6. We have so far constructed a constant `program` of type `IO<Response>`, 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 return the `Response` we | ||
@@ -85,3 +84,3 @@ get back. | ||
### Delete content by key and publish | ||
### Example 2: Delete content by key and publish | ||
@@ -109,4 +108,4 @@ In this example we delete come content by `key`. We are first doing this on the `draft` branch. And then we `publish` it | ||
fold( // 3 | ||
errorResponse(req), | ||
noContent // 4 | ||
errorResponse({ req, i18nPrefix: "articleErrors" }), // 4 | ||
noContent // 5 | ||
) | ||
@@ -118,31 +117,34 @@ ); | ||
export {del as delete}; // 5 | ||
export {del as delete}; // 6 | ||
const runOnBranchDraft = run({ branch: 'draft' }); | ||
const runOnBranchDraft = run({ branch: 'draft' }); // 7 | ||
``` | ||
1. We call the `remove` function with the `key` to delete some content. We want to do this on the _draft_ branch, so we | ||
wrap the call in `runInDraftContext` (which I have copied in from the *enonic-wizardry* package for this example). | ||
Remove returns `IOEither<EnonicError, void>`. If the content didn't exist, it will return a `EnonicError` with | ||
`errorKey="NotFoundError"`, that can be handled in the `fold`. | ||
2. We want to publish our change from the _draft_ branch to the _master_ branch. So we call another function that we | ||
have copied in from *enonic-wizardry*, called `publishContentByKey`. | ||
wrap the call in the `runInDraftContext` function that is defined below. | ||
Remove returns `IOEither<EnonicError, void>`. If the content didn't exist, it will return an `EnonicError` with of | ||
type "[https://problem.item.no/xp/not-found](https://problem.item.no/xp/not-found)", that can be handled in the | ||
`fold()`. | ||
2. We want to publish our change from the _draft_ branch to the _master_ branch. The `publish()` function in | ||
_enonic-fp_ has an overload that only takes the `key` as a `string` and defaults to publish from _draft_ to | ||
_master_. | ||
3. To create our `Response` we call `fold`, where we handle the error and success cases, and return `IO<Response>`. | ||
4. Since this is a delete operation we return a `204` on the success case, which means "no content". | ||
5. Since delete is a keyword in JavaScript and TypeScript, we have to do this hack to return the `delete` function. | ||
4. The `errorResponse()` function use the `HttpError.status` field to know which http status number to use on the | ||
`Response`. It can optionally take the `Request` and a `i18nPrefix` as parameters. | ||
* The `Request` adds the `HttpError.instance` on the return object, and it will check if `req.mode !== 'live'`, | ||
and if yes, return more details about the error (this is to prevent exploits based on the error messages). | ||
* The usage of `i18nPrefix` is detailed the [i18n for error messages](#i18n-for-error-messages) chapter. | ||
5. Since this is a delete operation we return a | ||
[https status 204](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/204) on the success case, which means | ||
"no content". | ||
6. Since delete is a keyword in JavaScript and TypeScript, we have to do this hack to return the `delete` function. | ||
7. This is a curried version of `ContextLib.run`. It returns a new function – here assigned to the constant | ||
`runOnBranchDraft` – that takes an `IO` as parameter (which all the wrapped functions already return as `IOEither`). | ||
### Multiple queries, and http request | ||
### Example 3: Thymeleaf, multiple queries, and http request | ||
In this example we do 3 queries. First we look up an article by `key`, then we search for comments related to that | ||
In this example we do three queries. First we look up an article by `key`, then we search for comments related to that | ||
article based on the articles key. And then we get a list of open positions in the company, that we want to display on | ||
the web page. | ||
The first two are queries in Enonic, and the last one is over http. We do a `sequenceT` taking the 3 `Either<Error, T>` | ||
as input, and getting an Either with the results in a tuple (`Either<Error, [Content, QueryResponse, any]>`). | ||
We then `map` over the tuple, and create an object with all the data, that can be returned to the user. | ||
In the `fold` we either return the an error, with the correct http status (`404`, `500` or `502`), or we return the | ||
result with the http status `200`. | ||
```typescript | ||
@@ -155,2 +157,3 @@ import {sequenceT} from "fp-ts/Apply"; | ||
import {Content, QueryResponse} from "enonic-types/content"; | ||
import {getRenderer} from "enonic-fp/thymeleaf"; | ||
import {EnonicError} from "enonic-fp/errors"; | ||
@@ -161,5 +164,9 @@ import {get as getContent, query} from "enonic-fp/content"; | ||
import {Comment} from "../../site/content-types/comment/comment"; | ||
import {errorResponse, ok} from "enonic-fp/controller"; | ||
import {ok, unsafeRenderErrorPage} from "enonic-fp/controller"; | ||
import {tupled} from "fp-ts/function"; | ||
const view = resolve('./article.html'); | ||
const errorView = resolve('../../templates/error.html'); | ||
const renderer = getRenderer<ThymeleafParams>(view); // 1 | ||
export function get(req: Request): Response { | ||
@@ -169,3 +176,3 @@ const articleId = req.params.key!; | ||
return pipe( | ||
sequenceT(ioEither)( | ||
sequenceT(ioEither)( // 2 | ||
getContent<Article>(articleId), | ||
@@ -175,5 +182,6 @@ getCommentsByArticleKey(articleId), | ||
), | ||
map(tupled(createResponse)), | ||
map(tupled(createThymeleafParams)), // 3 | ||
chain(renderer), // 4 | ||
fold( | ||
errorResponse({ req, i18nPrefix: "articleErrors" }), | ||
unsafeRenderErrorPage(errorView), // 5 | ||
ok | ||
@@ -184,3 +192,5 @@ ) | ||
function getCommentsByArticleKey(articleId: string): IOEither<EnonicError, QueryResponse<Comment>> { | ||
function getCommentsByArticleKey(articleId: string) | ||
: IOEither<EnonicError, QueryResponse<Comment>> { | ||
return query<Comment>({ | ||
@@ -195,3 +205,3 @@ contentTypes: ["com.example:comment"], | ||
return pipe( | ||
request("https://example.com/api/open-positions"), | ||
request("https://example.com/api/open-positions"), // 6 | ||
chain(bodyAsJson) | ||
@@ -201,9 +211,10 @@ ); | ||
function createResponse( | ||
function createThymeleafParams( // 7 | ||
article: Content<Article>, | ||
comments: QueryResponse<Comment>, | ||
openPositions: Json | ||
) { | ||
): ThymeleafParams { | ||
return { | ||
...article, | ||
id: article._id, | ||
data: article.data, | ||
comments: comments.hits, | ||
@@ -213,4 +224,31 @@ openPositions | ||
} | ||
interface ThymeleafParams { | ||
readonly id: string; | ||
readonly data: Article; | ||
readonly comments: ReadonlyArray<Comment>; | ||
readonly openPositions: Json | ||
} | ||
``` | ||
1. `getRenderer()` is a curried version of `ThymeleafLib.render()`. It takes `ThymeleafParams` (defined below) as a | ||
type parameter and the `view` as a parameter, and returns a function with this signature: | ||
`(params: ThymeleafParams) => IOEither<EnonicError, string>`, where the string is the finished rendered page. | ||
2. We do a `sequenceT` taking the three `IOEither<EnonicError, A>` as input, and getting an `IOEither` with the results | ||
in a tuple (`IOEither<EnonicError, [Content<Article>, QueryResponse<Comment>, Json]>`). The first two are queries in | ||
Enonic, and the last one is over http. | ||
3. We then `map` over the tuple, using `createThymeleafParams()`. But first we use the `tupled` function on | ||
`createThymeleafParams()` to give us _a new version_ of `createThymeleafParams` that takes the parameters as a | ||
tuple, instead of as individual arguments. A good rule of thumb is to always use `tupled` together with `sequenceT`! | ||
4. We use the `render()` function in a `chain()`, since it returns an `IOEither<EnonicError, string>`. | ||
5. If any of the functions in the `pipe` has returned a `Left<EnonicError>`, we need to handle the `EnonicError`. In | ||
this case we want to render an error page. The `unsafeRenderErrorPage()` takes the `errorView` (html page) as | ||
parameter, which should be a template for `EnonicError`. If the templating succeeds, an `IO<Response>` is created | ||
with the page as the `body`, and with the http status from the `EnonicError`. But if it fails, we just need to let | ||
it fail completely and handled by Enonic XP, because we don't want an infinite loop of failing templating. | ||
6. We use an overloaded version of `HttpLib.request`, which only takes the url as parameter. We then `pipe` it into the | ||
`bodyAsJson` function that parses the json in the `Request.body` and returns an `EnonicError` if it fails. | ||
7. The `createThymeleafParams` function gathers all the data and creates one new object that the Thymeleaf-renderer | ||
will take as input. | ||
## i18n for error messages | ||
@@ -221,3 +259,3 @@ | ||
There is support for adding internationalization for error-messages. This is done, when you generate the `Response` | ||
using the `errorResponse(req: Request, i18nPrefix: string)` method. | ||
using the `errorResponse({ req: Request, i18nPrefix: string})` method. | ||
@@ -224,0 +262,0 @@ The i18n-key to use to look up the message has the following shape: `${i18nPrefix}.title.${typeString}` where |
@@ -1,3 +0,3 @@ | ||
import { IOEither } from "fp-ts/lib/IOEither"; | ||
import { Option } from "fp-ts/lib/Option"; | ||
import { IOEither } from "fp-ts/IOEither"; | ||
import { Option } from "fp-ts/Option"; | ||
import { EnonicError } from "./errors"; | ||
@@ -4,0 +4,0 @@ import { RecaptchaLibrary } from "enonic-types/recaptcha"; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.isConfigured = exports.verify = exports.getSecretKey = exports.getSiteKey = exports.setLibrary = void 0; | ||
var pipeable_1 = require("fp-ts/lib/pipeable"); | ||
var IOEither_1 = require("fp-ts/lib/IOEither"); | ||
var function_1 = require("fp-ts/lib/function"); | ||
var Option_1 = require("fp-ts/lib/Option"); | ||
var pipeable_1 = require("fp-ts/pipeable"); | ||
var IOEither_1 = require("fp-ts/IOEither"); | ||
var function_1 = require("fp-ts/function"); | ||
var Option_1 = require("fp-ts/Option"); | ||
var errors_1 = require("./errors"); | ||
@@ -9,0 +9,0 @@ var recaptchaLib = __non_webpack_require__('/lib/recaptcha'); |
@@ -1,2 +0,2 @@ | ||
import { IOEither } from "fp-ts/lib/IOEither"; | ||
import { IOEither } from "fp-ts/IOEither"; | ||
import { EnonicError } from "./errors"; | ||
@@ -3,0 +3,0 @@ import { CreateBranchParams, CreateRepoParams, DeleteBranchParams, RefreshParams, RepoLibrary, RepositoryConfig } from "enonic-types/repo"; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.refresh = exports.deleteBranch = exports.remove = exports.list = exports.get = exports.createBranch = exports.create = exports.setLibrary = void 0; | ||
var IOEither_1 = require("fp-ts/lib/IOEither"); | ||
var pipeable_1 = require("fp-ts/lib/pipeable"); | ||
var IOEither_1 = require("fp-ts/IOEither"); | ||
var pipeable_1 = require("fp-ts/pipeable"); | ||
var errors_1 = require("./errors"); | ||
@@ -7,0 +7,0 @@ var utils_1 = require("./utils"); |
@@ -1,2 +0,2 @@ | ||
import { IOEither } from "fp-ts/lib/IOEither"; | ||
import { IOEither } from "fp-ts/IOEither"; | ||
import { ResourceKey, ThymeleafLibrary, ThymeleafRenderOptions } from "enonic-types/thymeleaf"; | ||
@@ -3,0 +3,0 @@ import { EnonicError } from "./errors"; |
@@ -1,3 +0,3 @@ | ||
import * as EI from "fp-ts/lib/Either"; | ||
import { IOEither } from "fp-ts/lib/IOEither"; | ||
import * as EI from "fp-ts/Either"; | ||
import { IOEither } from "fp-ts/IOEither"; | ||
import { ById, ByKey, ByPath } from "enonic-types/portal"; | ||
@@ -4,0 +4,0 @@ import { EnonicError } from "./errors"; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.stringToByPath = exports.stringToById = exports.stringToByKey = exports.substringAfter = exports.isString = exports.parseJSON = exports.fromNullable = void 0; | ||
var EI = require("fp-ts/lib/Either"); | ||
var IOEither_1 = require("fp-ts/lib/IOEither"); | ||
var EI = require("fp-ts/Either"); | ||
var IOEither_1 = require("fp-ts/IOEither"); | ||
function fromNullable(e) { | ||
@@ -7,0 +7,0 @@ return function (a) { return IOEither_1.fromEither(EI.fromNullable(e)(a)); }; |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
100289
299
46
1927
Updatedenonic-types@^0.1.4
Updatedfp-ts@^2.8.5