Abstractions on-top of
superagentandfetch(or other Ajax libaries) for communication with REST. Targeted mostly againstDjango Rest Framework (DRF)running onDjangoso some logic might not be applicable for other frameworks.
Using NPM
npm i tg-resources
# And resource backend
npm i @tg-resources/superagent
# Or
npm i @tg-resources/fetchOr using Yarn
yarn add tg-resources
# And resource backend
yarn add @tg-resources/superagent
# Or
yarn add @tg-resources/fetchYES
import { Router } from "tg-resources"
import { SuperAgentResource: Resource } from "@tg-resources/superagent"
const onLoad = result => console.log(result);
const onError = result => console.error(result);
const api = new Router({
cats: new Resource('/cats'),
cat: new Resource('/cats/${pk}')
}, {
apiRoot: '/api/v1' // Set api root
});
const apiRouter = createRouter({
cats: '/cats',
cat: '/cats/${pk}',
}, {
apiRoot: '/api/v1', // Set api root
}, Resource);
// Do a get request to /api/v1/cats?gender=M
api.cats.fetch(null, {gender: 'M'}).then(onLoad, onError);
apiRouter.cats.fetch(null, {gender: 'M'}).then(onLoad, onError);
// Do a head request to /api/v1/cats?gender=M
api.cats.head(null, {gender: 'M'}).then(onLoad, onError);
apiRouter.cats.head(null, {gender: 'M'}).then(onLoad, onError);
// Do a post request to /api/v1/cats with data: {name: 'Twinky', gender: 'M'}
api.cats.post(null, {name: 'Twinky', gender: 'M'}).then(onLoad, onError);
apiRouter.cats.post(null, {name: 'Twinky', gender: 'M'}).then(onLoad, onError);
// Do a patch request to /api/v1/cats/1 with data: {name: 'Tinkelberg'}
api.cat.patch({pk: 1}, {name: 'Tinkelberg'}).then(onLoad, onError);
apiRouter.cat.patch({pk: 1}, {name: 'Tinkelberg'}).then(onLoad, onError);
// Do a put request to /api/v1/cats with data: {pk: 1, name: 'Twinky'}
api.cats.put(null, {pk: 1, name: 'Twinky', gender: 'M'}).then(onLoad, onError);
apiRouter.cats.put(null, {pk: 1, name: 'Twinky', gender: 'M'}).then(onLoad, onError);
// Do a delete request to /api/v1/cats/1 with data: {'free':'yes'}
api.cat.del({pk: 1}, {free: 'yes'}).then(onLoad, onError);
apiRouter.cat.del({pk: 1}, {free: 'yes'}).then(onLoad, onError);Please note that the router is useful for providing default configuration and grouping endpoints. It's still possible to use Resources without a router(see Resource api)
apiRoot(String): Base for all resource pathsheaders(Object|Function: Object): Optional Function or Object which can be used to add any additional headers to requests.cookies(Object|Function): Optional Function or Object which can be used to add any additional cookies to requests. Please note that in modern browsers this is disabled due to security concerns.mutateResponse(Function): Optional function with signature(responseData, rawResponse: ResponseWrapper, resource: Resource, requestConfig: Object) => responseDatawhich can be used to mutate response data before resolving it. E.g. This can be used to provide access to raw response codes and headers to your success handler.mutateError(Function): Optional function with signature(error: ResourceErrorInterface, rawResponse: ResponseWrapper, resource: Resource, requestConfig: Object) => errorwhich can be used to mutate errors before rejecting them. E.g. This can be used to provide access to raw response codes and headers to your error handler.statusSuccess(Array[int]|number): Array (or a single value) of status codes to treat as a success. Default: [200, 201, 204]statusValidationError(Array[int]|number): Array (or a single value) of status codes to treat as ValidationError. Default: [400]defaultAcceptHeader(String): Default accept header that is automatically added to requests (only ifheaders.Accept=undefined). Default:'application/json'parseErrors(Function): Function with signature(errorText, parentConfig) => [nonFieldErrors, errors]which is used to parse response errors into a ValidationError object. The default handler is built for Django/DRF errors.prepareError(Function): Function with signature(err, parentConfig) => mixedwhich is used to normalize a single error. The default handler is built for Django/DRF errors.mutateRawResponse(Function): Advanced usage: Optional function with signature(rawResponse: ResponseWrapper, requestConfig: Object) => rawResponsewhich can be used to mutate the response before it is resolved toresponseDataor aResourceErrorInterfacesubclass. Use the source ofResponseWrapper,SuperagentResponseandResource::ensureStatusAndJsonfor guidance.withCredentials(bool): Allow request backend to send cookies/authentication headers, useful when using same API for server-side rendering.allowAttachments(bool): Allow POST like methods to send attachments.
With tg-resources, all errors are Rejected. The logic is best described with an example:
const resource = new Resource('user/login');
const errorHandler = (error) => {
// Network error occurred
if (error.isNetworkError) {
console.error({
type: 'NETWORK_FAILED',
error,
});
} else if (error.isValidationError) {
// Validation error occurred (e.g.: wrong credentials)
console.error({
type: 'VALIDATION_ERROR',
error,
});
} else {
// As a last resort, also handle invalid response codes
console.error({
type: 'SERVER_ERROR',
error,
});
}
};
const payload = {
user: 'foo',
passwrod: 'bar'
};
resource.post(null, payload).then(user =>
console.log({
type: 'LOGGED_IN',
data: {
user,
},
}),
errorHandler,
);Creates type-safe Router instance.
routes(Object): Object matching pattern{ [key]: string | { [key]: string } }. String values are used as endpoints to create resource. For more info see Resource API This can be nested, meaning new router is created for object types found.config(Object): Object containing config for top level router. See ConfigurationresourceKlassResource: Resource class that implements backend. This allows any of the backends to be used when creatingRouter.
Construct a new resource for loading data from a single (or dynamic) endpoint
apiEndpoint(string): Endpoint used for this resource. Supports ES6 token syntax, e.g: "/foo/bar/${pk}"config(Object): Object containing config for this resource. See Configuration
The Resource module also supports dynamic urls by supporting ES6 token syntax. Request methods
can then provide values as an object using the first argument kwargs.
So for example:
new Resource('/foo/bar/${pk}').get({pk: 1}).then(x => x);Would result in a GET request to /foo/bar/1
(Resource): Returns instance of Resource.
Do a get request to the resource endpoint with optional kwargs and query parameters.
kwargs=null(Object): Object containing the replacement values if the resource uses tokenized urlsquery=null(Object|string): Query parameters to use when doing the request.requestConfig=null(Object): Configuration overrides, useful when using same API for server-side rendering.
Alias for Resource.fetch(kwargs, query, requestConfig) with options method.
Alias for Resource.fetch(kwargs, query, requestConfig) with head method.
(Promise): Returns a Promise that resolves to the remote result or throws if errors occur.
Do a method request to the resource endpoint with optional kwargs and query parameters.
kwargs=null(Object): Object containing the replacement values if the resource uses tokenized urlsdata=null(Object|string): Query parameters to use when doing the request.query=null(Object|string): Query parameters to use when doing the request.attachments=null(Array): Attachments, creates multipart requestrequestConfig=null(Object): Configuration overrides, useful when using same API for server-side rendering.
(Promise): Returns a Promise that resolves to the remote result or throws if errors occur.
Alias for Resource.post(kwargs, data, query, requestConfig) with options method.
Alias for Resource.post(kwargs, data, query, requestConfig) with put method.
Alias for Resource.post(kwargs, data, query, requestConfig) with del method.
Generic base class for all errors that can happen during requests
isNetworkError(bool): AlwaysfalseisInvalidResponseCode(bool): AlwaysfalseisValidationError(bool): Alwaysfalse
Error class used for all network related errors
isNetworkError(bool): Alwaystrue
error(Error): Original Error object that occured during network transport
Error class used when unexpected response code occurs
isInvalidResponseCode(bool): Alwaystrue
statusCode(string): Response status coderesponseText(int): Response body text
Error class used when backend response code is in config.statusValidationError.
isInvalidResponseCode(bool): AlwaysfalseisValidationError(bool): Alwaystrue
errors: (ValidationErrorInterface|any): The result fromrequestConfig.parseError
Error types returned by the default error parser.
Supports iteration (map/forEach/for .. of/etc)
errors: (any): Errors and error messages.
Since DRF errors can be arbitrarily nested and one field can have multiple errors, some specific types of interest:
SingleValidationError: Errors for a single field the.errorsattribute is a list of strings.ValidationError: Errors for an object,.errorsis an object with field names as keys.ListValidationError: Errors related to list of objects..errorsis a list ofValidationErrorInterface.
(*) Not applicable to SingleValidationError
(bool): True if there are any errors.
Get field specific error
fieldName(Array|string): Field name or path to child error, e.g['parent', 'child']or array indexes forListValidationError[allowNonField=false](bool): If true, also check for nonFieldErrors if the specified field does not have an error
(any): Returns a normalized error for fieldName or null
Get first error normalized to a string for this ValidationError
[allowNonField=false](bool): If true, also check for nonFieldErrors
(any): First error as a string or null
MIT © Thorgate