1.0.5 • Published 2 years ago

ttt-rest-service v1.0.5

Weekly downloads
-
License
MIT
Repository
github
Last release
2 years ago

ttt-rest-service

JS Library which gives functionallity to create services for client-server communication with REST style

Library provides:

- default Service
- Composite classes:
    - Fetcher
    - ResponseProcessor
    - MimeParser
- Factories:
    - FetcherFactory
    - ServiceFactory

Use composite classes to create your own service if default Service does not fulfill the needs

Installation

npm i --save ttt-rest-service

Getting Started

import {
  Fetcher,
  MimeParser,
  ResponseProcessor,
  Service,
  FetcherFactory,
  ServiceFactory
} from 'ttt-rest-service'

import {
  ValidationError,
  StatusError,
  MimeError
} from 'ttt-rest-service/dist/errors'

// then look at one of example below

Fetcher and API Modules Metadata

API Module structure:

const authApiModule = [
    {
        // endpoint1
    },
    {
        // endpoint2
    },
]

Endpoint structure:

- method[string]
    request method
- url[string]
    request url. There is posibility to insert ID into url,
    use ".../image/delete/{{id}}/"
    to get ".../image/delete/id_102/"
- secure[boolean]
    help variable
- roles[array]
    help variable
- handler[string]
    name of the class method that will be generated
- headers[object]
    request headers
- schema[object]
    JSON schema of the data send by the request

ApiModuleExample:

    const authApiModule = [
    {
      method: 'POST',
      url: '/auth/login',
      secure: false,
      handler: 'login',
      roles: [],
      headers: {
        'Content-Type': 'application/json',
        Accept: 'application/json',
        Credentials: 'include'
      },
      schema: {
        type: 'object',
        required: [ 'username', 'password' ],
        properties: {
          username: {
            type: 'string',
            minLength: 3
          },
          password: {
            type: 'string',
            minLength: 6
          }
        }
      },

    },
    {
      method: 'GET',
      url: '/auth/logout/{{id}}',
      secure: true,
      handler: 'logout',
      roles: [ 'user' ],
      headers: {
        Accept: 'application/json',
        Credentials: 'include'
      },
      schema: {
        // another JSON Schema
      },
    },
  ]

Example of usage

MimeParser && ResponseProcessor:

const { MimeParser, ResponseProcessor } = require("ttt-rest-service")

const mimeParserPairs = [
    [ 'application/json', ( httpResponse ) => httpResponse.json() ]
]
const mimeParser = new MimeParser( mimeParserPairs )
const responseProcessor = new ResponseProcessor( mimeParser )

async function example() {
    const request = await fetch( 'some-url.com/get-instance' )
    const processedResponse = await responseProcessor.processResponse( request )
}

example()

Fetcher

const { FetcherFactory } = require('ttt-rest-service')

const authModule = [
  {
    method: 'POST',
    url: '/auth/login',
    secure: false,
    handler: 'login',
    roles: [],
    headers: {
      'Content-Type': 'application/json',
      Accept: 'application/json',
    },
    schema: {
      type: 'object',
      required: [ 'username', 'password' ],
      properties: {
        username: {
          type: 'string',
          minLength: 3
        },
        password: {
          type: 'string',
          minLength: 6
        }
      },
    },
  },
];

const fetcherFactory = new FetcherFactory()
const fetcher = fetcherFactory.getFetcher(authModule)
const authToken = localStorage.get('authToken')

fetcher.onBeforeRequest(( requestParameters ) => {
    if(requestParameters.secure && authToken === null) {
        return true // prevent fetch
    } else {
        requestParameters.fetchParams.headers.Authorization = `Token ${ authToken }`
    }
})

async function example() {
    const sendData = {
        username: 'username',
        password: 'strong_password'
    }
    const request = await fetcher.request({ handlerName: 'login', data: sendData })
}

example()

Service

const { Service, fetcherFactory, mimeParser, responseProcessor } = require('ttt-rest-service')

const authModule = [
  {
    method: 'POST',
    url: '/auth/login',
    secure: false,
    handler: 'login',
    roles: [],
    headers: {
      'Content-Type': 'application/json',
      Accept: 'application/json',
    },
    schema: {
      type: 'object',
      required: [ 'username', 'password' ],
      properties: {
        username: {
          type: 'string',
          minLength: 3
        },
        password: {
          type: 'string',
          minLength: 6
        }
      },
    },
  },
];

const fetcherFactory = new FetcherFactory();
const fetcher = fetcherFactory.getFetcher( authModule );

const mimeParserPairs = [
    [ 'application/json', ( httpResponse ) => httpResponse.json() ]
];
const mimeParser = new MimeParser( mimeParserPairs );
const responseProcessor = new ResponseProcessor( mimeParser );

const service = new Service(fetcher, responseProcessor)

service.onBeforeRequest(({ handlerName, data, id}) => {
    data.processedInBeforeRequest = true
    return {
        handlerName,
        data,
        id
    }
})

service.onResponseHandled(({ handledResponse }) => {
    handledResponse.parsedBody.processedInHook = true
})

async function exampleWithRequest() {
    const request = await service.request({
        handlerName: 'login',
        data: {
            username: 'username1',
            password: 'very_very_strong'
        }
    })
}

async function exampleWithSpecifiedHandler() {
    service.addHandler('login', authModule.schema)
    service.login({
        username: 'username1',
        password: 'very_weak_password'
    })
}

ServiceFactory

const { ServiceFactory, FetcherFactory, MimeParser, ResponseProcessor } = require('ttt-rest-service')

const API = {
    auth: [
        {
            method: 'POST',
            url: 'url.com/login/',
            secure: false,
            handlerName: 'login',
            roles: [],
            headers: {
                'Content-Type': 'application/json',
                Accept: 'application/json'
            },
            schema: {
                //...
            }
        }
    ],
    user: [
        {
            method: 'GET',
            url: 'url.com/user/{{id}}',
            secure: true,
            handlerName: 'getUser',
            roles: [],
            headers: {
                Accept: 'application/json'
            },
            schema: {
                // ...
            }
        }
    ]
}

const fetcherFactory = new FetcherFactory();

const mimeParserPairs = [
    [ 'application/json', ( httpResponse ) => httpResponse.json() ]
];
const mimeParser = new MimeParser( mimeParserPairs );
const responseProcessor = new ResponseProcessor( mimeParser );

const serviceFactory = new ServiceFactory( fetcherFactory, responseProcessor );
const services = serviceFactory.generateServices( API )

const authService = services.authService
const userService = services.userService

authService.login({
    username: 'username1',
    password: 'password1'
})

const userId = 'user_id_12343'
userService.getUser({
    allInformation: true
}, userId)

Library API

FetcherFactory

getFetcher( apiModuleSchema )

apiModuleStructure:

const anApiModule = [
  {
    method: 'POST',
    url: 'url.com/login/',
    secure: false,
    handlerName: 'login',
    roles: [],
    headers: {
     // ...
    },
    schema: {
      //...
    }
  },
  {
    // endpoint 2
    // ...
  }
]

*Schema in endpoint metadata MUST BE IN JSON SCHEMA FORMAT*

Fetcher

onBeforeFetch( callback )

ArgTypeDefaultDescription
callbackfunction() => falseThe function which will be called as a hook

If you want prevent fetch execution, then your callback should return true

request( { handlerName, data = {}, id } )

ArgTypeDefaultDescription
handlerNamestringundefinedrequest name
dataobject{}request payload
idstringundefinedurl id

If there is no {{id}} template in metadata url, id will not be inserted

ResponseProcessor

constructor( mimeParser, invalidStatuses )

ArgTypeDefaultDescription
mimeParserMimeParserundefinedHelper class for parsing response body
invalidStatusesarray[]Array of statuses that will be considered invalid

processResponse( httpResponse )

ArgTypeDefaultDescription
httpResponseResponseundefinedResponse that will be processed

If response contains body functino returns,

{
    parsedBody,
    httpResponse,
}

else returns passed httpResponse

MimeParser

constructor( mimeParserPairs )

ArgTypeDefaultDescription
mimeParserPairsarray[]Pairs of mime-type and parser-function in mapable^mapable format

Service

constructor(fetcher, responseProcessor, name)

ArgTypeDefaultDescription
fetcherFetchernullInstance of Fetcher
responseProcessorResponseProcessornullInstance of ResponseProcessor
namestringundefinedService name

request({ handlerName, data, id })

ArgTypeDefaultDescription
handlerNamestringundefinedName of endpoint specified in endpoint metadata by handler property
dataobject{}Request send data
idstringundefinedA string which will replace {{id}} template in url

addHandler( handlerName, dataSchema )

ArgTypeDefaultDescription
handlerNamestringundefinedThe name of property which will be set on a service instance
dataSchemaobjectundefinedThe data schema of request send data

onBeforeRequest( callback )

ArgTypeDefaultDescription
callbackfunction(val) => valThe function which will be called as a hook

onResponseHandled( callback )

ArgTypeDefaultDescription
callbackfunction(val) => valThe function which will be called as a hook

onBeforeFetch( callback )

ArgTypeDefaultDescription
callbackfunction(val) => valThe function which will be called as a hook

ServiceFactory

generateServices( api )

ArgTypeDefaultDescription
apiobjectundefinedAn object that describe API modules;

generateService( apiModuleName, apiModuleSchema )

ArgTypeDefaultDescription
apiModuleNamestringundefinedName of module which will be set as name of a service
apiModuleSchemaobjectundefinedThe metadata of endpoint

^mapable: mapable means array which can be used for creating of map

1.0.5

2 years ago

1.0.4

2 years ago

1.0.3

2 years ago

1.0.2

2 years ago

1.0.1

2 years ago

1.0.0

2 years ago