Services
Services are classes that gets delegated some responsibility by upfront. With services, it's easy to adjust upfront's behaviour without having to extend the model and write elaborate overrides. You may switch them out or extend them to fit your needs. To see how you change the implementations, visit the global config page.
Service Interfaces
Services have some interfaces that they need to implement on order to work.
ApiCaller
ApiCaller an object with a call
method defined which is utilized by all the ajax requests initiated by upfront, and it is responsible for sending a request with the given data returning a Promise<ApiResponse>
. The arguments the call
method takes in order are:
url
- a stringmethod
- a string representing the http methoddata
(optional) - an object or FormDatacustomHeaders
(optional) - an object with string keys and string or array of strings valuequeryParameters
(optional) - an object to send as query parameters in the url
HandlesApiResponse
HandlesApiResponse's task is to handle the parsing of the ApiResponse returned by ApiCaller and deal with any errors. It defines a handle
method which takes a Promise<ApiResponse>
and it should return a Promise<any>
.
ApiResponse
As you might have noticed in the above service interfaces they work with an object called ApiResponse
as opposed to a Response. This is because this interface is more generic and can easily be implemented if deciding to use something other than the fetch api. The only keys always available on the object are the following properties:
TIP
Typescript users may use module augmentation to specify what their ApiResponse
is actually look like:
// shims/upfront.d.ts
import type { ApiResponse as BaseApiResponse } from '@upfrontjs/framework';
declare module '@upfrontjs/framework' {
interface ApiResponse extends BaseApiResponse {
myKey?: string;
}
}
Upfront provides the implementations for the above interfaces which should cover most use cases. If you don't set your own implementation, upfront will fall back to these default services.
- API - implements
ApiCaller
- ApiResponseHandler - implements
HandlesApiResponse
Using Custom Services
Implementing interfaces
If you're thinking about creating your own service, for reference you may check out the interfaces and/or the default implementation's source code.
Creating a service is easy as:
// MyHandler.js
import notification from 'notification-lib';
export default class MyHandler {
handle(promise) {
return promise.then(response => {
if (response.status >= 300 && response.status < 400) {
// etc...
}
// response handling
})
.catch(error => notification(error.message));
}
}
// entry-file.js
import { GlobalConfig } from '@upfrontjs/framework';
import MyHandler from './Services/MyHandler';
new GlobalConfig({
apiResponseHandler: MyHandler,
})
// MyHandler.ts
import type { HandlesApiResponse } from '@upfrontjs/framework';
import notification from 'notification-lib';
export default class MyHandler implements HandlesApiResponse {
public handle(promise: Promise<Response>): Promise<any> {
return promise
.then(response => {
if (response.status >= 300 && response.status <= 400) {
// etc...
}
// response handling
})
.catch((error) => notification(error.message))
}
}
// entry-file.ts
import { GlobalConfig } from '@upfrontjs/framework';
import MyHandler from './Services/MyHandler';
new GlobalConfig({
apiResponseHandler: MyHandler,
})
Extending Services
If you just want to extend a service to add some functionality like adding initRequest() to the API, that can be achieved like so:
// MyHandler.js
import { ApiResponseHandler } from '@upfrontjs/framework';
export default class MyHandler extends ApiResponseHandler {
handleFinally() {
// any operations after the request
}
}
// entry file.js
import { GlobalConfig } from '@upfrontjs/framework';
import MyHandler from './Services/MyHandler';
new GlobalConfig({
apiResponseHandler: MyHandler,
})
// MyHandler.ts
import { ApiResponseHandler } from '@upfrontjs/framework';
export default class MyHandler extends ApiResponseHandler {
public handleFinally(): void {
// any operations after the request
}
}
// entry file.ts
import { GlobalConfig } from '@upfrontjs/framework';
import MyHandler from './Services/MyHandler';
new GlobalConfig({
apiResponseHandler: MyHandler,
})
You can find examples of testing custom services in the Testing section.