
Security News
vlt Launches "reproduce": A New Tool Challenging the Limits of Package Provenance
vlt's new "reproduce" tool verifies npm packages against their source code, outperforming traditional provenance adoption in the JavaScript ecosystem.
axios-rest-resource
Advanced tools
A small library that creates a pre-configured instance of axios to make HTTP requests to REST resources. Written in Typescript. Heavily inspired by AngularJS' $resource
A small library that creates a pre-configured instance of axios to make HTTP requests to REST resources. Written in Typescript. Heavily inspired by AngularJS' $resource.
npm i axios-rest-resource axios
Create resource module in your utils folder
// utils/resource.ts
import { ResourceBuilder } from "axios-rest-resource";
export const resourceBuilder = new ResourceBuilder({
baseURL: "http://localhost:3000"
});
Using a newly created resource builder create an actual resource
// api/entity1.js
import { resourceBuilder } from "utils/resource";
export const entity1Resource = resourceBuilder.build({ url: "/entity1" });
// exports an object
// {
// create: (action, requestConfig) => axiosPromise // sends POST http://localhost:3000/entity1,
// read: (action, requestConfig) => axiosPromise // sends GET http://localhost:3000/entity1,
// readOne: (action, requestConfig) => axiosPromise // sends GET http://localhost:3000/entity1/{id},
// remove: (action, requestConfig) => axiosPromise // sends DELETE http://localhost:3000/entity1/{id},
// update: (action, requestConfig) => axiosPromise // sends PUT http://localhost:3000/entity1/{id}
// }
Use your resource in your saga
import { entity1Resource } from "api/entity1";
// action here is { type: 'ENTITY1_READ_INIT' }
export function* entity1ReadSaga(action) {
const res = yield call(entity1Resource.read, action);
// sends GET http://localhost:3000/entity1
yield put({ type: "ENTITY1_READ_SUCCESS", payload: res });
}
// action here is { type: 'ENTITY1_READ_ONE_INIT', meta: { id: '123'} }
export function* entity1ReadOneSaga(action) {
const res = yield call(entity1Resource.readOne, action, {
params: { id: action.meta.id }
});
// sends GET http://localhost:3000/entity1/123
yield put({ type: "ENTITY1_READ_ONE_SUCCESS", payload: res });
}
You can pass an optional array of request interceptors to ResourceBuilder's constructor
export const resourceBuilder = new ResourceBuilder({
baseURL: "http://localhost:3000",
interceptors: [myRequestInterceptor]
});
You can read more about interceptors here. The only difference with axios' original interceptors is that axios-rest-resource passes an extended version of AxiosRequestConfig to its interceptors. It has an additional property AxiosResourceAdditionalProps. You can read more about it here. It contains an object with an action that triggerred that request. Most of the time you do not need to worry about it unless you want to access that action's data.
Axios-recource exposes two pre-defined interceptors:
interceptorUrlFormatter is always applied. interceptorAuthorizationToken you have to apply manually if you want to.
You can do it like this:
import {
ResourceBuilder,
interceptorAuthorizationToken
} from "axios-rest-resource";
export const resourceBuilder = new ResourceBuilder({
baseURL: "http://localhost:3000",
interceptors: [interceptorAuthorizationToken]
});
Here's how you can create an interceptor that logs all requests and apply it:
import { ResourceBuilder } from "axios-rest-resource";
import { AxiosRequestConfig } from "axios";
const interceptorLog = (config: AxiosRequestConfig) => {
console.log(
`axios-rest-resource.interceptorLog -> request ${JSON.stringify(config)}`
);
return config;
};
export const resourceBuilder = new ResourceBuilder({
baseURL: "http://localhost:3000",
interceptors: [interceptorAuthorizationToken]
});
If you want to access that additional property AxiosResourceAdditionalProps, you can do this:
import {
ResourceBuilder,
IAxiosResourceRequestConfig,
AxiosResourceAdditionalProps
} from "axios-rest-resource";
import { AxiosRequestConfig } from "axios";
const interceptorLogAction = (config: AxiosRequestConfig) => {
const configExtended = config as IAxiosResourceRequestConfig;
console.log(
`axios-rest-resource.interceptorLogAction -> action ${JSON.stringify(
configExtended[AxiosResourceAdditionalProps].action
)}`
);
return configExtended;
};
export const resourceBuilder = new ResourceBuilder({
baseURL: "http://localhost:3000",
interceptors: [interceptorAuthorizationToken, interceptorLogAction]
});
Create resource module in your utils folder
// utils/resource.ts
import { ResourceBuilder } from "axios-rest-resource";
export const resourceBuilder = new ResourceBuilder({
baseURL: "http://localhost:3000"
});
Using a newly created resource builder create an actual resource
// api/entity2.js
import {
IResourceSchemaKeysDefault,
resourceSchemaDefault
} from "axios-rest-resource";
import { resourceBuilder } from "utils/resource";
export const entity2Resource = resourceBuilder.build<
IResourceSchemaKeysDefault | "doSomething"
>({
schema: {
...resourceSchemaDefault,
doSomething: {
method: "post",
url: "/do-something"
}
},
url: "/entity2"
});
// exports an object
// {
// create: (action, requestConfig) => axiosPromise // sends POST http://localhost:3000/entity2,
// read: (action, requestConfig) => axiosPromise // sends GET http://localhost:3000/entity2,
// readOne: (action, requestConfig) => axiosPromise // sends GET http://localhost:3000/entity2/{id},
// remove: (action, requestConfig) => axiosPromise // sends DELETE http://localhost:3000/entity2/{id},
// update: (action, requestConfig) => axiosPromise // sends PUT http://localhost:3000/entity2/{id},
// doSomething: (action, requestConfig) => axiosPromise // sends POST http://localhost:3000/entity2/do-something
// }
Use your resource in your saga
import { entity2Resource } from "api/entity2";
// action here is { type: 'ENTITY2_DO_SOMETHING_INIT' }
export function* entity1ReDoSomthingSaga(action) {
const res = yield call(entity2Resource.doSomething, action);
// sends POST http://localhost:3000/entity2/do-something
yield put({ type: "ENTITY2_DO_SOMETHING_SUCCESS", payload: res });
}
// action here is { type: 'ENTITY2_READ_ONE_INIT', meta: { id: '123'} }
export function* entity2ReadOneSaga(action) {
const res = yield call(entity2Resource.readOne, action, {
params: { id: action.meta.id }
});
// sends GET http://localhost:3000/entity2/123
yield put({ type: "ENTITY2_READ_ONE_SUCCESS", payload: res });
}
You custom schema does not need to extend default schema if you do not want that
// api/entity.js
import { resourceBuilder } from "utils/resource";
export const entityResource = resourceBuilder.build<"doSomething">({
schema: {
doSomething: {
method: "post",
url: "/do-something"
}
},
url: "/entity"
});
// exports an object
// {
// doSomething: (action, requestConfig) => axiosPromise // sends POST http://localhost:3000/entity/do-something
// }
Alternatively you can use a partial of a default schema
// api/entity.js
import { resourceSchemaDefault } from "axios-rest-resource";
import { resourceBuilder } from "utils/resource";
const { read, readOne } = resourceSchemaDefault;
export const entityResource = resourceBuilder.build<"read" | "readOne">({
schema: {
read,
readOne
},
url: "/entity"
});
// exports an object
// {
// read: (action, requestConfig) => axiosPromise // sends GET http://localhost:3000/entity,
// readOne: (action, requestConfig) => axiosPromise // sends GET http://localhost:3000/entity/{id},
// }
You can pass a custom axios instance factory to ResourceBuilder. It's useful if you want to do something more with your axios instance but assign 'baseURL' and add request inerceptors.
import { ResourceBuilder } from "axios-rest-resource";
import axios, { AxiosInstance } from "axios";
const createAxiosInstanceFromUrl = (resourceUrl: string): AxiosInstance => {
const axiosInstance = axios.create({
// Don't forget to append resourceUrl to baseURL
baseURL: `http://localshot:3000${resourceUrl}`,
// It might be a good idea to tell your server what data you expect in return
headers: {
Accept: "application/json"
}
});
// This time we want to add response interceptors
axiosInstance.interceptors.response.use(myResponeInterceptor);
// Don't forget to add interceptorUrlFormatter if you want to keep {token} replacement in urls
axiosInstance.interceptors.request.use(interceptorUrlFormatter);
return axiosInstance;
};
export const resourceBuilder = new ResourceBuilder(createAxiosInstanceFromUrl);
As you can see there's a lot you have to remember. Not to keep all those things in mind you can utilize createAxiosResourceFactory.
import {
ResourceBuilder,
createAxiosResourceFactory
} from "axios-rest-resource";
import { AxiosInstance } from "axios";
const createAxiosResource = createAxiosResourceFactory({
baseURL: "http://localshot:3000"
});
const createAxiosInstanceFromUrl = (resourceUrl: string): AxiosInstance => {
// Creates an axios instance with appended resourceUrl and applied interceptorUrlFormatter. You can pass an additional array of request interceptors just like with ResourceBuilder. In fact ResourceBuilder uses this very function uner the hood.
const axiosInstance = createAxiosResource(resourceUrl);
// Add that response interceptor
axiosInstance.interceptors.response.use(myResponeInterceptor);
return axiosInstance;
};
export const resourceBuilder = new ResourceBuilder(createAxiosInstanceFromUrl);
As you noticed examples above are redux-saga centric. That's because this library was built with redux-saga in mind, but that doesn't make it unusable with redu-thunk. The only parameter enforced in any action is 'payload', which maskes it usable with thunks like this:
Create resource module in your utils folder
// utils/resource.ts
import { ResourceBuilder } from "axios-rest-resource";
export const resourceBuilder = new ResourceBuilder({
baseURL: "http://localhost:3000"
});
Using a newly created resource builder create an actual resource
// api/entity1.js
import { resourceBuilder } from "utils/resource";
export const entity1Resource = resourceBuilder.build({ url: "/entity1" });
// exports an object
// {
// create: (action, requestConfig) => axiosPromise // sends POST http://localhost:3000/entity1,
// read: (action, requestConfig) => axiosPromise // sends GET http://localhost:3000/entity1,
// readOne: (action, requestConfig) => axiosPromise // sends GET http://localhost:3000/entity1/{id},
// remove: (action, requestConfig) => axiosPromise // sends DELETE http://localhost:3000/entity1/{id},
// update: (action, requestConfig) => axiosPromise // sends PUT http://localhost:3000/entity1/{id}
// }
Use your resource in your thunk
import { entity1Resource } from "api/entity1";
export const entity1ReadThunk = async (dispatch) => {
dispatch({
type: "ENTITY1_READ_INIT"
})
const res = await entity1Resource.read()
// sends GET http://localhost:3000/entity1
dispatch({ type: "ENTITY1_READ_SUCCESS", payload: res });
}
export const entity1ReadOneThunk = (id) => async (dispatch) => {
dispatch({
type: "ENTITY1_READ_ONE_INIT",
meta: { id }
})
const res = await entity1Resource.readOne(undefined, { params: { id } })
// sends GET http://localhost:3000/entity1/{id}
yield put({ type: "ENTITY1_READ_ONE_SUCCESS", payload: res, { meta: { id } } });
}
export const entity1CreateThunk = (payload) => async (dispatch) => {
dispatch({
type: "ENTITY1_CREATE_INIT"
})
const res = await entity1Resource.create({ payload })
// sends POST http://localhost:3000/entity1 with body = payload
dispatch({ type: "ENTITY1_CREATE_SUCCESS", payload: res });
}
FAQs
Schema-based HTTP client powered by axios. Built with Typescript. Heavily inspired by AngularJS' $resource.
The npm package axios-rest-resource receives a total of 31 weekly downloads. As such, axios-rest-resource popularity was classified as not popular.
We found that axios-rest-resource demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
vlt's new "reproduce" tool verifies npm packages against their source code, outperforming traditional provenance adoption in the JavaScript ecosystem.
Research
Security News
Socket researchers uncovered a malicious PyPI package exploiting Deezer’s API to enable coordinated music piracy through API abuse and C2 server control.
Research
The Socket Research Team discovered a malicious npm package, '@ton-wallet/create', stealing cryptocurrency wallet keys from developers and users in the TON ecosystem.