├── .eslintignore
├── .eslintrc
├── .github
├── dependabot.yml
└── workflows
│ └── build.yaml
├── .gitignore
├── CHANGELOG.md
├── LICENSE
├── README.md
├── dist
├── es
│ ├── EndpointFactory.d.ts
│ ├── EndpointFactory.test.d.ts
│ ├── index.d.ts
│ ├── index.js
│ └── types.d.ts
├── lib
│ ├── EndpointFactory.d.ts
│ ├── EndpointFactory.test.d.ts
│ ├── index.d.ts
│ ├── index.js
│ └── types.d.ts
└── umd
│ ├── EndpointFactory.d.ts
│ ├── EndpointFactory.test.d.ts
│ ├── index.d.ts
│ ├── index.js
│ └── types.d.ts
├── index.js
├── jest.config.js
├── package-lock.json
├── package.json
├── rollup.config.js
├── src
├── EndpointFactory.test.ts
├── EndpointFactory.ts
├── index.ts
└── types.ts
└── tsconfig.json
/.eslintignore:
--------------------------------------------------------------------------------
1 | node_modules/*
2 | dist/*
3 | rollup.config.js
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "parser": "@typescript-eslint/parser",
3 | "extends": ["plugin:@typescript-eslint/recommended"],
4 | "plugins": ["@typescript-eslint"],
5 | "rules": {
6 | "@typescript-eslint/indent": ["warn", 2],
7 | "@typescript-eslint/no-empty-interface": "off",
8 | "@typescript-eslint/no-explicit-any": "off"
9 | },
10 | "parserOptions": {
11 | "project": "./tsconfig.json"
12 | }
13 | }
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | - package-ecosystem: npm
4 | directory: "/"
5 | schedule:
6 | interval: daily
7 | open-pull-requests-limit: 50
8 | ignore:
9 | - dependency-name: rollup
10 | versions:
11 | - 2.38.1
12 | - 2.38.3
13 | - 2.38.4
14 | - 2.38.5
15 | - 2.39.0
16 | - 2.39.1
17 | - 2.41.1
18 | - 2.41.3
19 | - 2.42.0
20 | - 2.42.4
21 | - 2.45.0
22 | - 2.45.1
23 | - dependency-name: "@types/jest"
24 | versions:
25 | - 26.0.22
26 | - dependency-name: typescript
27 | versions:
28 | - 3.9.8
29 | - 4.2.3
30 | - dependency-name: husky
31 | versions:
32 | - 4.3.8
33 | - 5.0.9
34 | - 5.1.0
35 | - 5.1.1
36 | - 5.1.2
37 | - dependency-name: lint-staged
38 | versions:
39 | - 10.5.3
40 |
--------------------------------------------------------------------------------
/.github/workflows/build.yaml:
--------------------------------------------------------------------------------
1 |
2 | name: Build
3 |
4 | on:
5 | push:
6 | branches: [ main ]
7 | pull_request:
8 | branches: [ main ]
9 |
10 | jobs:
11 | build:
12 |
13 | runs-on: ubuntu-latest
14 |
15 | strategy:
16 | matrix:
17 | node-version: [16.x, 18.x]
18 |
19 | steps:
20 | - uses: actions/checkout@v3
21 | - name: On version ${{ matrix.node-version }}
22 | uses: actions/setup-node@v3
23 | with:
24 | node-version: ${{ matrix.node-version }}
25 | cache: 'npm'
26 | - run: npm ci
27 | - run: npm run build
28 | - run: npm run lint
29 | - run: npm test
30 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | .idea
3 | .cache
4 | .rpt2_cache
5 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | ## 1.0.3
4 |
5 | - Update deps to remove vulnerabilities
6 |
7 |
8 | ## 1.0.2
9 |
10 | - Update deps to remove vulnerabilities
11 |
12 |
13 | ## 1.0.1
14 |
15 | - Update deps
16 |
17 | ## 1.0.0
18 |
19 | - Updated deps
20 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Renan
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Axios endpoints
2 |
3 | [](https://travis-ci.org/renancaraujo/axios-endpoints)
4 | [](https://www.npmjs.com/package/axios-endpoints)
5 |
6 | Axios endpoints helps you to create a more concise endpoint mapping with a simple but flexible api. It is as wrapper over [axios](https://github.com/axios/axios).
7 |
8 | ### Getting started
9 |
10 | Before anything, install axios-endpoints
11 |
12 | ```bash
13 | npm install --save axios #axios is a peer dependency
14 | npm install --save axios-endpoints
15 | ```
16 |
17 | ### Usage with Factory (recommended)
18 |
19 | For a more complete usage of axios settings, you may use the Factory.
20 |
21 | ```javascript
22 | import axios from "axios";
23 | import EndpointFactory from "axios-endpoints";
24 |
25 | const axiosInstance = axios.create({
26 | baseURL: "https://localhost:8080/api"
27 | });
28 |
29 | const Endpoint = EndpointFactory(axiosInstance);
30 |
31 | const cityEndpoint = new Endpoint("/city"); // GET https://localhost:8080/api/city
32 | const postEndpoint = new Endpoint(({id = ""}) => "/post/" + id);
33 |
34 | // Header changing example
35 | function setAuthorization(MYTOKEN){
36 | axiosInstance.defaults.headers.common["Authorization"] = MYTOKEN;
37 | }
38 |
39 |
40 |
41 | function getCityList(callback) {
42 | cityEndpoint.get().then(response=>{
43 | callback(response.data);
44 | }).catch(e=>{
45 | console.log("That didnt go well");
46 | });
47 | }
48 |
49 | // do you like async stuff? so take this async example
50 | async function getCityList(){
51 | try{
52 | const { data } = await cityEndpoint.get();
53 | return data;
54 | } catch (e) {
55 | console.log("That didnt go well");
56 | }
57 | }
58 |
59 |
60 | ```
61 |
62 |
63 | ### Usage without factory
64 |
65 | The fastest way to use axios-endpoints. ideal when you dont want to set any axios configs:
66 |
67 | ```javascript
68 | // endpoints.js
69 | import { Endpoint } from "axios-endpoints";
70 |
71 | export const userEndpoint = new Endpoint("https://localhost:8080/api/user");
72 |
73 |
74 | // anotherfile.js
75 | import { userEndpoint } from "./endpoints";
76 |
77 | async function getUserList(){
78 | try{
79 | const { data } = await userEndpoint.get();
80 | return data;
81 | } catch (e) {
82 | console.log("That didnt go well");
83 | }
84 | }
85 |
86 |
87 | ```
88 |
89 | ### HTTP methods
90 |
91 | You can user either `.get` `.post` `.put` and `.delete` as well:
92 |
93 | ```javascript
94 |
95 | const cityEndpoint = new Endpoint("/city");
96 |
97 | const { data } = await cityEndpoint.get(); // GET https://localhost:8080/api/city
98 | const { data } = await cityEndpoint.get({
99 | params: {country:"brazil"}
100 | }); // GET https://localhost:8080/api/city?country=brazil
101 |
102 |
103 | const { data } = await cityEndpoint.post({
104 | name: "Hortolandia",
105 | country: "Brazil",
106 | hazardLevel: 10000
107 | }, {
108 | params: { someParam: "icecream" }
109 | });
110 | /*
111 | curl --request POST \
112 | --url https://localhost:8080/api/city?someParam=icecream \
113 | --header 'Content-Type: application/json' \
114 | --data '{
115 | "name": "Hortolandia",
116 | "country": "Brazil",
117 | "hazardLevel": 10000
118 | }'
119 | */
120 | ```
121 |
122 |
123 | #### uriParams
124 |
125 | Not always your endpoint will be represented by a fixed string. For that, uri params exists.
126 |
127 | ```javascript
128 | const postEndpoint = new Endpoint(({postId = ""}) => "/post/" + postId)
129 |
130 | const { data } = await postEndpoint.get({
131 | uriParams: {
132 | postId: 1
133 | }
134 | }); // GET https://localhost:8080/api/post/1
135 | ```
136 |
137 | For more information about parameters and returned values, check the API section.
138 |
139 |
140 |
141 | ## API
142 |
143 | #### `EndpointFactory`
144 | ```javascript
145 | import axios from "axios";
146 | import EndpointFactory from "axios-endpoints"
147 |
148 | const axiosInstance = axios.create(config);
149 | const Enpoint = EndpointFactory(axiosInstance);
150 | ```
151 |
152 | Type: function
153 |
154 | | Parameters | |
155 | |---------------|----------------|
156 | | axiosInstance | Axios instance |
157 |
158 | `axiosInstance` is generated via `axios.create` function. For more information, check [axios documentation](https://github.com/axios/axios#axioscreateconfig).
159 |
160 | Return: `Endpoint`
161 |
162 |
163 | #### `Endpoint`
164 | ```javascript
165 | import axios from "axios";
166 | import EndpointFactory from "axios-endpoints"
167 |
168 | const axiosInstance = axios.create(config);
169 | const Enpoint = EndpointFactory(axiosInstance);
170 | ```
171 | Type: class
172 |
173 | ##### Constructor
174 |
175 | | Constructor Parameters | Type |
176 | |---------------|----------------|
177 | | endpointIdentifier | `String` or `Function any => String` |
178 |
179 | ##### Instance methods
180 |
181 | ###### `endpoint#get(options)`
182 | ###### `endpoint#post(payload, options)`
183 | ###### `endpoint#put(payload, options)`
184 | ###### `endpoint#patch(payload, options)`
185 | ###### `endpoint#delete(options)`
186 |
187 | | Parameters | Type |
188 | |---------------|----------------|
189 | | options | The same object as the [Request Config](https://github.com/axios/axios#request-config) with the extra property `uriParams`.
You may use `params` and `uriParams` more often.|
190 | | payload | The object that will be carried as json payload of the request |
191 |
192 |
193 |
194 |
195 | ## Contributing
196 |
197 | If you got so far reading this README, you are maybe thinking about contributing. Pull requests are welcome.
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
--------------------------------------------------------------------------------
/dist/es/EndpointFactory.d.ts:
--------------------------------------------------------------------------------
1 | import { AxiosInstance } from 'axios';
2 | import { EndpointClass } from './types';
3 | declare const EndpointFactory: (axiosInstance: AxiosInstance) => typeof EndpointClass;
4 | export default EndpointFactory;
5 |
--------------------------------------------------------------------------------
/dist/es/EndpointFactory.test.d.ts:
--------------------------------------------------------------------------------
1 | export {};
2 |
--------------------------------------------------------------------------------
/dist/es/index.d.ts:
--------------------------------------------------------------------------------
1 | import EndpointFactory from './EndpointFactory';
2 | export declare const Endpoint: typeof import("./types").EndpointClass;
3 | export default EndpointFactory;
4 |
--------------------------------------------------------------------------------
/dist/es/index.js:
--------------------------------------------------------------------------------
1 | import axios from 'axios';
2 |
3 | /******************************************************************************
4 | Copyright (c) Microsoft Corporation.
5 |
6 | Permission to use, copy, modify, and/or distribute this software for any
7 | purpose with or without fee is hereby granted.
8 |
9 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
10 | REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11 | AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
12 | INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13 | LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
14 | OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 | PERFORMANCE OF THIS SOFTWARE.
16 | ***************************************************************************** */
17 | /* global Reflect, Promise */
18 |
19 | var extendStatics = function(d, b) {
20 | extendStatics = Object.setPrototypeOf ||
21 | ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
22 | function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
23 | return extendStatics(d, b);
24 | };
25 |
26 | function __extends(d, b) {
27 | if (typeof b !== "function" && b !== null)
28 | throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
29 | extendStatics(d, b);
30 | function __() { this.constructor = d; }
31 | d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
32 | }
33 |
34 | var __assign = function() {
35 | __assign = Object.assign || function __assign(t) {
36 | for (var s, i = 1, n = arguments.length; i < n; i++) {
37 | s = arguments[i];
38 | for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
39 | }
40 | return t;
41 | };
42 | return __assign.apply(this, arguments);
43 | };
44 |
45 | function __rest(s, e) {
46 | var t = {};
47 | for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
48 | t[p] = s[p];
49 | if (s != null && typeof Object.getOwnPropertySymbols === "function")
50 | for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
51 | if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
52 | t[p[i]] = s[p[i]];
53 | }
54 | return t;
55 | }
56 |
57 | var EndpointClass = /** @class */ (function () {
58 | function EndpointClass(endpoint, endpointOptions) {
59 | if (endpointOptions === void 0) { endpointOptions = {}; }
60 | if (typeof endpoint === 'string') {
61 | this.uri = endpoint;
62 | }
63 | else {
64 | this.uriFunction = endpoint;
65 | }
66 | this.endpointOptions = endpointOptions;
67 | }
68 | return EndpointClass;
69 | }());
70 |
71 | var EndpointFactory = function (axiosInstance) { return /** @class */ (function (_super) {
72 | __extends(ApiClient, _super);
73 | function ApiClient() {
74 | var _this = _super !== null && _super.apply(this, arguments) || this;
75 | _this.get = function (options) {
76 | if (options === void 0) { options = {}; }
77 | var uriParams = options.uriParams, endpointOptions = __rest(options, ["uriParams"]);
78 | return axiosInstance(__assign(__assign({ url: _this.uri || _this.uriFunction(uriParams), responseType: 'json' }, _this.endpointOptions), endpointOptions));
79 | };
80 | _this.post = function (payload, options) {
81 | if (payload === void 0) { payload = {}; }
82 | if (options === void 0) { options = {}; }
83 | var uriParams = options.uriParams, endpointOptions = __rest(options, ["uriParams"]);
84 | return axiosInstance(__assign({ method: 'post', url: _this.uri || _this.uriFunction(uriParams), data: payload, responseType: 'json' }, endpointOptions));
85 | };
86 | _this.put = function (payload, options) {
87 | if (payload === void 0) { payload = {}; }
88 | if (options === void 0) { options = {}; }
89 | var uriParams = options.uriParams, endpointOptions = __rest(options, ["uriParams"]);
90 | return axiosInstance(__assign({ method: 'put', url: _this.uri || _this.uriFunction(uriParams), data: payload, responseType: 'json' }, endpointOptions));
91 | };
92 | _this.patch = function (payload, options) {
93 | if (payload === void 0) { payload = {}; }
94 | if (options === void 0) { options = {}; }
95 | var uriParams = options.uriParams, endpointOptions = __rest(options, ["uriParams"]);
96 | return axiosInstance(__assign({ method: 'patch', url: _this.uri || _this.uriFunction(uriParams), data: payload, responseType: 'json' }, endpointOptions));
97 | };
98 | _this.delete = function (options) {
99 | if (options === void 0) { options = {}; }
100 | var uriParams = options.uriParams, endpointOptions = __rest(options, ["uriParams"]);
101 | return axiosInstance(__assign({ method: 'delete', url: _this.uri || _this.uriFunction(uriParams), responseType: 'json' }, endpointOptions));
102 | };
103 | return _this;
104 | }
105 | return ApiClient;
106 | }(EndpointClass)); };
107 |
108 | var Endpoint = EndpointFactory(axios);
109 |
110 | export { Endpoint, EndpointFactory as default };
111 |
--------------------------------------------------------------------------------
/dist/es/types.d.ts:
--------------------------------------------------------------------------------
1 | import { AxiosRequestConfig, AxiosPromise } from 'axios';
2 | export declare type UriFunction = (uriParams: UriParams) => string;
3 | export interface UriParamsWrapper {
4 | uriParams?: UriParams;
5 | }
6 | export interface EndpointsOptions extends AxiosRequestConfig, UriParamsWrapper {
7 | }
8 | export declare class EndpointClass {
9 | uri: string;
10 | uriFunction: UriFunction;
11 | endpointOptions: AxiosRequestConfig;
12 | constructor(endpoint: string | UriFunction, endpointOptions?: AxiosRequestConfig);
13 | get: (options?: EndpointsOptions) => AxiosPromise;
14 | post: (payload?: any, options?: EndpointsOptions) => AxiosPromise;
15 | put: (payload?: any, options?: EndpointsOptions) => AxiosPromise;
16 | patch: (payload?: any, options?: EndpointsOptions) => AxiosPromise;
17 | delete: (options?: EndpointsOptions) => AxiosPromise;
18 | }
19 |
--------------------------------------------------------------------------------
/dist/lib/EndpointFactory.d.ts:
--------------------------------------------------------------------------------
1 | import { AxiosInstance } from 'axios';
2 | import { EndpointClass } from './types';
3 | declare const EndpointFactory: (axiosInstance: AxiosInstance) => typeof EndpointClass;
4 | export default EndpointFactory;
5 |
--------------------------------------------------------------------------------
/dist/lib/EndpointFactory.test.d.ts:
--------------------------------------------------------------------------------
1 | export {};
2 |
--------------------------------------------------------------------------------
/dist/lib/index.d.ts:
--------------------------------------------------------------------------------
1 | import EndpointFactory from './EndpointFactory';
2 | export declare const Endpoint: typeof import("./types").EndpointClass;
3 | export default EndpointFactory;
4 |
--------------------------------------------------------------------------------
/dist/lib/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, '__esModule', { value: true });
4 |
5 | var axios = require('axios');
6 |
7 | function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
8 |
9 | var axios__default = /*#__PURE__*/_interopDefaultLegacy(axios);
10 |
11 | /******************************************************************************
12 | Copyright (c) Microsoft Corporation.
13 |
14 | Permission to use, copy, modify, and/or distribute this software for any
15 | purpose with or without fee is hereby granted.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
18 | REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
19 | AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
20 | INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
21 | LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
22 | OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
23 | PERFORMANCE OF THIS SOFTWARE.
24 | ***************************************************************************** */
25 | /* global Reflect, Promise */
26 |
27 | var extendStatics = function(d, b) {
28 | extendStatics = Object.setPrototypeOf ||
29 | ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
30 | function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
31 | return extendStatics(d, b);
32 | };
33 |
34 | function __extends(d, b) {
35 | if (typeof b !== "function" && b !== null)
36 | throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
37 | extendStatics(d, b);
38 | function __() { this.constructor = d; }
39 | d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
40 | }
41 |
42 | var __assign = function() {
43 | __assign = Object.assign || function __assign(t) {
44 | for (var s, i = 1, n = arguments.length; i < n; i++) {
45 | s = arguments[i];
46 | for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
47 | }
48 | return t;
49 | };
50 | return __assign.apply(this, arguments);
51 | };
52 |
53 | function __rest(s, e) {
54 | var t = {};
55 | for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
56 | t[p] = s[p];
57 | if (s != null && typeof Object.getOwnPropertySymbols === "function")
58 | for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
59 | if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
60 | t[p[i]] = s[p[i]];
61 | }
62 | return t;
63 | }
64 |
65 | var EndpointClass = /** @class */ (function () {
66 | function EndpointClass(endpoint, endpointOptions) {
67 | if (endpointOptions === void 0) { endpointOptions = {}; }
68 | if (typeof endpoint === 'string') {
69 | this.uri = endpoint;
70 | }
71 | else {
72 | this.uriFunction = endpoint;
73 | }
74 | this.endpointOptions = endpointOptions;
75 | }
76 | return EndpointClass;
77 | }());
78 |
79 | var EndpointFactory = function (axiosInstance) { return /** @class */ (function (_super) {
80 | __extends(ApiClient, _super);
81 | function ApiClient() {
82 | var _this = _super !== null && _super.apply(this, arguments) || this;
83 | _this.get = function (options) {
84 | if (options === void 0) { options = {}; }
85 | var uriParams = options.uriParams, endpointOptions = __rest(options, ["uriParams"]);
86 | return axiosInstance(__assign(__assign({ url: _this.uri || _this.uriFunction(uriParams), responseType: 'json' }, _this.endpointOptions), endpointOptions));
87 | };
88 | _this.post = function (payload, options) {
89 | if (payload === void 0) { payload = {}; }
90 | if (options === void 0) { options = {}; }
91 | var uriParams = options.uriParams, endpointOptions = __rest(options, ["uriParams"]);
92 | return axiosInstance(__assign({ method: 'post', url: _this.uri || _this.uriFunction(uriParams), data: payload, responseType: 'json' }, endpointOptions));
93 | };
94 | _this.put = function (payload, options) {
95 | if (payload === void 0) { payload = {}; }
96 | if (options === void 0) { options = {}; }
97 | var uriParams = options.uriParams, endpointOptions = __rest(options, ["uriParams"]);
98 | return axiosInstance(__assign({ method: 'put', url: _this.uri || _this.uriFunction(uriParams), data: payload, responseType: 'json' }, endpointOptions));
99 | };
100 | _this.patch = function (payload, options) {
101 | if (payload === void 0) { payload = {}; }
102 | if (options === void 0) { options = {}; }
103 | var uriParams = options.uriParams, endpointOptions = __rest(options, ["uriParams"]);
104 | return axiosInstance(__assign({ method: 'patch', url: _this.uri || _this.uriFunction(uriParams), data: payload, responseType: 'json' }, endpointOptions));
105 | };
106 | _this.delete = function (options) {
107 | if (options === void 0) { options = {}; }
108 | var uriParams = options.uriParams, endpointOptions = __rest(options, ["uriParams"]);
109 | return axiosInstance(__assign({ method: 'delete', url: _this.uri || _this.uriFunction(uriParams), responseType: 'json' }, endpointOptions));
110 | };
111 | return _this;
112 | }
113 | return ApiClient;
114 | }(EndpointClass)); };
115 |
116 | var Endpoint = EndpointFactory(axios__default["default"]);
117 |
118 | exports.Endpoint = Endpoint;
119 | exports["default"] = EndpointFactory;
120 |
--------------------------------------------------------------------------------
/dist/lib/types.d.ts:
--------------------------------------------------------------------------------
1 | import { AxiosRequestConfig, AxiosPromise } from 'axios';
2 | export declare type UriFunction = (uriParams: UriParams) => string;
3 | export interface UriParamsWrapper {
4 | uriParams?: UriParams;
5 | }
6 | export interface EndpointsOptions extends AxiosRequestConfig, UriParamsWrapper {
7 | }
8 | export declare class EndpointClass {
9 | uri: string;
10 | uriFunction: UriFunction;
11 | endpointOptions: AxiosRequestConfig;
12 | constructor(endpoint: string | UriFunction, endpointOptions?: AxiosRequestConfig);
13 | get: (options?: EndpointsOptions) => AxiosPromise;
14 | post: (payload?: any, options?: EndpointsOptions) => AxiosPromise;
15 | put: (payload?: any, options?: EndpointsOptions) => AxiosPromise;
16 | patch: (payload?: any, options?: EndpointsOptions) => AxiosPromise;
17 | delete: (options?: EndpointsOptions) => AxiosPromise;
18 | }
19 |
--------------------------------------------------------------------------------
/dist/umd/EndpointFactory.d.ts:
--------------------------------------------------------------------------------
1 | import { AxiosInstance } from 'axios';
2 | import { EndpointClass } from './types';
3 | declare const EndpointFactory: (axiosInstance: AxiosInstance) => typeof EndpointClass;
4 | export default EndpointFactory;
5 |
--------------------------------------------------------------------------------
/dist/umd/EndpointFactory.test.d.ts:
--------------------------------------------------------------------------------
1 | export {};
2 |
--------------------------------------------------------------------------------
/dist/umd/index.d.ts:
--------------------------------------------------------------------------------
1 | import EndpointFactory from './EndpointFactory';
2 | export declare const Endpoint: typeof import("./types").EndpointClass;
3 | export default EndpointFactory;
4 |
--------------------------------------------------------------------------------
/dist/umd/index.js:
--------------------------------------------------------------------------------
1 | (function (global, factory) {
2 | typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('axios')) :
3 | typeof define === 'function' && define.amd ? define(['exports', 'axios'], factory) :
4 | (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.axiosEndpoints = {}, global.axios));
5 | })(this, (function (exports, axios) { 'use strict';
6 |
7 | function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
8 |
9 | var axios__default = /*#__PURE__*/_interopDefaultLegacy(axios);
10 |
11 | /******************************************************************************
12 | Copyright (c) Microsoft Corporation.
13 |
14 | Permission to use, copy, modify, and/or distribute this software for any
15 | purpose with or without fee is hereby granted.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
18 | REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
19 | AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
20 | INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
21 | LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
22 | OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
23 | PERFORMANCE OF THIS SOFTWARE.
24 | ***************************************************************************** */
25 | /* global Reflect, Promise */
26 |
27 | var extendStatics = function(d, b) {
28 | extendStatics = Object.setPrototypeOf ||
29 | ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
30 | function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
31 | return extendStatics(d, b);
32 | };
33 |
34 | function __extends(d, b) {
35 | if (typeof b !== "function" && b !== null)
36 | throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
37 | extendStatics(d, b);
38 | function __() { this.constructor = d; }
39 | d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
40 | }
41 |
42 | var __assign = function() {
43 | __assign = Object.assign || function __assign(t) {
44 | for (var s, i = 1, n = arguments.length; i < n; i++) {
45 | s = arguments[i];
46 | for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
47 | }
48 | return t;
49 | };
50 | return __assign.apply(this, arguments);
51 | };
52 |
53 | function __rest(s, e) {
54 | var t = {};
55 | for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
56 | t[p] = s[p];
57 | if (s != null && typeof Object.getOwnPropertySymbols === "function")
58 | for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
59 | if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
60 | t[p[i]] = s[p[i]];
61 | }
62 | return t;
63 | }
64 |
65 | var EndpointClass = /** @class */ (function () {
66 | function EndpointClass(endpoint, endpointOptions) {
67 | if (endpointOptions === void 0) { endpointOptions = {}; }
68 | if (typeof endpoint === 'string') {
69 | this.uri = endpoint;
70 | }
71 | else {
72 | this.uriFunction = endpoint;
73 | }
74 | this.endpointOptions = endpointOptions;
75 | }
76 | return EndpointClass;
77 | }());
78 |
79 | var EndpointFactory = function (axiosInstance) { return /** @class */ (function (_super) {
80 | __extends(ApiClient, _super);
81 | function ApiClient() {
82 | var _this = _super !== null && _super.apply(this, arguments) || this;
83 | _this.get = function (options) {
84 | if (options === void 0) { options = {}; }
85 | var uriParams = options.uriParams, endpointOptions = __rest(options, ["uriParams"]);
86 | return axiosInstance(__assign(__assign({ url: _this.uri || _this.uriFunction(uriParams), responseType: 'json' }, _this.endpointOptions), endpointOptions));
87 | };
88 | _this.post = function (payload, options) {
89 | if (payload === void 0) { payload = {}; }
90 | if (options === void 0) { options = {}; }
91 | var uriParams = options.uriParams, endpointOptions = __rest(options, ["uriParams"]);
92 | return axiosInstance(__assign({ method: 'post', url: _this.uri || _this.uriFunction(uriParams), data: payload, responseType: 'json' }, endpointOptions));
93 | };
94 | _this.put = function (payload, options) {
95 | if (payload === void 0) { payload = {}; }
96 | if (options === void 0) { options = {}; }
97 | var uriParams = options.uriParams, endpointOptions = __rest(options, ["uriParams"]);
98 | return axiosInstance(__assign({ method: 'put', url: _this.uri || _this.uriFunction(uriParams), data: payload, responseType: 'json' }, endpointOptions));
99 | };
100 | _this.patch = function (payload, options) {
101 | if (payload === void 0) { payload = {}; }
102 | if (options === void 0) { options = {}; }
103 | var uriParams = options.uriParams, endpointOptions = __rest(options, ["uriParams"]);
104 | return axiosInstance(__assign({ method: 'patch', url: _this.uri || _this.uriFunction(uriParams), data: payload, responseType: 'json' }, endpointOptions));
105 | };
106 | _this.delete = function (options) {
107 | if (options === void 0) { options = {}; }
108 | var uriParams = options.uriParams, endpointOptions = __rest(options, ["uriParams"]);
109 | return axiosInstance(__assign({ method: 'delete', url: _this.uri || _this.uriFunction(uriParams), responseType: 'json' }, endpointOptions));
110 | };
111 | return _this;
112 | }
113 | return ApiClient;
114 | }(EndpointClass)); };
115 |
116 | var Endpoint = EndpointFactory(axios__default["default"]);
117 |
118 | exports.Endpoint = Endpoint;
119 | exports["default"] = EndpointFactory;
120 |
121 | Object.defineProperty(exports, '__esModule', { value: true });
122 |
123 | }));
124 |
--------------------------------------------------------------------------------
/dist/umd/types.d.ts:
--------------------------------------------------------------------------------
1 | import { AxiosRequestConfig, AxiosPromise } from 'axios';
2 | export declare type UriFunction = (uriParams: UriParams) => string;
3 | export interface UriParamsWrapper {
4 | uriParams?: UriParams;
5 | }
6 | export interface EndpointsOptions extends AxiosRequestConfig, UriParamsWrapper {
7 | }
8 | export declare class EndpointClass {
9 | uri: string;
10 | uriFunction: UriFunction;
11 | endpointOptions: AxiosRequestConfig;
12 | constructor(endpoint: string | UriFunction, endpointOptions?: AxiosRequestConfig);
13 | get: (options?: EndpointsOptions) => AxiosPromise;
14 | post: (payload?: any, options?: EndpointsOptions) => AxiosPromise;
15 | put: (payload?: any, options?: EndpointsOptions) => AxiosPromise;
16 | patch: (payload?: any, options?: EndpointsOptions) => AxiosPromise;
17 | delete: (options?: EndpointsOptions) => AxiosPromise;
18 | }
19 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | require('dist/lib/index.js');
2 |
--------------------------------------------------------------------------------
/jest.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | preset: 'ts-jest',
3 | testEnvironment: 'node',
4 | };
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "axios-endpoints",
3 | "version": "1.0.3",
4 | "description": "Axios endpoints helps you to create mor concise endpoint mapping with axios. ",
5 | "main": "dist/lib/index.js",
6 | "module": "dist/es/index.js",
7 | "jsnext:main": "src/es/index.js",
8 | "unpkg": "dist/umd/index.js",
9 | "types": "dist/es/index.d.ts",
10 | "files": [
11 | "dist"
12 | ],
13 | "scripts": {
14 | "build": "rollup -c",
15 | "prepublishOnly": "npm run build",
16 | "test": "jest",
17 | "lint": "eslint --ext=ts --ext=tsx ./src",
18 | "lint:fix": "eslint --fix --ext=ts --ext=tsx ./src",
19 | "precommit": "lint-staged"
20 | },
21 | "author": "Renan C. Araújo",
22 | "license": "MIT",
23 | "homepage": "https://github.com/renancaraujo/axios-endpoints#readme",
24 | "repository": {
25 | "type": "git",
26 | "url": "git+ssh://git@github.com:renancaraujo/axios-endpoints.git"
27 | },
28 | "bugs": {
29 | "url": "https://github.com/renancaraujo/axios-endpoints/issues"
30 | },
31 | "lint-staged": {
32 | "src/**/*.{js,jsx,json}": [
33 | "npm run lint:fix",
34 | "git add"
35 | ]
36 | },
37 | "peerDepencies": {
38 | "axios": "^1.1.2"
39 | },
40 | "devDependencies": {
41 | "@types/jest": "^27.0.1",
42 | "@typescript-eslint/eslint-plugin": "^6.7.2",
43 | "@typescript-eslint/parser": "^5.0.0",
44 | "axios": "^1.1.2",
45 | "axios-mock-adapter": "^1.15.0",
46 | "eslint": "^9.0.0",
47 | "husky": "^8.0.1",
48 | "jest": "^26.6.3",
49 | "lint-staged": "14.0.1",
50 | "npm-run-all": "^4.1.3",
51 | "regenerator-runtime": "^0.14.1",
52 | "rollup": "^3.15.0",
53 | "rollup-plugin-node-resolve": "^5.2.0",
54 | "rollup-plugin-typescript2": "^0.35.0",
55 | "ts-jest": "^26.5.4",
56 | "typescript": "^4.2.4"
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/rollup.config.js:
--------------------------------------------------------------------------------
1 | import resolve from 'rollup-plugin-node-resolve';
2 | import typescript from 'rollup-plugin-typescript2';
3 |
4 | const extensions = ['.ts', '.tsx', '.js', '.jsx', '.json'];
5 |
6 | export default [
7 | {
8 | input: 'src/index.ts',
9 | output: [
10 | {
11 | format: 'es',
12 | dir: 'dist/es',
13 | },
14 | {
15 | format: 'cjs',
16 | dir: 'dist/lib',
17 | exports: 'named',
18 | },
19 | ],
20 | external: ['axios'],
21 | plugins: [
22 | typescript({
23 | typescript: require('typescript'),
24 | }),
25 | resolve(),
26 | ],
27 | },
28 | {
29 | input: 'src/index.ts',
30 | output: [
31 | {
32 | file: 'dist/umd/index.js',
33 | format: 'umd',
34 | indent: ' ',
35 | name: 'axiosEndpoints',
36 | globals: {
37 | axios: 'axios'
38 | },
39 | exports: 'named',
40 | },
41 | ],
42 | external: ['axios'],
43 | plugins: [
44 | typescript({
45 | typescript: require('typescript'),
46 | }),
47 | ],
48 | },
49 | ];
50 |
--------------------------------------------------------------------------------
/src/EndpointFactory.test.ts:
--------------------------------------------------------------------------------
1 | import axios from 'axios';
2 | import MockAdapter from 'axios-mock-adapter';
3 | import EndpointFactory from './EndpointFactory';
4 | import { EndpointClass } from './types';
5 |
6 | let MockedService: typeof EndpointClass;
7 |
8 | describe('mocking axios', function(): void {
9 | beforeAll((): void => {
10 | const axiosInstance = axios.create();
11 | const mock = new MockAdapter(axiosInstance);
12 | mock.onGet('/test').reply(200, 'was a get');
13 | mock.onPost('/test').reply(200, 'was a post');
14 | mock.onPut('/test').reply(200, 'was a put');
15 | mock.onPatch('/test').reply(200, 'was a patch');
16 | mock.onDelete('/test').reply(200, 'was a delete');
17 | mock.onAny('/error').reply(500);
18 |
19 | mock.onAny('/dynamic').reply(200, 'was a dynamic endpoint');
20 | mock.onAny('/dynamicPost').reply(200, 'was a dynamic endpoint post');
21 | mock.onAny('/dynamicPut').reply(200, 'was a dynamic endpoint put');
22 | mock.onAny('/dynamicPatch').reply(200, 'was a dynamic endpoint patch');
23 | mock.onAny('/dynamicDelete').reply(200, 'was a dynamic endpoint delete');
24 |
25 | MockedService = EndpointFactory(axiosInstance);
26 | });
27 |
28 | it('should the request be a get', async (): Promise => {
29 | const testService = new MockedService('/test');
30 | const { data } = await testService.get();
31 | expect(data).toEqual('was a get');
32 | });
33 |
34 | it('should the request be a post', async (): Promise => {
35 | const testService = new MockedService('/test');
36 | const { data } = await testService.post();
37 | expect(data).toEqual('was a post');
38 | });
39 |
40 | it('should the request be a put', async (): Promise => {
41 | const testService = new MockedService('/test');
42 | const { data } = await testService.put();
43 | expect(data).toEqual('was a put');
44 | });
45 |
46 | it('should the request be a patch', async (): Promise => {
47 | const testService = new MockedService('/test');
48 | const { data } = await testService.patch();
49 | expect(data).toEqual('was a patch');
50 | });
51 |
52 | it('should the request be a delete', async (): Promise => {
53 | const testService = new MockedService('/test');
54 | const { data } = await testService.delete();
55 | expect(data).toEqual('was a delete');
56 | });
57 |
58 | it('should the request be a delete', async (): Promise => {
59 | const testService = new MockedService('/error');
60 | try {
61 | await testService.get();
62 | } catch ({ message }) {
63 | expect(message).toEqual('Request failed with status code 500');
64 | }
65 | });
66 |
67 | it('should the request be a dynamic get', async (): Promise => {
68 | const testService = new MockedService<{id: string}>(({ id }): string => `/${id}`);
69 | const { data } = await testService.get({
70 | uriParams: {
71 | id: 'dynamic',
72 | },
73 | });
74 | expect(data).toEqual('was a dynamic endpoint');
75 | });
76 |
77 | it('should the request be a dynamic post', async (): Promise => {
78 | const testService = new MockedService(({ id }): string => `/${id}`);
79 | const { data } = await testService.post(
80 | {},
81 | {
82 | uriParams: {
83 | id: 'dynamicPost',
84 | },
85 | }
86 | );
87 | expect(data).toEqual('was a dynamic endpoint post');
88 | });
89 |
90 | it('should the request be a dynamic put', async (): Promise => {
91 | interface UriParamInterface { id: string };
92 | const testService = new MockedService(({ id }): string => `/${id}`);
93 | const { data } = await testService.put(
94 | {},
95 | {
96 | uriParams: {
97 | id: 'dynamicPut',
98 | },
99 | }
100 | );
101 | expect(data).toEqual('was a dynamic endpoint put');
102 | });
103 |
104 | it('should the request be a dynamic patch', async (): Promise => {
105 | const testService = new MockedService(({ id }): string => `/${id}`);
106 | const { data } = await testService.patch(
107 | {},
108 | {
109 | uriParams: {
110 | id: 'dynamicPatch',
111 | },
112 | }
113 | );
114 | expect(data).toEqual('was a dynamic endpoint patch');
115 | });
116 |
117 | it('should the request be a dynamic delete', async (): Promise => {
118 | const testService = new MockedService(({ id }): string => `/${id}`);
119 | const { data } = await testService.delete({
120 | uriParams: {
121 | id: 'dynamicDelete',
122 | },
123 | });
124 | expect(data).toEqual('was a dynamic endpoint delete');
125 | });
126 | });
127 |
--------------------------------------------------------------------------------
/src/EndpointFactory.ts:
--------------------------------------------------------------------------------
1 | import {
2 | AxiosRequestConfig,
3 | AxiosInstance,
4 | AxiosPromise,
5 | } from 'axios';
6 | import { EndpointClass, UriFunction, EndpointsOptions } from './types';
7 |
8 | const EndpointFactory = (axiosInstance: AxiosInstance): typeof EndpointClass => class ApiClient extends EndpointClass{
9 |
10 | public uri: string;
11 | public uriFunction: UriFunction;
12 | public endpointOptions: AxiosRequestConfig;
13 |
14 | public get = (options: EndpointsOptions = {}): AxiosPromise => {
15 | const { uriParams, ...endpointOptions } = options;
16 | return axiosInstance({
17 | url: this.uri || this.uriFunction(uriParams),
18 | responseType: 'json',
19 | ...this.endpointOptions,
20 | ...endpointOptions,
21 | });
22 | };
23 | public post = (payload: any = {}, options: EndpointsOptions = {}): AxiosPromise => {
24 | const { uriParams, ...endpointOptions } = options;
25 | return axiosInstance({
26 | method: 'post',
27 | url: this.uri || this.uriFunction(uriParams),
28 | data: payload,
29 | responseType: 'json',
30 | ...endpointOptions,
31 | });
32 | };
33 | public put = (payload: any = {}, options: EndpointsOptions = {}): AxiosPromise => {
34 | const { uriParams, ...endpointOptions } = options;
35 | return axiosInstance({
36 | method: 'put',
37 | url: this.uri || this.uriFunction(uriParams),
38 | data: payload,
39 | responseType: 'json',
40 | ...endpointOptions,
41 | });
42 | };
43 | public patch = (payload: any = {}, options: EndpointsOptions = {}): AxiosPromise => {
44 | const { uriParams, ...endpointOptions } = options;
45 | return axiosInstance({
46 | method: 'patch',
47 | url: this.uri || this.uriFunction(uriParams),
48 | data: payload,
49 | responseType: 'json',
50 | ...endpointOptions,
51 | });
52 | };
53 | public delete = (options: EndpointsOptions = {}): AxiosPromise => {
54 | const { uriParams, ...endpointOptions } = options;
55 | return axiosInstance({
56 | method: 'delete',
57 | url: this.uri || this.uriFunction(uriParams),
58 | responseType: 'json',
59 | ...endpointOptions,
60 | });
61 | };
62 | };
63 |
64 |
65 | export default EndpointFactory;
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
1 | import axios from 'axios';
2 | import EndpointFactory from './EndpointFactory';
3 | export const Endpoint = EndpointFactory(axios);
4 | export default EndpointFactory;
5 |
--------------------------------------------------------------------------------
/src/types.ts:
--------------------------------------------------------------------------------
1 | import {
2 | AxiosRequestConfig,
3 | AxiosPromise,
4 | } from 'axios';
5 |
6 | export type UriFunction = (uriParams: UriParams) => string;
7 |
8 | export interface UriParamsWrapper {
9 | uriParams?: UriParams;
10 | }
11 |
12 | export interface EndpointsOptions extends AxiosRequestConfig, UriParamsWrapper {}
13 |
14 |
15 | export class EndpointClass {
16 | public uri: string;
17 | public uriFunction: UriFunction;
18 | public endpointOptions: AxiosRequestConfig;
19 |
20 | public constructor(endpoint: string | UriFunction, endpointOptions: AxiosRequestConfig = {}) {
21 | if (typeof endpoint === 'string') {
22 | this.uri = endpoint;
23 | } else {
24 | this.uriFunction = endpoint;
25 | }
26 | this.endpointOptions = endpointOptions;
27 | }
28 |
29 | public get: (options?: EndpointsOptions) => AxiosPromise;
30 | public post: (payload?: any, options?: EndpointsOptions) => AxiosPromise;
31 | public put: (payload?: any, options?: EndpointsOptions) => AxiosPromise;
32 | public patch: (payload?: any, options?: EndpointsOptions) => AxiosPromise;
33 | public delete: (options?: EndpointsOptions) => AxiosPromise;
34 |
35 | }
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "baseUrl": ".",
4 | "moduleResolution": "node",
5 | "paths": { "*": [ "types/*" ] },
6 | "declaration": true,
7 | "declarationDir": "./dist",
8 | "module": "es6",
9 | "noImplicitAny": true,
10 | "outDir": "./dist",
11 | "target": "es5"
12 | }
13 | }
--------------------------------------------------------------------------------