@phenyl/express
TypeScript icon, indicating that this package has built-in type declarations

4.1.0 • 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

API Documentation

  • createPhenylApiMiddleware()
  • createPhenylMiddleware()

createPhenylApiMiddleware()

Create express middleware to handle Phenyl REST APIs.

createPhenylApiMiddleware(
  restApiHandler: GeneralRestApiHandler,
  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) => ({ version: '1.2.3' })

// Settings of Phenyl REST API
const fg = { users: {}, nonUsers: {}, customQueries: { getVersion: { execute: getVersion } }, customCommands: {} }
const phenylRestApi = PhenylRestApi.createFromFunctionalGroup(fg, { entityClient: 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: GeneralServerParams,
  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: GeneralServerParams

Type of params is here:

type GeneralServerParams = {
  restApiHandler: GeneralRestApiHandler,
  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. 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

150

Version

4.1.0

License

Apache-2.0

Unpacked Size

29.4 kB

Total Files

5

Last publish

Collaborators

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