axios-rest-resource
Advanced tools
Comparing version 0.2.1 to 0.3.0
@@ -1,2 +0,2 @@ | ||
export * from './src/axios'; | ||
export * from './src/resource'; | ||
export * from './src/url-formatter'; |
@@ -1,2 +0,7 @@ | ||
export * from './src/axios'; | ||
export * from './src/resource'; | ||
"use strict"; | ||
function __export(m) { | ||
for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; | ||
} | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
__export(require("./src/resource")); | ||
__export(require("./src/url-formatter")); |
@@ -1,47 +0,27 @@ | ||
import { AxiosPromise, AxiosRequestConfig } from 'axios'; | ||
import { ICreateAxiosInstanceFactoryParams, ICreateAxiosInstanceFromUrl } from './axios'; | ||
import { AxiosInstance, AxiosPromise, AxiosRequestConfig } from 'axios'; | ||
export declare type IAPIMethod = (requestConfig?: Partial<AxiosRequestConfig>) => AxiosPromise; | ||
export interface IResource { | ||
[index: string]: IAPIMethod; | ||
} | ||
export interface IResourceDefault { | ||
read: IAPIMethod; | ||
readOne: IAPIMethod; | ||
create: IAPIMethod; | ||
update: IAPIMethod; | ||
remove: IAPIMethod; | ||
} | ||
export declare type IResource<Methods extends string> = { | ||
[Method in Methods]: IAPIMethod; | ||
}; | ||
declare type RequestMethod = 'get' | 'delete' | 'head' | 'options' | 'post' | 'put' | 'patch'; | ||
export interface IAPIMethodSchema { | ||
method: string; | ||
method: RequestMethod; | ||
url?: string; | ||
} | ||
export declare type IResourceSchemaKeysDefault = 'create' | 'read' | 'readOne' | 'remove' | 'update'; | ||
export declare const resourceSchemaDefault: { | ||
[Key in IResourceSchemaKeysDefault]: IAPIMethodSchema; | ||
export declare type IResourceSchema<T extends string> = { | ||
[Key in T]: IAPIMethodSchema; | ||
}; | ||
export interface IBuildParams { | ||
url: string; | ||
export declare type IResourceMethodsDefault = 'create' | 'read' | 'readOne' | 'remove' | 'update'; | ||
export declare const resourceSchemaDefault: IResourceSchema<IResourceMethodsDefault>; | ||
interface IAxiosConfig extends AxiosRequestConfig { | ||
baseURL: string; | ||
} | ||
export interface IBuildParamsExtended<ResourceMethods extends string> extends IBuildParams { | ||
schema: { | ||
[Key in ResourceMethods]: IAPIMethodSchema; | ||
}; | ||
} | ||
export declare type IBuildParamsExtendedRes<ResourceMethods extends string> = { | ||
[Key in ResourceMethods]: IAPIMethod; | ||
}; | ||
export declare class ResourceBuilder { | ||
protected readonly _schemaDefault: { | ||
create: IAPIMethodSchema; | ||
read: IAPIMethodSchema; | ||
readOne: IAPIMethodSchema; | ||
remove: IAPIMethodSchema; | ||
update: IAPIMethodSchema; | ||
}; | ||
protected readonly _createAxiosResource: ICreateAxiosInstanceFromUrl; | ||
constructor(createParams: ICreateAxiosInstanceFromUrl | ICreateAxiosInstanceFactoryParams); | ||
build(buildParams: IBuildParams): IResourceDefault; | ||
build<ResourceMethods extends string>(buildParams: IBuildParamsExtended<ResourceMethods>): IBuildParamsExtendedRes<ResourceMethods>; | ||
protected _isBuildRapamsExtended<ResourceMethods extends string>(buildParams: IBuildParams | IBuildParamsExtended<ResourceMethods>): buildParams is IBuildParamsExtended<ResourceMethods>; | ||
protected _isAxiosResourceFactoryParams(createParams: ICreateAxiosInstanceFromUrl | ICreateAxiosInstanceFactoryParams): createParams is ICreateAxiosInstanceFactoryParams; | ||
readonly axiosInstance: AxiosInstance; | ||
protected readonly _schemaDefault: IResourceSchema<IResourceMethodsDefault>; | ||
constructor(axiosConfig: IAxiosConfig); | ||
build(resourceUrl: string): IResource<IResourceMethodsDefault>; | ||
build<Methods extends string>(resourceUrl: string, schema: IResourceSchema<Methods>): IResource<Methods>; | ||
protected _build<Methods extends string>(resourceUrl: string, schema: IResourceSchema<Methods>): IResource<Methods>; | ||
} | ||
export {}; |
@@ -1,51 +0,54 @@ | ||
import { createAxiosResourceFactory } from './axios'; | ||
export const resourceSchemaDefault = { | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const axios_1 = require("axios"); | ||
const url_formatter_1 = require("./url-formatter"); | ||
exports.resourceSchemaDefault = { | ||
create: { | ||
method: 'post' | ||
method: 'post', | ||
}, | ||
read: { | ||
method: 'get' | ||
method: 'get', | ||
}, | ||
readOne: { | ||
method: 'get', | ||
url: '/{id}' | ||
url: '/{id}', | ||
}, | ||
remove: { | ||
method: 'delete', | ||
url: '/{id}' | ||
url: '/{id}', | ||
}, | ||
update: { | ||
method: 'put', | ||
url: '/{id}' | ||
} | ||
url: '/{id}', | ||
}, | ||
}; | ||
export class ResourceBuilder { | ||
constructor(createParams) { | ||
this._schemaDefault = resourceSchemaDefault; | ||
if (this._isAxiosResourceFactoryParams(createParams)) { | ||
this._createAxiosResource = createAxiosResourceFactory(createParams); | ||
return; | ||
class ResourceBuilder { | ||
constructor(axiosConfig) { | ||
this._schemaDefault = exports.resourceSchemaDefault; | ||
if (!axiosConfig.headers) { | ||
axiosConfig.headers = {}; | ||
} | ||
this._createAxiosResource = createParams; | ||
if (axiosConfig.headers.Accept === undefined) { | ||
axiosConfig.headers.Accept = 'application/json'; | ||
} | ||
this.axiosInstance = axios_1.default.create(axiosConfig); | ||
this.axiosInstance.interceptors.request.use(url_formatter_1.interceptorUrlFormatter); | ||
} | ||
build(buildParams) { | ||
const { url } = buildParams; | ||
let schema = this._schemaDefault; | ||
if (this._isBuildRapamsExtended(buildParams)) { | ||
schema = buildParams.schema; | ||
build(resourceUrl, schema) { | ||
if (!schema) { | ||
return this._build(resourceUrl, this._schemaDefault); | ||
} | ||
const axiosInstance = this._createAxiosResource(url); | ||
return this._build(resourceUrl, schema); | ||
} | ||
_build(resourceUrl, schema) { | ||
const resource = {}; | ||
for (const methodName of Object.keys(schema)) { | ||
const methodSchema = schema[methodName]; | ||
resource[methodName] = (requestConfig = {}) => axiosInstance.request(Object.assign({}, requestConfig, methodSchema)); | ||
let url = methodSchema.url || ''; | ||
url = `${resourceUrl}${url}`; | ||
resource[methodName] = (requestConfig = {}) => this.axiosInstance.request(Object.assign({}, requestConfig, methodSchema, { url })); | ||
} | ||
return resource; | ||
} | ||
_isBuildRapamsExtended(buildParams) { | ||
return !!buildParams.schema; | ||
} | ||
_isAxiosResourceFactoryParams(createParams) { | ||
return typeof createParams === 'object'; | ||
} | ||
} | ||
exports.ResourceBuilder = ResourceBuilder; |
{ | ||
"name": "axios-rest-resource", | ||
"version": "0.2.1", | ||
"description": "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", | ||
"version": "0.3.0", | ||
"description": "Schema-based HTTP client powered by axios. Built with Typescript. Heavily inspired by AngularJS' $resource.", | ||
"keywords": [ | ||
@@ -11,11 +11,10 @@ "axios", | ||
"ajax", | ||
"api" | ||
"api", | ||
"schema" | ||
], | ||
"main": "dist/index.js", | ||
"scripts": { | ||
"test": "./node_modules/.bin/mocha --recursive --use_strict --require ts-node/register './**/*.test.ts'", | ||
"compile": "rm -rf ./dist && ./node_modules/.bin/tsc -p ./tsconfig.prod.json", | ||
"lint": "./node_modules/.bin/tsc -p ./tsconfig.json --noEmit && ./node_modules/.bin/tslint -c ./tslint.json -p ./tsconfig.json", | ||
"docs": "rm -rf docs/api && ./node_modules/.bin/typedoc --tsconfig ./tsconfig.docs.json --mode file --ignoreCompilerErrors --excludePrivate --excludeProtected --readme none --theme markdown --mdHideSources --mdEngine github --out ./docs/api ./index.ts && find ./docs/api/ -type f -exec sed -i \"s/\\`\\`\\`js/\\\\n\\`\\`\\`js/g\" {} \\; && npm run markdown-format", | ||
"markdown-format": "./node_modules/.bin/doctoc ./README.md && ./node_modules/.bin/prettier --write './**/*.md'", | ||
"test": "npx jest -i", | ||
"compile": "npx rimraf ./dist && npx tsc -p ./tsconfig.prod.json", | ||
"lint": "npx tsc -p ./tsconfig.json --noEmit && npx tslint -c ./tslint.json -p ./tsconfig.json", | ||
"prepack": "npm run compile" | ||
@@ -34,28 +33,21 @@ }, | ||
"devDependencies": { | ||
"@types/chai": "^4.1.4", | ||
"@types/mocha": "^5.2.4", | ||
"@types/jest": "^23.3.13", | ||
"@types/moxios": "^0.4.8", | ||
"@types/sinon": "^5.0.1", | ||
"axios": "^0.18.0", | ||
"chai": "^4.1.2", | ||
"doctoc": "^1.3.1", | ||
"mocha": "^5.2.0", | ||
"doctoc": "^1.4.0", | ||
"husky": "^1.3.1", | ||
"jest": "^24.0.0", | ||
"lint-staged": "^8.1.0", | ||
"moxios": "^0.4.0", | ||
"pre-commit": "^1.2.2", | ||
"prettier": "^1.13.7", | ||
"sinon": "^6.1.3", | ||
"ts-node": "^4.1.0", | ||
"tslint": "^5.10.0", | ||
"tslint-config-standard": "^7.1.0", | ||
"typedoc": "^0.11.1", | ||
"typedoc-plugin-markdown": "git+https://git@github.com/keenondrums/typedoc-plugin-markdown.git", | ||
"typescript": "^3.0.0-rc" | ||
"prettier": "^1.16.1", | ||
"ts-jest": "^23.10.5", | ||
"ts-node": "^8.0.2", | ||
"tslint": "^5.12.1", | ||
"tslint-config-prettier": "^1.17.0", | ||
"tslint-config-standard": "^8.0.1", | ||
"typescript": "^3.2.4" | ||
}, | ||
"peerDependencies": { | ||
"axios": "^0.18.0" | ||
}, | ||
"pre-commit": [ | ||
"docs", | ||
"markdown-format" | ||
] | ||
} | ||
} |
157
README.md
# axios-rest-resource [](https://travis-ci.org/keenondrums/axios-rest-resource) | ||
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. | ||
Schema-based HTTP client powered by axios. Built with Typescript. Heavily inspired by AngularJS' `$resource`. | ||
@@ -12,4 +12,3 @@ <!-- START doctoc generated TOC please keep comment here to allow auto update --> | ||
- [Custom resource schema](#custom-resource-schema) | ||
- [Adavanced usage](#adavanced-usage) | ||
- [API](#api) | ||
- [In depth](#in-depth) | ||
@@ -30,7 +29,7 @@ <!-- END doctoc generated TOC please keep comment here to allow auto update --> | ||
// utils/resource.ts | ||
import { ResourceBuilder } from "axios-rest-resource"; | ||
import { ResourceBuilder } from 'axios-rest-resource' | ||
export const resourceBuilder = new ResourceBuilder({ | ||
baseURL: "http://localhost:3000" | ||
}); | ||
baseURL: 'http://localhost:3000', | ||
}) | ||
``` | ||
@@ -42,5 +41,5 @@ | ||
// api/entity1.js | ||
import { resourceBuilder } from "utils/resource"; | ||
import { resourceBuilder } from 'utils/resource' | ||
export const entity1Resource = resourceBuilder.build({ url: "/entity1" }); | ||
export const entity1Resource = resourceBuilder.build({ url: '/entity1' }) | ||
// exports an object | ||
@@ -59,9 +58,9 @@ // { | ||
```ts | ||
import { entity1Resource } from "api/entity1"; | ||
import { entity1Resource } from 'api/entity1' | ||
const resRead = entity1Resource.read(); | ||
const resRead = entity1Resource.read() | ||
// sends GET http://localhost:3000/entity1 | ||
// resRead is a Promise of data received from the server | ||
const resReadOne = entity1Resource.readOne({ params: { id } }); | ||
const resReadOne = entity1Resource.readOne({ params: { id } }) | ||
// for id = '123' | ||
@@ -71,3 +70,3 @@ // sends GET http://localhost:3000/entity1/123 | ||
const resCreate = entity1Resource.create({ data }); | ||
const resCreate = entity1Resource.create({ data }) | ||
// for data = { field1: 'test' } | ||
@@ -77,3 +76,3 @@ // sends POST http://localhost:3000/entity1 with body { field1: 'test' } | ||
const resUpdate = entity1Resource.update({ data, params: { id } }); | ||
const resUpdate = entity1Resource.update({ data, params: { id } }) | ||
// for data = { field1: 'test' } and id = '123' | ||
@@ -83,3 +82,3 @@ // sends PUT http://localhost:3000/entity1/123 with body { field1: 'test' } | ||
const resRemove = entity1Resource.remove({ params: { id } }); | ||
const resRemove = entity1Resource.remove({ params: { id } }) | ||
// for id = '123' | ||
@@ -92,3 +91,3 @@ // sends DELETE http://localhost:3000/entity1/123 | ||
axios-rest-resource applies [interceptorUrlFormatter](docs/api/README.md#interceptorurlformatter) interceptor by default. It handles {token} substituin in URLs. | ||
axios-rest-resource applies [interceptorUrlFormatter](src/url-formatter.ts) interceptor by default. It handles {token} substitution in URLs. | ||
@@ -101,7 +100,7 @@ ## Custom resource schema | ||
// utils/resource.ts | ||
import { ResourceBuilder } from "axios-rest-resource"; | ||
import { ResourceBuilder } from 'axios-rest-resource' | ||
export const resourceBuilder = new ResourceBuilder({ | ||
baseURL: "http://localhost:3000" | ||
}); | ||
baseURL: 'http://localhost:3000', | ||
}) | ||
``` | ||
@@ -113,20 +112,15 @@ | ||
// api/entity2.js | ||
import { | ||
IResourceSchemaKeysDefault, | ||
resourceSchemaDefault | ||
} from "axios-rest-resource"; | ||
import { resourceBuilder } from "utils/resource"; | ||
import { resourceSchemaDefault } from 'axios-rest-resource' | ||
import { resourceBuilder } from 'utils/resource' | ||
export const entity2Resource = resourceBuilder.build< | ||
IResourceSchemaKeysDefault | "doSomething" | ||
>({ | ||
export const entity2Resource = resourceBuilder.build({ | ||
schema: { | ||
...resourceSchemaDefault, | ||
doSomething: { | ||
method: "post", | ||
url: "/do-something" | ||
} | ||
method: 'post', | ||
url: '/do-something', | ||
}, | ||
}, | ||
url: "/entity2" | ||
}); | ||
url: '/entity2', | ||
}) | ||
// exports an object | ||
@@ -146,9 +140,9 @@ // { | ||
```ts | ||
import { entity2Resource } from "api/entity2"; | ||
import { entity2Resource } from 'api/entity2' | ||
const resRead = entity2Resource.read(); | ||
const resRead = entity2Resource.read() | ||
// sends GET http://localhost:3000/entity2 | ||
// resRead is a Promise of data received from the server | ||
const resReadOne = entity2Resource.readOne({ params: { id } }); | ||
const resReadOne = entity2Resource.readOne({ params: { id } }) | ||
// for id = '123' | ||
@@ -158,3 +152,3 @@ // sends GET http://localhost:3000/entity2/123 | ||
const resCreate = entity2Resource.create({ data }); | ||
const resCreate = entity2Resource.create({ data }) | ||
// for data = { field1: 'test' } | ||
@@ -164,3 +158,3 @@ // sends POST http://localhost:3000/entity2 with body { field1: 'test' } | ||
const resUpdate = entity2Resource.update({ data, params: { id } }); | ||
const resUpdate = entity2Resource.update({ data, params: { id } }) | ||
// for data = { field1: 'test' } and id = '123' | ||
@@ -170,3 +164,3 @@ // sends PUT http://localhost:3000/entity2/123 with body { field1: 'test' } | ||
const resRemove = entity2Resource.remove({ params: { id } }); | ||
const resRemove = entity2Resource.remove({ params: { id } }) | ||
// for id = '123' | ||
@@ -176,3 +170,3 @@ // sends DELETE http://localhost:3000/entity2/123 | ||
const resDoSomething = entity2Resource.doSomething(); | ||
const resDoSomething = entity2Resource.doSomething() | ||
// sends POST http://localhost:3000/entity2/do-something | ||
@@ -186,13 +180,13 @@ // resDoSomething is a Promise of data received from the server | ||
// api/entity.js | ||
import { resourceBuilder } from "utils/resource"; | ||
import { resourceBuilder } from 'utils/resource' | ||
export const entityResource = resourceBuilder.build<"doSomething">({ | ||
export const entityResource = resourceBuilder.build({ | ||
schema: { | ||
doSomething: { | ||
method: "post", | ||
url: "/do-something" | ||
} | ||
method: 'post', | ||
url: '/do-something', | ||
}, | ||
}, | ||
url: "/entity" | ||
}); | ||
url: '/entity', | ||
}) | ||
// exports an object | ||
@@ -208,14 +202,14 @@ // { | ||
// api/entity.js | ||
import { resourceSchemaDefault } from "axios-rest-resource"; | ||
import { resourceBuilder } from "utils/resource"; | ||
import { resourceSchemaDefault } from 'axios-rest-resource' | ||
import { resourceBuilder } from 'utils/resource' | ||
const { read, readOne } = resourceSchemaDefault; | ||
const { read, readOne } = resourceSchemaDefault | ||
export const entityResource = resourceBuilder.build<"read" | "readOne">({ | ||
export const entityResource = resourceBuilder.build({ | ||
schema: { | ||
read, | ||
readOne | ||
readOne, | ||
}, | ||
url: "/entity" | ||
}); | ||
url: '/entity', | ||
}) | ||
// exports an object | ||
@@ -228,54 +222,25 @@ // { | ||
## Adavanced usage | ||
## In depth | ||
You can pass a custom axios instance factory to ResourceBuilder. It's useful if you want to do something more with your axios instance like add an interceptor. | ||
What does `ResourceBuilder` do exactly upon creation? | ||
```ts | ||
import { ResourceBuilder } from "axios-rest-resource"; | ||
import axios, { AxiosInstance } from "axios"; | ||
When you call `new ResourceBuilder(axiosConfig)` | ||
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; | ||
}; | ||
1. If your `axiosConfig` doesn't have `headers.Accept` property it sets it to 'application/json'. | ||
1. It creates a new instance of axios passing `axiosConfig` to `axios.create`. | ||
1. It adds `interceptorUrlFormatter` to request interceptors of the newly created instance of axios. | ||
1. It exposes the newly created instance of axios for further modifications at `axiosInstance`. | ||
export const resourceBuilder = new ResourceBuilder(createAxiosInstanceFromUrl); | ||
``` | ||
Each instance of ResourceBuilder has its own `axiosInstance`. It's useful if you want to do something more with your axios instance like adding an interceptor. | ||
As you can see there's a lot you have to remember. Not to keep all those things in mind you can utilize [createAxiosResourceFactory](docs/api/README.md#createaxiosresourcefactory). | ||
```ts | ||
import { | ||
ResourceBuilder, | ||
createAxiosResourceFactory | ||
} from "axios-rest-resource"; | ||
import { AxiosInstance } from "axios"; | ||
import { ResourceBuilder } from 'axios-rest-resource' | ||
import axios, { 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; | ||
}; | ||
const resourceBuilder = new ResourceBuilder({ | ||
baseURL: 'http://localhost:3000', | ||
}) | ||
resourceBuilder.axiosInstance.interceptors.response.use(myCustomResponeInterceptor) | ||
export const resourceBuilder = new ResourceBuilder(createAxiosInstanceFromUrl); | ||
export resourceBuilder | ||
``` | ||
## API | ||
[API reference](docs/api/README.md) |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
15
14
15392
125
229
1