Skip to content

Commit

Permalink
feat: add initial source
Browse files Browse the repository at this point in the history
  • Loading branch information
KillWolfVlad committed Jun 8, 2022
1 parent 39b1084 commit 117bf3c
Show file tree
Hide file tree
Showing 12 changed files with 559 additions and 114 deletions.
1 change: 1 addition & 0 deletions .markdownlint.yaml
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
MD013: false
MD033: false
156 changes: 149 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
# ᐸRepository nameᐳ
# nest-http-client

[![npm@latest](https://img.shields.io/npm/v/@byndyusoft/typescript-template/latest.svg)](https://www.npmjs.com/package/@byndyusoft/typescript-template)
[![test](https://github.com/Byndyusoft/node-typescript-template/actions/workflows/test.yaml/badge.svg?branch=master)](https://github.com/Byndyusoft/node-typescript-template/actions/workflows/test.yaml)
[![npm@latest](https://img.shields.io/npm/v/@byndyusoft/nest-http-client/latest.svg)](https://www.npmjs.com/package/@byndyusoft/nest-http-client)
[![test](https://github.com/Byndyusoft/nest-http-client/actions/workflows/test.yaml/badge.svg?branch=master)](https://github.com/Byndyusoft/nest-http-client/actions/workflows/test.yaml)
[![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg)](https://github.com/prettier/prettier)
[![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg)](https://github.com/semantic-release/semantic-release)

ᐸRepository descriptionᐳ
axios for NestJS

## Comparison with `@nestjs/axios`

- [Promises instead of Observables](https://github.com/nestjs/axios/issues/271)
- `axios` dependency [is not pinning](https://github.com/nestjs/axios/pull/149#issuecomment-925764515), you must provide it by yourself (e.g. get it from `HttpService`)
- Allowing you use global `axios` with interceptors and different configs for various clients

## Requirements

Expand All @@ -15,25 +21,161 @@
## Install

```bash
npm install ᐸPackage nameᐳ
npm install @byndyusoft/nest-http-client @nestjs/common axios
```

or

```bash
yarn add ᐸPackage nameᐳ
yarn add @byndyusoft/nest-http-client @nestjs/common axios
```

## Usage

<details>
<summary>1. Create module</summary>

```typescript
// Usage example
import {
DynamicModuleHelper,
TRegisterAsyncOptions,
} from "@byndyusoft/nest-dynamic-module";
import {
HttpClientModule,
IHttpClientOptions,
} from "@byndyusoft/nest-http-client";
import { DynamicModule, Module } from "@nestjs/common";
import urlJoin from "proper-url-join";
import qs from "qs";

import { ClientBaseOptionsToken, ClientOptionsToken } from "./tokens";
import { UsersClient } from "./usersClient";

@Module({
imports: [
HttpClientModule.registerAsync({
inject: [ClientOptionsToken],
useFactory: (options: IHttpClientOptions) => options,
}),
],
providers: [UsersClient],
exports: [UsersClient],
})
export class ClientModule {
public static registerAsync(
options?: TRegisterAsyncOptions<IHttpClientOptions>,
): DynamicModule {
return DynamicModuleHelper.registerAsync(
{
module: ClientModule,
global: true,
providers: [
{
provide: ClientOptionsToken,
inject: [ClientBaseOptionsToken],
useFactory: (baseOptions: IHttpClientOptions) =>
ClientModule.clientOptionsFactory(baseOptions),
},
],
exports: [ClientOptionsToken],
},
ClientBaseOptionsToken,
options,
);
}

private static clientOptionsFactory(
baseOptions: IHttpClientOptions,
): IHttpClientOptions {
return {
...baseOptions,
config: {
...baseOptions.config,
baseURL: urlJoin(baseOptions.config?.baseURL as string, "/api/v1"),
paramsSerializer: (params) =>
qs.stringify(params, {
skipNulls: true,
arrayFormat: "repeat",
}),
},
};
}
}
```

</details>

<details>
<summary>2. Create client</summary>

```typescript
import { HttpClient } from "@byndyusoft/nest-http-client";
import { Injectable } from "@nestjs/common";
import _ from "lodash";
import { keys } from "ts-transformer-keys";

import {
CreateUserDto,
ListUsersQueryDto,
ListUsersResponseDto,
ParamsWithUserIdDto,
QueryWithUserVersionDto,
UpdateUserDto,
UserDto,
} from "ᐸDtosᐳ";

@Injectable()
export class UsersClient {
public constructor(private readonly httpClient: HttpClient) {}

public createUser(request: CreateUserDto): Promise<UserDto> {
return this.httpClient.post("/users", request);
}

public deleteUser(
request: ParamsWithUserIdDto & QueryWithUserVersionDto,
): Promise<UserDto> {
return this.httpClient.delete(
`/users/${encodeURIComponent(request.userId)}`,
{
params: _.pick(request, keys<QueryWithUserVersionDto>()),
},
);
}

public getUserById(request: ParamsWithUserIdDto): Promise<UserDto> {
return this.httpClient.get(`/users/${encodeURIComponent(request.userId)}`);
}

public listUsers(
request?: Partial<ListUsersQueryDto>,
): Promise<ListUsersResponseDto> {
return this.httpClient.get("/users", {
params: request,
});
}

public updateUser(
request: ParamsWithUserIdDto & QueryWithUserVersionDto & UpdateUserDto,
): Promise<UserDto> {
return this.httpClient.patch(
`/users/${encodeURIComponent(request.userId)}`,
_.pick(request, keys<UpdateUserDto>()),
{
params: _.pick(request, keys<QueryWithUserVersionDto>()),
},
);
}
}
```

</details>

## Maintainers

- [@Byndyusoft/owners](https://github.com/orgs/Byndyusoft/teams/owners) <<[email protected]>>
- [@Byndyusoft/team](https://github.com/orgs/Byndyusoft/teams/team)
- [@KillWolfVlad](https://github.com/KillWolfVlad)

## License

Expand Down
37 changes: 25 additions & 12 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
{
"name": "@byndyusoft/typescript-template",
"name": "@byndyusoft/nest-http-client",
"version": "0.0.0-development",
"description": "Base template for TypeScript packages",
"homepage": "https://github.com/Byndyusoft/node-typescript-template#readme",
"description": "axios for NestJS",
"homepage": "https://github.com/Byndyusoft/nest-http-client#readme",
"bugs": {
"url": "https://github.com/Byndyusoft/node-typescript-template/issues"
"url": "https://github.com/Byndyusoft/nest-http-client/issues"
},
"repository": {
"type": "git",
"url": "https://github.com/Byndyusoft/node-typescript-template.git"
"url": "https://github.com/Byndyusoft/nest-http-client.git"
},
"license": "Apache-2.0",
"author": "Byndyusoft",
Expand All @@ -24,6 +24,7 @@
"!**/*spec.ts"
],
"scripts": {
"_test:cov": "jest --coverage",
"prebuild": "shx rm -rf ./dist",
"build": "tsc --project ./tsconfig.build.json",
"postinstall": "husky install && ts-patch install",
Expand All @@ -37,8 +38,7 @@
"lint:prettier:fix": "prettier --ignore-path ./.gitignore --write \"./**/*.{ts,js,json,yaml,yml,md}\"",
"prepublishOnly": "pinst --disable",
"postpublish": "pinst --enable",
"test": "jest",
"test:cov": "jest --coverage"
"test": "jest"
},
"jest": {
"collectCoverageFrom": [
Expand Down Expand Up @@ -75,16 +75,20 @@
}
},
"dependencies": {
"@byndyusoft/nest-dynamic-module": "^1.0.0",
"deepmerge": "^4.2.2",
"tslib": "^2.4.0"
},
"devDependencies": {
"@byndyusoft/eslint-config": "^2.0.0",
"@byndyusoft/tsconfig": "^1.1.0",
"@commitlint/cli": "^17.0.2",
"@commitlint/config-conventional": "^17.0.2",
"@types/jest": "^28.1.0",
"@types/node": "^17.0.38",
"eslint": "^8.16.0",
"@nestjs/common": "^8.4.6",
"@types/jest": "^28.1.1",
"@types/node": "^17.0.40",
"axios": "^0.27.2",
"eslint": "^8.17.0",
"husky": "^8.0.1",
"jest": "^28.1.0",
"jest-extended": "^2.0.0",
Expand All @@ -95,11 +99,20 @@
"prettier-plugin-packagejson": "^2.2.18",
"semantic-release": "^19.0.2",
"shx": "^0.3.4",
"ts-jest": "^28.0.3",
"ts-jest": "^28.0.4",
"ts-patch": "^2.0.1",
"typescript": "^4.7.2",
"typescript": "^4.7.3",
"typescript-transform-paths": "^3.3.1"
},
"peerDependencies": {
"@nestjs/common": "^8.4.6",
"axios": "^0.27.2"
},
"peerDependenciesMeta": {
"axios": {
"optional": true
}
},
"engines": {
"node": ">=14"
},
Expand Down
31 changes: 0 additions & 31 deletions src/__tests__/helloWorldService.spec.ts

This file was deleted.

90 changes: 90 additions & 0 deletions src/httpClient.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/*
* Copyright 2022 Byndyusoft
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/* eslint-disable @typescript-eslint/explicit-module-boundary-types,@typescript-eslint/no-explicit-any */

import { Injectable } from "@nestjs/common";
import { AxiosRequestConfig } from "axios";

import { HttpCoreClient } from "./httpCoreClient";

@Injectable()
export class HttpClient {
public constructor(private readonly httpCoreClient: HttpCoreClient) {}

public async delete<T = any>(
url: string,
config?: AxiosRequestConfig,
): Promise<T> {
const response = await this.httpCoreClient.delete<T>(url, config);

return response.data;
}

public async get<T = any>(
url: string,
config?: AxiosRequestConfig,
): Promise<T> {
const response = await this.httpCoreClient.get<T>(url, config);

return response.data;
}

public async head<T = any>(
url: string,
config?: AxiosRequestConfig,
): Promise<T> {
const response = await this.httpCoreClient.head<T>(url, config);

return response.data;
}

public async patch<T = any>(
url: string,
data?: any,
config?: AxiosRequestConfig,
): Promise<T> {
const response = await this.httpCoreClient.patch<T>(url, data, config);

return response.data;
}

public async post<T = any>(
url: string,
data?: any,
config?: AxiosRequestConfig,
): Promise<T> {
const response = await this.httpCoreClient.post<T>(url, data, config);

return response.data;
}

public async put<T = any>(
url: string,
data?: any,
config?: AxiosRequestConfig,
): Promise<T> {
const response = await this.httpCoreClient.put<T>(url, data, config);

return response.data;
}

public async request<T = any>(config: AxiosRequestConfig): Promise<T> {
const response = await this.httpCoreClient.request<T>(config);

return response.data;
}
}
Loading

0 comments on commit 117bf3c

Please sign in to comment.