├── .editorconfig
├── .eslintrc.js
├── .github
└── workflows
│ ├── continous.yml
│ └── release.yml
├── .gitignore
├── .prettierignore
├── .prettierrc
├── .releaserc
├── CHANGELOG.md
├── LICENSE
├── README.md
├── jest.config.js
├── package-lock.json
├── package.json
├── rollup.config.js
├── src
├── axios.test.ts
├── axios.ts
├── composable.test.ts
├── composable.ts
├── index.ts
├── plugin.test.ts
├── plugin.ts
├── utils.test.ts
└── utils.ts
└── tsconfig.json
/.editorconfig:
--------------------------------------------------------------------------------
1 | # http://editorconfig.org
2 |
3 | root = true
4 |
5 | [*]
6 | charset = utf-8
7 | indent_style = space
8 | indent_size = 2
9 | end_of_line = lf
10 | insert_final_newline = true
11 | trim_trailing_whitespace = true
12 |
13 | [*.md]
14 | insert_final_newline = false
15 | trim_trailing_whitespace = false
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | env: {
4 | node: true,
5 | },
6 | plugins: ['vue'],
7 | extends: [
8 | 'plugin:vue/vue3-essential',
9 | 'eslint:recommended',
10 | '@vue/typescript/recommended',
11 | '@vue/prettier',
12 | '@vue/prettier/@typescript-eslint',
13 | ],
14 | parserOptions: {
15 | ecmaVersion: 2020,
16 | },
17 | overrides: [
18 | {
19 | files: ['**/src/**/*.test.{j,t}s?(x)'],
20 | env: {
21 | jest: true,
22 | },
23 | rules: {
24 | '@typescript-eslint/no-explicit-any': 'off',
25 | },
26 | },
27 | ],
28 | }
29 |
--------------------------------------------------------------------------------
/.github/workflows/continous.yml:
--------------------------------------------------------------------------------
1 | name: Continous
2 |
3 | on: [push]
4 |
5 | jobs:
6 | BuildAndTest:
7 | runs-on: ubuntu-latest
8 | steps:
9 | - name: Checkout Repository
10 | uses: actions/checkout@v1
11 |
12 | - name: Clean install dependencies
13 | run: npm ci
14 |
15 | - name: Format
16 | run: npm run prettier:check
17 |
18 | - name: Lint
19 | run: npm run lint
20 |
21 | - name: Build
22 | run: npm run build
23 |
24 | - name: Test
25 | run: npm run test
26 |
--------------------------------------------------------------------------------
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | name: Release
2 |
3 | on:
4 | push:
5 | branches:
6 | - master
7 |
8 | jobs:
9 | Publish:
10 | runs-on: ubuntu-latest
11 | steps:
12 | - name: Checkout Repository
13 | uses: actions/checkout@v2
14 | with:
15 | fetch-depth: '0'
16 |
17 | - name: Git Identity
18 | run: |
19 | git config --global user.name 'baopso'
20 | git config --global user.email 'Group.CH_Open-Source@baloise.ch'
21 | git remote set-url origin https://$GITHUB_ACTOR:$GITHUB_TOKEN@github.com/$GITHUB_REPOSITORY
22 | env:
23 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
24 |
25 | # - name: Fetch all Tags and Pull
26 | # run: |
27 | # git fetch --depth=1 origin +refs/tags/*:refs/tags/*
28 | # git pull
29 |
30 | - name: Authenticate with Registry
31 | run: |
32 | echo "registry=http://registry.npmjs.org/" > .npmrc
33 | echo //registry.npmjs.org/:_authToken=$NPM_TOKEN >> .npmrc
34 | env:
35 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
36 |
37 | - name: Clean install dependencies
38 | run: npm ci
39 |
40 | - name: Build
41 | run: npm run build
42 |
43 | # - uses: EndBug/add-and-commit@v5
44 | # with:
45 | # message: 'chore(): update build artifacts'
46 | # env:
47 | # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
48 |
49 | - name: Publish to NPM
50 | run: 'npm run release'
51 | env:
52 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
53 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
54 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
55 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | lerna-debug.log*
8 |
9 | # Diagnostic reports (https://nodejs.org/api/report.html)
10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
11 |
12 | # Runtime data
13 | pids
14 | *.pid
15 | *.seed
16 | *.pid.lock
17 |
18 | # Directory for instrumented libs generated by jscoverage/JSCover
19 | lib-cov
20 |
21 | # Coverage directory used by tools like istanbul
22 | coverage
23 | *.lcov
24 |
25 | # nyc test coverage
26 | .nyc_output
27 |
28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
29 | .grunt
30 |
31 | # Bower dependency directory (https://bower.io/)
32 | bower_components
33 |
34 | # node-waf configuration
35 | .lock-wscript
36 |
37 | # Compiled binary addons (https://nodejs.org/api/addons.html)
38 | build/Release
39 |
40 | # Dependency directories
41 | node_modules/
42 | jspm_packages/
43 |
44 | # TypeScript v1 declaration files
45 | typings/
46 |
47 | # TypeScript cache
48 | *.tsbuildinfo
49 |
50 | # Optional npm cache directory
51 | .npm
52 | .npmrc
53 |
54 | # Optional eslint cache
55 | .eslintcache
56 |
57 | # Microbundle cache
58 | .rpt2_cache/
59 | .rts2_cache_cjs/
60 | .rts2_cache_es/
61 | .rts2_cache_umd/
62 |
63 | # Optional REPL history
64 | .node_repl_history
65 |
66 | # Output of 'npm pack'
67 | *.tgz
68 |
69 | # Yarn Integrity file
70 | .yarn-integrity
71 |
72 | # dotenv environment variables file
73 | .env
74 | .env.test
75 |
76 | # parcel-bundler cache (https://parceljs.org/)
77 | .cache
78 |
79 | # Next.js build output
80 | .next
81 |
82 | # Nuxt.js build / generate output
83 | .nuxt
84 | dist
85 | dist-transpiled
86 |
87 |
88 | # Gatsby files
89 | .cache/
90 | # Comment in the public line in if your project uses Gatsby and *not* Next.js
91 | # https://nextjs.org/blog/next-9-1#public-directory-support
92 | # public
93 |
94 | # vuepress build output
95 | .vuepress/dist
96 |
97 | # Serverless directories
98 | .serverless/
99 |
100 | # FuseBox cache
101 | .fusebox/
102 |
103 | # DynamoDB Local files
104 | .dynamodb/
105 |
106 | # TernJS port file
107 | .tern-port
108 | .idea
109 | /ui-library.iml
110 | /temp
111 |
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | dist/
3 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": true,
3 | "semi": false,
4 | "jsxBracketSameLine": true,
5 | "trailingComma": "all",
6 | "arrowParens": "avoid",
7 | "bracketSpacing": true,
8 | "jsxSingleQuote": false,
9 | "quoteProps": "consistent",
10 | "printWidth": 120,
11 | "tabWidth": 2,
12 | "useTabs": false
13 | }
14 |
--------------------------------------------------------------------------------
/.releaserc:
--------------------------------------------------------------------------------
1 | {
2 | "plugins": [
3 | "@semantic-release/commit-analyzer",
4 | "@semantic-release/release-notes-generator",
5 | ["@semantic-release/npm", { "npmPublish": true }],
6 | "@semantic-release/changelog",
7 | [
8 | "@semantic-release/git",
9 | {
10 | "assets": ["package.json", "package-lock.json", "CHANGELOG.md"],
11 | "message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
12 | }
13 | ],
14 | "@semantic-release/github"
15 | ]
16 | }
17 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | ## [1.3.2](https://github.com/baloise/vue-axios/compare/v1.3.1...v1.3.2) (2022-05-06)
2 |
3 |
4 | ### Bug Fixes
5 |
6 | * add >= to peer deps ([3ca19e2](https://github.com/baloise/vue-axios/commit/3ca19e2a67295df5ea1e7b70a65ca31763c45ab4))
7 |
8 | ## [1.3.1](https://github.com/baloise/vue-axios/compare/v1.3.0...v1.3.1) (2022-02-02)
9 |
10 |
11 | ### Bug Fixes
12 |
13 | * update versions ([2e98258](https://github.com/baloise/vue-axios/commit/2e982586e78c6a3c9966fbe77e71d6b7b9eac5ac))
14 |
15 | # [1.3.0](https://github.com/baloise/vue-axios/compare/v1.2.0...v1.3.0) (2022-01-10)
16 |
17 |
18 | ### Features
19 |
20 | * update deps and rename variables ([79aadff](https://github.com/baloise/vue-axios/commit/79aadffb949b5b92a7842a93b2bf03bfc850124d))
21 |
22 | # [1.2.0](https://github.com/baloise/vue-axios/compare/v1.1.0...v1.2.0) (2021-08-02)
23 |
24 |
25 | ### Features
26 |
27 | * trigger release ([3eb9f7a](https://github.com/baloise/vue-axios/commit/3eb9f7a39e217d570d050b7b160efaeb3f8ac480))
28 |
29 | # [1.1.0](https://github.com/baloise/vue-axios/compare/v1.0.0...v1.1.0) (2021-08-02)
30 |
31 |
32 | ### Features
33 |
34 | * add requestMock to mock responses ([b595d24](https://github.com/baloise/vue-axios/commit/b595d246a481115687076e2fd0edb6327d27fb12))
35 | * update deps ([2bc692d](https://github.com/baloise/vue-axios/commit/2bc692d6b90a6b76655c8d21ad8a0f200bcd3a82))
36 |
37 | # 1.0.0 (2021-03-31)
38 |
39 |
40 | ### Features
41 |
42 | * **useAxios:** add missing request helper functions ([260fbb6](https://github.com/baloise/vue-axios/commit/260fbb6c49ae9e8c37503abf529662adbc4364ed))
43 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright 2021 Baloise Group
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | |
6 |
7 | +
8 | |
9 |
10 |
11 | |
12 |
13 |
14 |
15 | # vue-axios
16 |
17 | A small wrapper library for the simple promise based HTTP client [axios](https://axios-http.com/).
18 |
19 | > The library is made for [Vue 3.x.x](https://v3.vuejs.org/) and the [Composition API](https://v3.vuejs.org/api/composition-api.html).
20 |
21 | ## Instalation
22 |
23 | Install the library and axios with npm.
24 |
25 | ```bash
26 | npm install axios @baloise/vue-axios
27 | ```
28 |
29 | ## Use plugin
30 |
31 | Import the library into your `src/main.ts` file or any other entry point.
32 |
33 | ```typescript
34 | import { createApp } from 'vue'
35 | import { vueAxios } from '@baloise/vue-axios'
36 | ```
37 |
38 | Apply the library to the vue app instance. The additional configuration have the type [AxiosRequestConfig](https://axios-http.com/docs/req_config/).
39 |
40 | ```typescript
41 | const app = createApp(App)
42 |
43 | // simple
44 | app.use(vueAxios)
45 |
46 | // additional configurations
47 | app.use(vueAxios, {
48 | baseURL: 'http://api.my-site.com',
49 | })
50 | ```
51 |
52 | ## Interceptors
53 |
54 | Use the defined `$axios` instance. More to the intercepters can be found [here](https://axios-http.com/docs/interceptors/).
55 |
56 | ```typescript
57 | import { $axios } from '@baloise/vue-axios'
58 |
59 | // Add a request interceptor
60 | $axios.interceptors.request.use(
61 | function (config) {
62 | // Do something before request is sent
63 | return config
64 | },
65 | function (error) {
66 | // Do something with request error
67 | return Promise.reject(error)
68 | },
69 | )
70 |
71 | // Add a response interceptor
72 | $axios.interceptors.response.use(
73 | function (response) {
74 | // Any status code that lie within the range of 2xx cause this function to trigger
75 | // Do something with response data
76 | return response
77 | },
78 | function (error) {
79 | // Any status codes that falls outside the range of 2xx cause this function to trigger
80 | // Do something with response error
81 | return Promise.reject(error)
82 | },
83 | )
84 | ```
85 |
86 | ## Usage
87 |
88 | ### Have multiple API's
89 |
90 | To access multiple apis in your app it could be help full to create a new axios instance. However, if you only access one api configure it through the plugin options `defaults`.
91 |
92 | Export the new instance and use it in any component.
93 |
94 | ```typescript
95 | import { $axios } from '@baloise/vue-axios'
96 |
97 | export const catApi = $axios.create({
98 | baseURL: 'https://cat-fact.herokuapp.com',
99 | })
100 |
101 | export const dogApi = $axios.create({
102 | baseURL: 'https://dog-fact.herokuapp.com',
103 | })
104 | ```
105 |
106 | Use the defined api instance in your components with the same interface that axios has.
107 |
108 | [Axios API Reference](https://axios-http.com/docs/api_intro/)
109 |
110 | ```typescript
111 | catApi.get('/facts')
112 |
113 | dogApi.post('/facts', {
114 | fact: 'wuff',
115 | })
116 | ```
117 |
118 | ## Composition API
119 |
120 | To use axios with the composition API import the `useAxios` composable function. `useAxios` return reactive values like `isLoading` or functions like `request` to execute a HTTP request.
121 |
122 | The reactive values gets updated when executing a HTTP request.
123 |
124 | ```typescript
125 | import { computed, defineComponent } from 'vue'
126 | import { useAxios } from '@baloise/vue-axios'
127 | import { CatApi } from '../api/cat.api'
128 |
129 | type CatFacts = { text: string }[]
130 |
131 | export default defineComponent({
132 | setup() {
133 | const { get, data, isLoading, isSuccessful } = useAxios(CatApi)
134 |
135 | function callApi() {
136 | get('/facts')
137 | }
138 |
139 | return {
140 | callApi,
141 | data,
142 | isLoading,
143 | isSuccessful,
144 | }
145 | },
146 | })
147 | ```
148 |
149 | ### useAxios
150 |
151 | The `useAxios` function accepts a custom axios instance, otherwise it uses the global `$axios` instance.
152 | The `$axios` instance is defined in the plugin options with the default config.
153 |
154 | ```typescript
155 | import { useAxios } from '@baloise/vue-axios'
156 |
157 | useAxios()
158 | useAxios(axiosInstance)
159 | ```
160 |
161 | #### Reactive State
162 |
163 | The `useAxios` function exposes the following reactive state.
164 |
165 | ```typescript
166 | import { useAxios } from '@baloise/vue-axios'
167 |
168 | const {
169 | data,
170 | error,
171 | headers,
172 | status,
173 | statusText,
174 | abortMessage,
175 |
176 | // state
177 | isFinished,
178 | isLoading,
179 | isSuccessful,
180 | hasFailed,
181 | aborted,
182 | } = useAxios()
183 | ```
184 |
185 | | State | Type | Description |
186 | | ------------ | --------- | ----------------------------------------------------------------- |
187 | | data | `any` | `data` is the response that was provided by the server. |
188 | | error | `any` | Promise Error. |
189 | | headers | `any` | `headers` the HTTP headers that the server responded with. |
190 | | status | `number` | `status` is the HTTP status code from the server response. |
191 | | statusText | `string` | `statusText` is the HTTP status message from the server response. |
192 | | abortMessage | `string` | `abortMessage` is the provided message of the abort action. |
193 | | isFinished | `boolean` | If `true` the response of the http call is finished. |
194 | | isLoading | `boolean` | If `true` the response of the http call is still pending. |
195 | | isSuccessful | `boolean` | If `true` the response successfully arrived. |
196 | | hasFailed | `boolean` | If `true` the response has failed. |
197 | | aborted | `boolean` | If `true` the request has been aborted by the user. |
198 |
199 | #### Functions
200 |
201 | The `useAxios` function exposes the following functions.
202 |
203 | ```typescript
204 | import { useAxios } from '@baloise/vue-axios'
205 |
206 | const { request, get, post, put, patch, remove, head, options, abort } = useAxios()
207 | ```
208 |
209 | ##### request
210 |
211 | Similar to the `axios.request` function. Moreover, besides the `AxiosRequestConfig` it also accepts `Promise` paramter too. `Promise` is the return type of the OpenAPI Codegen ParamCreator.
212 |
213 | ```typescript
214 | request(config: AxiosRequestConfig)
215 | request(config: Promise)
216 | ```
217 |
218 | ##### get, post, put, patch, head, options, remove
219 |
220 | Similar to the `axios` functions.
221 |
222 | ```typescript
223 | get(url[, config])
224 | remove(url[, config])
225 | head(url[, config])
226 | options(url[, config])
227 | post(url[, data[, config]])
228 | put(url[, data[, config]])
229 | patch(url[, data[, config]])
230 | ```
231 |
232 | ##### abort
233 |
234 | aborts the HTTP request.
235 |
236 | ```typescript
237 | abort()
238 | abort(message: string)
239 | ```
240 |
241 | ## Open API Codegen
242 |
243 | If your API uses Swagger and follows the OpenApi guidlines it is possible to generate a typescript axios SDK out of it.
244 |
245 | To generate a SDK install the [OpenAPI Generator](https://www.npmjs.com/package/@openapitools/openapi-generator-cli)
246 |
247 | ```bash
248 | npm add -D @openapitools/openapi-generator-cli
249 | ```
250 |
251 | Export the `swagger.json` or `swagger.yaml` from your API and run the following command.
252 |
253 | ```bash
254 | openapi-generator-cli generate -i path-to/swagger.yaml -g typescript-axios -o generated-sources/openapi --additional-properties=supportsES6=true,npmVersion=6.9.0,withInterfaces=true
255 | ```
256 |
257 | Move the generated SDK code into your project. Then define the base configuration of your API and for each endpoint create the param creator.
258 |
259 | Have a look into our awesome [@baloise/vue-keycloak](https://github.com/baloise/vue-keycloak) library.
260 |
261 | ```typescript
262 | import { Configuration, UsersApiAxiosParamCreator } from './generated'
263 | import { getToken } from '@baloise/vue-keycloak'
264 |
265 | const myApiConfiguration = new Configuration({
266 | basePath: '/my/api',
267 | apiKey: async () => {
268 | const token = await getToken()
269 | return `Bearer ${token}`
270 | },
271 | })
272 |
273 | export const UsersApi = UsersApiAxiosParamCreator(myApiConfiguration)
274 | ```
275 |
276 | Import the param creator `UsersApi` into the component and use them with the function `request` to send the HTTP request to the defined API.
277 |
278 | ```typescript
279 | import { defineComponent, ref } from 'vue'
280 | import { UsersApi } from '../api/my.api'
281 | import { useAxios } from '@baloise/vue-axios'
282 |
283 | export default defineComponent({
284 | setup() {
285 | const { request } = useAxios()
286 |
287 | async function onButtonClick() {
288 | await request(UsersApi.getUserUsingGET('7'))
289 | }
290 |
291 | return { onButtonClick }
292 | },
293 | })
294 | ```
295 |
296 | # License
297 |
298 | Apache-2.0 Licensed | Copyright © 2021-present Gery Hirschfeld & Contributors
299 |
--------------------------------------------------------------------------------
/jest.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | roots: ['/src'],
3 | testMatch: ['**/__tests__/**/*.+(ts|tsx|js)', '**/?(*.)+(spec|test).+(ts|tsx|js)'],
4 | transform: {
5 | '^.+\\.(ts|tsx)$': 'ts-jest',
6 | },
7 | }
8 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@baloise/vue-axios",
3 | "version": "1.3.2",
4 | "description": "Wrapper for the axios package to use with the composition api of Vue 3",
5 | "author": {
6 | "name": "Gery Hirschfeld",
7 | "email": "gerhard.hirschfeld@baloise.ch",
8 | "url": "https://github.com/hirsch88"
9 | },
10 | "homepage": "https://github.com/baloise/vue-axios",
11 | "repository": {
12 | "type": "git",
13 | "url": "https://github.com/baloise/vue-axios.git"
14 | },
15 | "scripts": {
16 | "test": "jest",
17 | "test:watch": "jest --watchAll",
18 | "build": "npm run build:clean && npm run build:compile && npm run build:bundle",
19 | "build:clean": "rimraf dist && rimraf dist-transpiled",
20 | "build:compile": "tsc -p .",
21 | "build:bundle": "rollup --config rollup.config.js",
22 | "lint": "eslint src --ext .ts,vue",
23 | "format": "npm run prettier:write",
24 | "prettier:write": "prettier --write \"./src\"",
25 | "prettier:check": "prettier --check \"./src\"",
26 | "release": "semantic-release"
27 | },
28 | "main": "./dist/index.js",
29 | "module": "./dist/index.esm.js",
30 | "types": "./dist/types/index.d.ts",
31 | "files": [
32 | "dist/"
33 | ],
34 | "keywords": [
35 | "vue",
36 | "axios",
37 | "composition-api",
38 | "http-client"
39 | ],
40 | "license": "Apache-2.0",
41 | "devDependencies": {
42 | "@semantic-release/changelog": "^5.0.1",
43 | "@semantic-release/git": "^9.0.0",
44 | "@semantic-release/github": "^7.2.3",
45 | "@semantic-release/npm": "^7.1.3",
46 | "@types/jest": "^26.0.24",
47 | "@typescript-eslint/eslint-plugin": "^4.28.5",
48 | "@typescript-eslint/parser": "^4.28.5",
49 | "@vue/eslint-config-prettier": "^6.0.0",
50 | "@vue/eslint-config-typescript": "^7.0.0",
51 | "axios": "^0.24.0",
52 | "eslint": "^7.32.0",
53 | "eslint-plugin-prettier": "^3.4.0",
54 | "eslint-plugin-vue": "^7.15.0",
55 | "jest": "^26.6.3",
56 | "prettier": "^2.3.2",
57 | "rimraf": "^3.0.2",
58 | "rollup": "^2.55.1",
59 | "semantic-release": "^17.4.4",
60 | "ts-jest": "^26.5.6",
61 | "typescript": "^4.3.5",
62 | "vue": "^3.1.5"
63 | },
64 | "dependencies": {},
65 | "peerDependencies": {
66 | "axios": ">=0.24.0",
67 | "vue": ">=3.1.0"
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/rollup.config.js:
--------------------------------------------------------------------------------
1 | export default {
2 | input: 'dist-transpiled/index.js',
3 | output: [
4 | {
5 | dir: 'dist/',
6 | entryFileNames: '[name].esm.js',
7 | chunkFileNames: '[name]-[hash].esm.js',
8 | format: 'es',
9 | sourcemap: true,
10 | },
11 | {
12 | dir: 'dist/',
13 | format: 'commonjs',
14 | preferConst: true,
15 | sourcemap: true,
16 | },
17 | ],
18 | external: ['axios', 'vue'],
19 | }
20 |
--------------------------------------------------------------------------------
/src/axios.test.ts:
--------------------------------------------------------------------------------
1 | import { $axios } from './axios'
2 |
3 | describe('axios defaults', () => {
4 | test('should have a default timeout', () => {
5 | expect($axios.defaults.timeout).toBe(5000)
6 | })
7 |
8 | test('should have a default headers', () => {
9 | expect($axios.defaults.headers.common.Accept).toBe('application/json')
10 | expect($axios.defaults.headers.common.ContentType).toBe('application/json')
11 | })
12 | })
13 |
--------------------------------------------------------------------------------
/src/axios.ts:
--------------------------------------------------------------------------------
1 | import Axios from 'axios'
2 |
3 | Axios.defaults.timeout = 5000
4 | Axios.defaults.headers.common.Accept = 'application/json'
5 | Axios.defaults.headers.common.ContentType = 'application/json'
6 |
7 | export const $axios = Axios
8 |
--------------------------------------------------------------------------------
/src/composable.test.ts:
--------------------------------------------------------------------------------
1 | import { AxiosResponse } from 'axios'
2 | import { useAxios } from './composable'
3 |
4 | describe('useAxios', () => {
5 | test('should have the correct inital values', () => {
6 | const { abortMessage, data, status, statusText, aborted, isLoading, isSuccessful, hasFailed, headers } = useAxios()
7 | expect(data.value).toBe(undefined)
8 | expect(headers.value).toBe(undefined)
9 | expect(status.value).toBe(undefined)
10 | expect(statusText.value).toBe(undefined)
11 | expect(abortMessage.value).toBe(undefined)
12 | expect(aborted.value).toBe(false)
13 | expect(isLoading.value).toBe(false)
14 | expect(isSuccessful.value).toBe(false)
15 | expect(hasFailed.value).toBe(false)
16 | })
17 |
18 | test('should map the axios response object to the reactive values', async () => {
19 | const mock = jest.fn().mockReturnValue({
20 | status: 200,
21 | statusText: 'Ok',
22 | data: 'data',
23 | headers: {
24 | ContentType: 'json',
25 | },
26 | config: {},
27 | } as AxiosResponse)
28 | const { abortMessage, data, status, statusText, aborted, isLoading, isSuccessful, hasFailed, headers, request } =
29 | useAxios({ request: mock } as any)
30 |
31 | await request({ url: '/path' })
32 |
33 | expect(data.value).toBe('data')
34 | expect(headers.value).toStrictEqual({ ContentType: 'json' })
35 | expect(status.value).toBe(200)
36 | expect(statusText.value).toBe('Ok')
37 | expect(abortMessage.value).toBe(undefined)
38 | expect(aborted.value).toBe(false)
39 | expect(isLoading.value).toBe(false)
40 | expect(isSuccessful.value).toBe(true)
41 | expect(hasFailed.value).toBe(false)
42 | })
43 |
44 | test('should map the failed response', async () => {
45 | const mock = jest.fn().mockReturnValue({
46 | status: 404,
47 | statusText: 'Not Found',
48 | } as AxiosResponse)
49 | const { status, statusText, isSuccessful, hasFailed, request } = useAxios({ request: mock } as any)
50 |
51 | await request({ url: '/path' })
52 |
53 | expect(status.value).toBe(404)
54 | expect(statusText.value).toBe('Not Found')
55 | expect(isSuccessful.value).toBe(false)
56 | expect(hasFailed.value).toBe(true)
57 | })
58 |
59 | test('should set isPending correct', async () => {
60 | const mock = jest.fn().mockImplementation(() => {
61 | return new Promise(resolve => {
62 | setTimeout(() => resolve({ status: 200 } as AxiosResponse), 0)
63 | })
64 | })
65 | const { isLoading, request } = useAxios({ request: mock } as any)
66 |
67 | const promise = request({ url: '/path' })
68 |
69 | expect(isLoading.value).toBe(true)
70 | await promise
71 | expect(isLoading.value).toBe(false)
72 | })
73 | })
74 |
--------------------------------------------------------------------------------
/src/composable.ts:
--------------------------------------------------------------------------------
1 | import { ref, Ref, shallowRef } from 'vue'
2 | import Axios, { AxiosError, AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios'
3 | import { $axios } from './axios'
4 | import { isPromise, wait } from './utils'
5 |
6 | export interface RequestArgs {
7 | url: string
8 | options: AxiosRequestConfig
9 | }
10 |
11 | export interface AxiosResponseComposables {
12 | response: Ref | undefined>
13 | data: Ref
14 | error: Ref | undefined>
15 | headers: Ref
16 | status: Ref
17 | statusText: Ref
18 | abortMessage: Ref
19 | hasFailed: Ref
20 | isFinished: Ref
21 | isSuccessful: Ref
22 | aborted: Ref
23 | }
24 |
25 | export interface AxiosComposables extends AxiosResponseComposables {
26 | isLoading: Ref
27 | abort: (message: string) => void
28 | request: (config: AxiosRequestConfig | Promise) => Promise
29 | requestMock: (
30 | config: AxiosRequestConfig | Promise,
31 | response: AxiosResponse,
32 | delay?: number,
33 | ) => Promise
34 | get: (url: string, config: AxiosRequestConfig) => Promise
35 | head: (url: string, config: AxiosRequestConfig) => Promise
36 | options: (url: string, config: AxiosRequestConfig) => Promise
37 | post: (url: string, data: T, config: AxiosRequestConfig) => Promise
38 | put: (url: string, data: T, config: AxiosRequestConfig) => Promise
39 | patch: (url: string, data: T, config: AxiosRequestConfig) => Promise
40 | remove: (url: string, config: AxiosRequestConfig) => Promise
41 | }
42 |
43 | export function useAxios(instance: AxiosInstance = $axios): AxiosComposables {
44 | const CancelToken = Axios.CancelToken
45 | const source = CancelToken.source()
46 |
47 | const aborted = ref(false)
48 | const abortMessage = ref()
49 | const isLoading = ref(false)
50 | const hasFailed = ref(false)
51 | const isSuccessful = ref(false)
52 | const isFinished = ref(false)
53 | const status = ref()
54 | const statusText = ref()
55 | const response = shallowRef>()
56 | const data = shallowRef()
57 | const error = shallowRef>()
58 | const headers = ref()
59 |
60 | function abort(message?: string) {
61 | if (isFinished.value || !isLoading.value) return
62 |
63 | source.cancel(message)
64 | abortMessage.value = message
65 | }
66 |
67 | function reset() {
68 | response.value = undefined
69 | data.value = undefined
70 | error.value = undefined
71 | status.value = 0
72 | statusText.value = undefined
73 | abortMessage.value = undefined
74 | isLoading.value = true
75 | hasFailed.value = false
76 | isSuccessful.value = false
77 | aborted.value = false
78 | isFinished.value = false
79 | }
80 |
81 | function map(res: AxiosResponse) {
82 | status.value = res.status
83 | status.value = res.status
84 | statusText.value = res.statusText
85 | isSuccessful.value = res.status < 400
86 | hasFailed.value = !isSuccessful.value
87 | data.value = res.data
88 | headers.value = res.headers as any
89 | }
90 |
91 | async function request(config: AxiosRequestConfig): Promise
92 | async function request(config: Promise): Promise
93 | async function request(config: AxiosRequestConfig | Promise): Promise {
94 | reset()
95 |
96 | if (isPromise(config)) {
97 | const { url, options } = (await config) as RequestArgs
98 | config = { url, ...options }
99 | }
100 |
101 | try {
102 | response.value = await instance.request({
103 | ...config,
104 | cancelToken: source.token,
105 | })
106 | map(response.value)
107 | } catch (_error) {
108 | error.value = _error
109 | hasFailed.value = true
110 | } finally {
111 | isLoading.value = false
112 | isFinished.value = true
113 | }
114 | }
115 |
116 | async function requestMock(config: AxiosRequestConfig, res: AxiosResponse, delay?: number): Promise
117 | async function requestMock(config: Promise, res: AxiosResponse, delay?: number): Promise
118 | async function requestMock(
119 | config: AxiosRequestConfig | Promise,
120 | res: AxiosResponse,
121 | delay?: number,
122 | ): Promise {
123 | reset()
124 |
125 | if (isPromise(config)) {
126 | const { url, options } = (await config) as RequestArgs
127 | config = { url, ...options }
128 | }
129 |
130 | try {
131 | await wait(delay)
132 | response.value = res
133 | map(res)
134 | } catch (_error) {
135 | error.value = _error
136 | hasFailed.value = true
137 | } finally {
138 | isLoading.value = false
139 | isFinished.value = true
140 | }
141 | }
142 |
143 | function get(url: string, config: AxiosRequestConfig): Promise {
144 | return request({ ...config, method: 'GET', url })
145 | }
146 |
147 | function head(url: string, config: AxiosRequestConfig): Promise {
148 | return request({ ...config, method: 'HEAD', url })
149 | }
150 |
151 | function options(url: string, config: AxiosRequestConfig): Promise {
152 | return request({ ...config, method: 'OPTIONS', url })
153 | }
154 |
155 | function post(url: string, data: T, config: AxiosRequestConfig): Promise {
156 | return request({ ...config, method: 'POST', url, data })
157 | }
158 |
159 | function put(url: string, data: T, config: AxiosRequestConfig): Promise {
160 | return request({ ...config, method: 'PUT', url, data })
161 | }
162 |
163 | function patch(url: string, data: T, config: AxiosRequestConfig): Promise {
164 | return request({ ...config, method: 'PATCH', url, data })
165 | }
166 |
167 | function remove(url: string, config: AxiosRequestConfig): Promise {
168 | return request({ ...config, method: 'DELETE', url })
169 | }
170 |
171 | return {
172 | data,
173 | response,
174 | error,
175 | headers,
176 | status,
177 | statusText,
178 | isLoading: isLoading,
179 | hasFailed,
180 | isSuccessful,
181 | isFinished,
182 | aborted,
183 | abortMessage,
184 | abort,
185 | request,
186 | requestMock,
187 | get,
188 | head,
189 | options,
190 | post,
191 | patch,
192 | put,
193 | remove,
194 | }
195 | }
196 |
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from './axios'
2 | export * from './composable'
3 | export * from './plugin'
4 |
--------------------------------------------------------------------------------
/src/plugin.test.ts:
--------------------------------------------------------------------------------
1 | import { vueAxios } from './plugin'
2 | import { $axios } from './axios'
3 |
4 | describe('plugin', () => {
5 | let appMock: any
6 |
7 | beforeEach(() => {
8 | appMock = {
9 | config: {
10 | globalProperties: {
11 | $axios: undefined,
12 | },
13 | },
14 | }
15 | })
16 |
17 | test('should set axios as globalProperties', async () => {
18 | await vueAxios.install(appMock)
19 |
20 | expect(appMock.config.globalProperties.$axios).toBeDefined()
21 | })
22 |
23 | test('should set override default config', async () => {
24 | await vueAxios.install(appMock, {
25 | baseURL: 'https://stackoverflow.com',
26 | })
27 |
28 | expect($axios.defaults.baseURL).toBe('https://stackoverflow.com')
29 | })
30 | })
31 |
--------------------------------------------------------------------------------
/src/plugin.ts:
--------------------------------------------------------------------------------
1 | /* ============
2 | * Axios
3 | * ============
4 | *
5 | * Promise based HTTP client for the browser and node.js.
6 | * Because Vue Resource has been retired, Axios will now been used
7 | * to perform AJAX-requests.
8 | *
9 | * https://github.com/mzabriskie/axios
10 | */
11 |
12 | import { AxiosDefaults } from 'axios'
13 | import { Plugin } from 'vue'
14 | import { $axios } from './axios'
15 |
16 | export const vueAxios: Plugin = {
17 | async install(app, defaults: AxiosDefaults) {
18 | $axios.defaults = {
19 | ...$axios.defaults,
20 | ...defaults,
21 | }
22 |
23 | app.config.globalProperties.$axios = $axios
24 | },
25 | }
26 |
--------------------------------------------------------------------------------
/src/utils.test.ts:
--------------------------------------------------------------------------------
1 | import { isPromise } from './utils'
2 |
3 | describe('util', () => {
4 | describe('isPromise', () => {
5 | test('should ', () => {
6 | expect(isPromise(new Promise(() => undefined))).toBe(true)
7 | })
8 | })
9 | })
10 |
--------------------------------------------------------------------------------
/src/utils.ts:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any
2 | export function isPromise(promise: any): boolean {
3 | return !!promise && typeof promise.then === 'function'
4 | }
5 |
6 | export async function wait(time = 2000): Promise {
7 | return new Promise(resolve => {
8 | setTimeout(() => resolve(undefined), time)
9 | })
10 | }
11 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "allowUnreachableCode": false,
4 | "allowSyntheticDefaultImports": true,
5 | "declaration": true,
6 | "emitDecoratorMetadata": true,
7 | "experimentalDecorators": true,
8 | "esModuleInterop": true,
9 | "lib": ["dom", "es2020"],
10 | "module": "es2015",
11 | "target": "es2017",
12 | "moduleResolution": "node",
13 | "noImplicitAny": true,
14 | "noImplicitReturns": true,
15 | "noUnusedLocals": true,
16 | "noUnusedParameters": true,
17 | "outDir": "dist-transpiled",
18 | "declarationDir": "dist/types",
19 | "removeComments": false,
20 | "sourceMap": true,
21 | "jsx": "react",
22 | "types": ["@types/jest"]
23 | },
24 | "include": ["src/**/*.ts", "src/**/*.tsx"],
25 | "exclude": ["node_modules", "src/**/*.test.ts", "src/**/*.spec.ts"],
26 | "compileOnSave": false,
27 | "buildOnSave": false
28 | }
29 |
--------------------------------------------------------------------------------