phenyl-express

0.2.14 • Public • Published

phenyl-expressCircleCI

Express middleware to use Phenyl in it.

import express from 'express'
import { createPhenylApiMiddleware } from 'phenyl-express'
 
// instance of PhenylRestApi (see [phenyl-rest-api](https://github.com/phenyl-js/phenyl/tree/master/modules/phenyl-rest-api).)
const phenylRestApi = ...
const app = express()
app.use(createPhenylApiMiddleware(phenylRestApi))
app.listen(3000)

Installation

npm install phenyl-express

Using types with flow

For Flow annotations, just use /jsnext entrypoint.

import { createPhenylApiMiddleware } from 'phenyl-express/jsnext'

API Documentation

  • createPhenylApiMiddleware()
  • createPhenylMiddleware()

createPhenylApiMiddleware()

Create express middleware to handle Phenyl REST APIs.

createPhenylApiMiddleware(
  restApiHandler: RestApiHandler,
  pathRegex: RegExp = /\^/api\/.*$/,
): Function // express middleware

Parameters

restApiHandler

Object, which has a method handleRequestData(reqData: RequestData): Promise<ResponseData>. Instance of PhenylRestApi are compatible with restApiHandler.

pathRegex

RegExp. Optional. Paths which match the pathRegex are handled by Phenyl. By default, it's /\^/api\/.*$/; paths start with "/api/" are passed.

Example

import express from 'express'
import { createPhenylApiMiddleware } from 'phenyl-express'
import PhenylRestApi from 'phenyl-rest-api'
import { createEntityClient } from 'phenyl-memory-db' // create DB Client used in Phenyl REST API
 
const getVersion = async (customQuery) => ({ ok: 1, result: { version: '1.2.3' } })
 
// Settings of Phenyl REST API
const fg = { users: {}, nonUsers: {}, customQueries: { getVersion }, customCommands: {} }
const phenylRestApi = PhenylRestApi.createFromFunctionalGroup(fg, { client: createEntityClient() })
const app = express()
app.use(createPhenylApiMiddleware(phenylRestApi))
app.get('/foo/bar', (req, res) => res.text(`Hello, Express!`))
app.listen(3000)

Client-side code will be like the following.

import PhenylHttpClient from 'phenyl-http-client'
const client = new PhenylHttpClient({ url: 'http://localhost:3000' })
const { result } = await client.runCustomQuery({ name: 'getVersion' })
console.log(result.version) // 1.2.3
const text = await client.requestText('/foo/bar')
console.log(text) // Hello, Express!

createPhenylMiddleware()

Create express middleware to handle Phenyl REST APIs and non-REST-API paths defined by customRequestHandler.

createPhenylMiddleware(
  params: ServerParams,
  pathRegex: RegExp = /^\/api\/.*$|^\/explorer($|\/.*$)/
): Function // express middleware

Why this?

It's true that Express can be easier to set your custom pages than Phenyl's customRequestHandler. Some non-rest entrypoints, however, are offered by Phenyl Family (like phenyl-api-explorer) and this function will be suitable for using them.

Parameters

params: ServerParams

Type of params is here:

type ServerParams = {
  restApiHandler: RestApiHandler,
  customRequestHandler?: (encodedHttpRequest: EncodedHttpRequest, restApiClient: RestApiClient) => Promise<EncodedHttpResponse>,
  modifyPath?: (path: string) => string,
}

restApiHandler is the same as one described in createPhenylApiMiddleware(). It's an object with a method handleRequestData(reqData: RequestData): Promise<ResponseData>.

customRequestHandler is a function to handle general request and returns response information. It's first argument is here:

type EncodedHttpRequest = {
  method: 'GET' | 'POST' | 'PUT' | 'DELETE',
  headers: { [name: string]: string },
  path: string, // must start with "/"
  qsParams?: { [name: string]: string },
  body?: string,
}

The second argument restApiClient is a client for PhenylRestApi. See phenyl-interfaces for the detailed interface. It implements EntityClient, AuthClient and CustomClient.

The return value must be Promise<EncodedHttpResponse>.

type EncodedHttpResponse = {
  +headers: { [name: string]: string } | Headers,
  +body: string, // stringified JSON or parsed JSON
  statusCode: number,
}

pathRegex

RegExp. Optional. Paths which match the pathRegex are handled by Phenyl. By default, it's /^/api/.$|^/explorer($|/.$)/; paths start with "/api/" or "/explorer" are passed.

/explorer is redirected because phenyl-api-explorer use the URL.

Example

import express from 'express'
import { createPhenylApiMiddleware } from 'phenyl-express'
import PhenylRestApi from 'phenyl-rest-api'
import { createEntityClient } from 'phenyl-memory-db' // create DB Client used in Phenyl REST API
 
// Settings of Phenyl REST API
const fg = { users: {}, nonUsers: {}, customQueries: {}, customCommands: {} }
const phenylRestApi = PhenylRestApi.createFromFunctionalGroup(fg, { client: createEntityClient() })
const app = express()
app.use(createPhenylMiddleware({
  restApiHandler: phenylRestApi,
  async customRequestHandler(httpReq) {
    const { headers, body, method, qsParams, path } = httpReq
    return {
      statusCode: 200,
      headers: { 'Content-Type': 'text/plain' },
      body: `Hi Phenyl, I'm ${qsParams ? qsParams.name : 'NoName'}!`
    }
  }
}, /^\/api\/.*$|^\/abc$/))
 
app.get('/foo/bar', (req, res) => res.text(`Hello, Express!`))
app.listen(3000)

Client-side code will be like the following.

import PhenylHttpClient from 'phenyl-http-client'
const client = new PhenylHttpClient({ url: 'http://localhost:3000' })
const { result } = await client.runCustomQuery({ name: 'getVersion' })
console.log(result.version) // 1.2.3
const text1 = await client.requestText('/abc?name=John')
console.log(text1) // Hi Phenyl, I'm John!
 
const text2 = await client.requestText('/foo/bar')
console.log(text2) // Hello, Express!

LICENSE

Apache License 2.0

Readme

Keywords

none

Package Sidebar

Install

npm i phenyl-express

Weekly Downloads

31

Version

0.2.14

License

Apache License 2.0

Unpacked Size

27.9 kB

Total Files

7

Last publish

Collaborators

  • camcam-lemon
  • alternacrow
  • bowzstandard
  • shinout
  • naturalclar
  • sasurau4
  • wh1tecat