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 )
Arg | Type | Default | Description |
---|
callback | function | () => false | The function which will be called as a hook |
If you want prevent fetch execution, then your callback should return true
request( { handlerName, data = {}, id } )
Arg | Type | Default | Description |
---|
handlerName | string | undefined | request name |
data | object | {} | request payload |
id | string | undefined | url id |
If there is no {{id}} template in metadata url, id will not be inserted
ResponseProcessor
constructor( mimeParser, invalidStatuses )
Arg | Type | Default | Description |
---|
mimeParser | MimeParser | undefined | Helper class for parsing response body |
invalidStatuses | array | [] | Array of statuses that will be considered invalid |
processResponse( httpResponse )
Arg | Type | Default | Description |
---|
httpResponse | Response | undefined | Response that will be processed |
If response contains body functino returns,
{
parsedBody,
httpResponse,
}
else returns passed httpResponse
MimeParser
constructor( mimeParserPairs )
Arg | Type | Default | Description |
---|
mimeParserPairs | array | [] | Pairs of mime-type and parser-function in mapable^mapable format |
Service
constructor(fetcher, responseProcessor, name)
Arg | Type | Default | Description |
---|
fetcher | Fetcher | null | Instance of Fetcher |
responseProcessor | ResponseProcessor | null | Instance of ResponseProcessor |
name | string | undefined | Service name |
request({ handlerName, data, id })
Arg | Type | Default | Description |
---|
handlerName | string | undefined | Name of endpoint specified in endpoint metadata by handler property |
data | object | {} | Request send data |
id | string | undefined | A string which will replace {{id}} template in url |
addHandler( handlerName, dataSchema )
Arg | Type | Default | Description |
---|
handlerName | string | undefined | The name of property which will be set on a service instance |
dataSchema | object | undefined | The data schema of request send data |
onBeforeRequest( callback )
Arg | Type | Default | Description |
---|
callback | function | (val) => val | The function which will be called as a hook |
onResponseHandled( callback )
Arg | Type | Default | Description |
---|
callback | function | (val) => val | The function which will be called as a hook |
onBeforeFetch( callback )
Arg | Type | Default | Description |
---|
callback | function | (val) => val | The function which will be called as a hook |
ServiceFactory
generateServices( api )
Arg | Type | Default | Description |
---|
api | object | undefined | An object that describe API modules; |
generateService( apiModuleName, apiModuleSchema )
Arg | Type | Default | Description |
---|
apiModuleName | string | undefined | Name of module which will be set as name of a service |
apiModuleSchema | object | undefined | The metadata of endpoint |
^mapable: mapable means array which can be used for creating of map