Skip to content

Commit

Permalink
feat: initial version
Browse files Browse the repository at this point in the history
  • Loading branch information
tpluscode committed Oct 31, 2021
1 parent 9b12cad commit 86addbc
Show file tree
Hide file tree
Showing 6 changed files with 709 additions and 26 deletions.
5 changes: 5 additions & 0 deletions .changeset/silver-lemons-buy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"express-rdf-problem-details": major
---

First release
25 changes: 25 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# express-rdf-problem-details

This package wraps [express-http-problem-details](https://github.com/PDMLab/express-http-problem-details) so that RDF/Linked Data express applications will return Problem documents ([RFC7807](https://tools.ietf.org/html/rfc7807)) as valid JSON-LD.

This is done simply by adding a `Link` header pointing to a JSON-LD `@context`. By default, it's the [context provided by Hydra Community Group](http://www.hydra-cg.com/spec/latest/core/#example-31-rfc-7807-compatible-error-description)

## Usage

```typescript
import express from 'express'
import * as error from 'express-rdf-problem-details'
import { NotFoundMapper } from './error-mappers'

const app = express()

// All params optional
express.use(error.handler({
// change the @context URL
context: 'http://example.com/error.jsonld',
// additional mappers to customize error documents
mappers: [new NotFoundMapper()]
}))
```

Implementing mappers is explained in [PDMLab/express-http-problem-details](https://github.com/PDMLab/express-http-problem-details#example)
22 changes: 21 additions & 1 deletion index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,21 @@
export default 'foo'
import type * as express from 'express'
import { HttpProblemResponse } from 'express-http-problem-details'
import { DefaultMappingStrategy, IErrorMapper, MapperRegistry } from 'http-problem-details-mapper'
import setLink from 'set-link'

interface Factory {
(arg?: { mappers?: IErrorMapper[]; context?: string }): express.ErrorRequestHandler
}

export const handler: Factory = ({ mappers = [], context = 'https://www.w3.org/ns/hydra/error' } = {}) => {
const registry = mappers.reduce((r, mapper) => r.registerMapper(mapper, true), new MapperRegistry())

const problemDetailsHandler = HttpProblemResponse({ strategy: new DefaultMappingStrategy(registry) })

return (err, req, res, next) => {
setLink.attach(res)

res.setLink(context, 'http://www.w3.org/ns/json-ld#context')
problemDetailsHandler(err, req, res, next)
}
}
22 changes: 17 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "ts-template",
"name": "express-rdf-problem-details",
"description": "hydra-box error handler which returns HTTP Problem Details with JSON-LD context link",
"version": "0.0.0",
"private": true,
"type": "module",
"main": "main.js",
"module": "index.js",
Expand All @@ -17,6 +17,11 @@
"*.js",
"*.d.ts"
],
"dependencies": {
"express-http-problem-details": "^0.2.1",
"http-problem-details-mapper": "^0.1.7",
"set-link": "^1.0.0"
},
"devDependencies": {
"@babel/core": "^7.16.0",
"@babel/preset-env": "^7.16.0",
Expand All @@ -25,9 +30,13 @@
"@changesets/cli": "^2.17.0",
"@tpluscode/eslint-config": "^0.3.0",
"@types/chai": "^4.2.22",
"@types/express": "^4.17.13",
"@types/http-errors": "^1.8.1",
"@types/mocha": "^9.0.0",
"@types/set-link": "^1",
"@types/sinon": "^10.0.6",
"@types/sinon-chai": "^3.2.5",
"@types/supertest": "^2.0.11",
"@typescript-eslint/eslint-plugin": "^5.2.0",
"@typescript-eslint/parser": "^5.2.0",
"c8": "^7.10.0",
Expand All @@ -38,24 +47,27 @@
"eslint-plugin-import": "^2.25.2",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^5.1.1",
"express": "^4.17.1",
"husky": "^7.0.4",
"http-errors": "^1.8.0",
"lint-staged": "^11.2.6",
"mocha": "^9.1.3",
"sinon": "^11.1.2",
"sinon-chai": "^3.7.0",
"standard": "^16.0.3",
"supertest": "^6.1.6",
"typescript": "^4.3.4"
},
"repository": {
"type": "git",
"url": "git+https://github.com/tpluscode/ts-template.git"
"url": "git+https://github.com/hypermedia-app/hydra-box-problem-details.git"
},
"author": "Tomasz Pluskiewicz",
"license": "MIT",
"bugs": {
"url": "https://github.com/tpluscode/ts-template/issues"
"url": "https://github.com/hypermedia-app/hydra-box-problem-details/issues"
},
"homepage": "https://github.com/tpluscode/ts-template#readme",
"homepage": "https://github.com/hypermedia-app/hydra-box-problem-details#readme",
"mocha": {
"watch-files": [
"./**/*.ts"
Expand Down
61 changes: 57 additions & 4 deletions test/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,62 @@
import { describe, it } from 'mocha'
import express from 'express'
import request from 'supertest'
import { BadRequest } from 'http-errors'
import { expect } from 'chai'
import index from '..'
import * as error from '..'

describe('index', () => {
it('exports foo', () => {
expect(index).to.eq('foo')
describe('express-rdf-problem-details', () => {
it('sets context link', async () => {
// given
const app = express()
app
.use((req, res, next) => next(404))
.use(error.handler())

// when
const response = request(app).get('/foo')

await response.expect('link', /^<https:\/\/www\.w3\.org\/ns\/hydra\/error>/)
})

it('allows customizing mappers', async () => {
// given
const app = express()
app
.use((req, res, next) => next(new BadRequest()))
.use(error.handler({
mappers: [new (class {
get error() {
return 'BadRequestError'
}

mapError() {
return {
title: 'something wrong',
status: 400,
}
}
})()],
}))

// when
const { body } = await request(app).get('/foo')

expect(body).to.have.property('title', 'something wrong')
})

it('allows changing context', async () => {
// given
const app = express()
app
.use((req, res, next) => next(404))
.use(error.handler({
context: 'https://example.com/error.jsonld',
}))

// when
const response = request(app).get('/foo')

await response.expect('link', /^<https:\/\/example\.com\/error\.jsonld>/)
})
})
Loading

0 comments on commit 86addbc

Please sign in to comment.