Injectable axios wrapper for Angular and injection-js π―
yarn add @martin_hotell/axios-http
# install peer dependencies
yarn add axios injection-js tslib
# install Reflect API polyfill
yarn add @abraham/reflection
Note:
You need a polyfill for the Reflect API.
We highly recommend tiny reflection polyfill ( 3kB only ! )
Also for TypeScript you will need to enable
experimentalDecorators
andemitDecoratorMetadata
flags within yourtsconfig.json
import { Injectable, ReflectiveInjector } from 'injection-js'
import {
registerHttpClientProviders,
HttpClient,
} from '@martin_hotell/axios-http'
@Injectable()
class UserService {
constructor(private http: HttpClient) {}
getUsers() {
return this.http.get<User[]>('/api/users')
}
}
const injector = ReflectiveInjector.resolveAndCreate([
registerHttpClientProviders(),
UserService,
])
import { Module } from '@angular/core'
import { HttpClientModule, HttpClient } from '@martin_hotell/axios-http'
@Injectable({
provideIn: 'root',
})
class UserService {
constructor(private http: HttpClient) {}
getUsers() {
return this.http.get<User[]>('/api/users')
}
}
@Module({
providers: [HttpClient, HttpClientModule.forRoot()],
})
class AppModule {}
axios-http is just a injectable wrapper which creates an axios instance, so API is the same as for axios.instance ( except Interceptors )
- HttpClient methods
- HttpClient request config schema
- HttpClient response schema
Go checkout examples !
When you execute http.get('/api/user/123').then(response=>response.data)
, on Success the response object is typeof AxiosPromise<any>
with anonymous type of data
property. It doesn't know what the shape of that object is.
You can tell HttpClient
the type of the response, to make consuming the output easier and more obvious.
First, define an interface with the correct shape:
export interface User {
name: string
email: string
}
Then, specify that interface as the HttpClient.get()
call's generic type parameter in the service:
getUser(id:string) {
// now returns a Promise<User>
return this.http.get<User>(`/api/users/${id}`).then(response => response.data);
}
Now our getUser()
returns typed data property as Promise<User>
, so we can access our data in type-safe way
heroService.getUser('123').then({name,email}=>...)
- when registering providers you can pass optional config to
forRoot(config)
import { Injectable, ReflectiveInjector } from 'injection-js'
import { HttpClientModule, HttpClientModule } from '@martin_hotell/axios-http'
@Injectable()
class UserService {
/*...*/
}
const injector = ReflectiveInjector.resolveAndCreate([
HttpClientModule.forRoot({
baseUrl: 'api/swapi',
withCredentials: true,
}),
UserService,
])
axios-http
implements similar API for registering interceptors like Angular HttpClient, so you can inject any other service to your interceptors. Under the hood it transforms this API to leverage pure axios
βοΈ
To wire-up our interceptor, you need to register provider via HTTP_INTERCEPTORS
token and set mutli:true
:
import { Injectable, ReflectiveInjector } from 'injection-js'
import {
HttpClientModule,
HttpInterceptor,
HTTP_INTERCEPTORS,
HttpRequest,
HttpResponse,
} from '@martin_hotell/axios-http'
@Injectable()
class Logger {
log(...args: any[]) {}
error(...args: any[]) {}
}
@Injectable()
export class MyInterceptor implements HttpInterceptor {
// we can inject other injectables
constructor(private logger: Logger) {}
interceptRequest(request: HttpRequest) {
const modifiedData = request.data.replace(/pizza/gi, 'π')
const modifiedRequest = { ...request, data: modifiedData }
return modifiedRequest
}
interceptRequestError(error: any) {
this.logger.error('whooops!')
return Promise.reject(error)
}
interceptResponse(response: HttpResponse) {
this.logger.log('---> data:', response.data)
this.logger.log('---> filter:', response.params.get('filter'))
return response
}
interceptResponseError(error: any) {
this.logger.error('whooops!')
return Promise.reject(error)
}
}
const injector = ReflectiveInjector.resolveAndCreate([
Logger,
HttpClientModule.forRoot(),
// wire up our interceptor
{ provide: HTTP_INTERCEPTORS, useClass: MyInterceptor, multi: true },
])
Execute yarn release
which will handle following tasks:
- bump package version and git tag
- update/(create if it doesn't exist) CHANGELOG.md
- push to github master branch + push tags
- publish build packages to npm
releases are handled by awesome standard-version
- To get from
1.1.2
to1.1.2-0
:
yarn release --prerelease
- Alpha: To get from
1.1.2
to1.1.2-alpha.0
:
yarn release --prerelease alpha
- Beta: To get from
1.1.2
to1.1.2-beta.0
:
yarn release --prerelease beta
See what commands would be run, without committing to git or updating files
yarn release --dry-run
yarn pack
ORyarn release:preflight
which will create a tarball with everything that would get published to NPM
Test are written and run via Jest πͺ
yarn test
# OR
yarn test:watch
Style guides are enforced by robots, I meant prettier and tslint of course π€ , so they'll let you know if you screwed something, but most of the time, they'll autofix things for you. Magic right ?
#Format and fix lint errors
yarn ts:style:fix
yarn docs
- this is preferred way how to create convetional-changelog valid commits
- if you preffer your custom tool we provide a commit hook linter which will error out, it you provide invalid commit message
- if you are in rush and just wanna skip commit message valiation just prefix your message with
WIP: something done
( if you do this please squash your work when you're done with proper commit message so standard-version can create Changelog and bump version of your library appropriately )
yarn commit
- will invoke commitizen CLI
MIT as always