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
npm i --save ttt-rest-service
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 binds to the API Module metadata
API Module metadata is array of object which describe endpoints
Describe send data of endpoints with JSON Schema
const authApiModule = [
{
// endpoint1
},
{
// endpoint2
},
]
- 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
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
},
},
]
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()
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()
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'
})
}
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)
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
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
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
Arg | Type | Default | Description |
---|---|---|---|
mimeParser | MimeParser | undefined | Helper class for parsing response body |
invalidStatuses | array | [] | Array of statuses that will be considered invalid |
Arg | Type | Default | Description |
---|---|---|---|
httpResponse | Response | undefined | Response that will be processed |
If response contains body functino returns,
{
parsedBody,
httpResponse,
}
else returns passed httpResponse
Arg | Type | Default | Description |
---|---|---|---|
mimeParserPairs | array | [] | Pairs of mime-type and parser-function in mapable1 format |
Arg | Type | Default | Description |
---|---|---|---|
fetcher | Fetcher | null | Instance of Fetcher |
responseProcessor | ResponseProcessor | null | Instance of ResponseProcessor |
name | string | undefined | Service name |
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 |
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 |
Arg | Type | Default | Description |
---|---|---|---|
callback | function | (val) => val | The function which will be called as a hook |
Arg | Type | Default | Description |
---|---|---|---|
callback | function | (val) => val | The function which will be called as a hook |
Arg | Type | Default | Description |
---|---|---|---|
callback | function | (val) => val | The function which will be called as a hook |
Arg | Type | Default | Description |
---|---|---|---|
api | object | undefined | An object that describe API modules; |
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 |
Footnotes
-
mapable means array which can be used for creating of map ↩