{"id":15910500,"url":"https://github.com/itemconsulting/enonic-wizardry","last_synced_at":"2026-01-19T09:34:09.432Z","repository":{"id":91316335,"uuid":"46849016","full_name":"ItemConsulting/enonic-wizardry","owner":"ItemConsulting","description":"Functional utility library for Enonic XP","archived":false,"fork":false,"pushed_at":"2023-07-18T20:15:47.000Z","size":683,"stargazers_count":1,"open_issues_count":3,"forks_count":0,"subscribers_count":15,"default_branch":"main","last_synced_at":"2025-04-08T01:45:11.358Z","etag":null,"topics":["enonic","enonic-xp","functional-programming","typescript"],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ItemConsulting.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2015-11-25T08:50:35.000Z","updated_at":"2021-12-14T10:41:06.000Z","dependencies_parsed_at":"2024-10-28T12:45:25.888Z","dependency_job_id":"f83f38ae-bd87-4f21-be25-7c78acacbf8e","html_url":"https://github.com/ItemConsulting/enonic-wizardry","commit_stats":{"total_commits":125,"total_committers":4,"mean_commits":31.25,"dds":"0.18400000000000005","last_synced_commit":"0c7976b562676efe003f0867da1ea87862c823cf"},"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ItemConsulting%2Fenonic-wizardry","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ItemConsulting%2Fenonic-wizardry/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ItemConsulting%2Fenonic-wizardry/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ItemConsulting%2Fenonic-wizardry/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ItemConsulting","download_url":"https://codeload.github.com/ItemConsulting/enonic-wizardry/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247761030,"owners_count":20991533,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["enonic","enonic-xp","functional-programming","typescript"],"created_at":"2024-10-06T15:07:08.178Z","updated_at":"2026-01-19T09:34:09.385Z","avatar_url":"https://github.com/ItemConsulting.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Enonic Wizardry\n\n[![npm version](https://badge.fury.io/js/enonic-wizardry.svg)](https://badge.fury.io/js/enonic-wizardry)\n\nFunctional utility library for Enonic XP. This library is intended to house reusable and tested code blocks based on \n[enonic-fp](https://github.com/ItemConsulting/enonic-fp) that can be used in every project.\n\n## Enonic-fp\n\n*Enonic-wizardry* is intended to supplement *enonic-fp* with common patterns.\n\n## Code generation\n\nWe recommend using this library together with the\n[xp-codegen-plugin](https://github.com/ItemConsulting/xp-codegen-plugin) Gradle plugin. *xp-codegen-plugin* will create TypeScript \n`interfaces` for your content-types. Those interfaces will be very useful together with this library.\n\n## Building the project\n\n```bash\nnpm run build\n```\n\n## Usage\n\n### Get content by key service\n\nIn this example we have a service that returns an article by the `key` as json. Or if something goes wrong, we return \nan _Internal Server Error_ instead.\n\n```typescript\nimport {fold} from \"fp-ts/lib/IOEither\";\nimport {pipe} from \"fp-ts/lib/pipeable\";\nimport {Request, Response} from \"enonic-types/controller\";\nimport {errorResponse, ok} from \"enonic-fp/controller\";\nimport {Article} from \"../../site/content-types/article/article\"; // 1\nimport {getContentByIds} from \"enonic-wizardry/content\";\nimport {forceArray} from \"enonic-fp/array\";\n\nexport function get(req: Request): Response { // 2\n  const keys: Array\u003cstring\u003e = forceArray(req.params.key); // [\"key1\", \"key2\", \"key3\"]\n\n  const program = pipe( // 3\n    getContentByIds\u003cArticle\u003e(keys), // 4\n    fold( // 5\n      errorResponse(req), // 7\n      ok // 8\n    )\n  );\n\n  return program(); // 9\n}\n\n```\n\n 1. We import an `interface Article { ... }` generated by \n    [xp-codegen-plugin](https://github.com/ItemConsulting/xp-codegen-plugin).\n 2. We use the imported `Request` and `Response` to control the shape of our controller.\n 3. We use the `pipe` function from *fp-ts* to pipe the result of one function into the next one.\n 4. We can use the `getContentByIds` function from `content` that query for the `Content\u003cArticle\u003e` where the id is one \n    of the strings in the `keys`-Array. The return type here is `IOEither\u003cEnonicError, ReadonlyArray\u003cContent\u003cArticle\u003e\u003e\u003e`\n 6. The last thing we usually do in `pipe` is to unpack the `IOEither`. This is done with \n    `fold(handleError, handleSuccess)`.\n 7. The `errorResponse(req: Request)` function returns a new function that can be used as a _callback_ by `fold`. \n    This \"new function\", takes the `EnonicError` object as a parameter, and creates a Json `Response` with the correct \n    status number, based on the `errorKey` of the `EnonicError`. \n 8. We pass the `ok` function to `fold` as the second parameter. The `ok` creates a `Response` where the `status` is \n    `200`, and the parameter is the `body`. In this case the `ReadonlyArray\u003cContent\u003cArticle\u003e\u003e` is assigned to the`body`.\n 9. We have so far constructed a constant `program` of type `IO\u003cResponse\u003e`, but we have not yet performed a single \n    side effect. It's time to perform those side effects, so we run the `IO` by calling it, and a `Response` is returned\n    which out controller function can return.\n\n## API\n\n * [Content](./src/content.ts)\n   * `getContentByIds`\n   * `createAll`\n   * `createAndPublish`\n   * `deleteAndPublish`\n   * `modifyAndPublish`\n   * `applyChangesToData`\n   * `createMediaFromAttachment`\n   \n * [Context](./src/context.ts)\n   * `runAsSuperUser`\n   * `runInDraftContext`\n   \n* [Menu](./src/menu.ts)\n  * `getSubMenuByKey`\n   \n * [Validation](./src/validation.ts)\n   * `validate`\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fitemconsulting%2Fenonic-wizardry","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fitemconsulting%2Fenonic-wizardry","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fitemconsulting%2Fenonic-wizardry/lists"}