@beyonk/http 12.0.1 → 12.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/api/index.js DELETED
@@ -1,233 +0,0 @@
1
- import { AccessDeniedMixin } from '../error-handlers/access-denied.js'
2
- import { ConflictMixin } from '../error-handlers/conflict.js'
3
- import { DefaultMixin } from '../error-handlers/default.js'
4
- import { ForbiddenMixin } from '../error-handlers/forbidden.js'
5
- import { HandleMixin } from '../error-handlers/handle.js'
6
- import { NotFoundMixin } from '../error-handlers/not-found.js'
7
- import { BadDataMixin } from '../error-handlers/bad-data.js'
8
- import { PaymentRequiredMixin } from '../error-handlers/payment-required.js'
9
- import { PreconditionFailedMixin } from '../error-handlers/precondition-failed.js'
10
- import { TooManyRequestsMixin } from '../error-handlers/too-many-requests.js'
11
- import { NotAcceptableMixin } from '../error-handlers/not-acceptable.js'
12
- import { GoneMixin } from '../error-handlers/gone.js'
13
- import { ExpectationFailedMixin } from '../error-handlers/expectation-failed.js'
14
- import { byCode } from '../errors.js'
15
- import { compose } from './_just-compose.js'
16
-
17
- class ApiBase {}
18
- const Behaviours = compose(
19
- AccessDeniedMixin,
20
- ConflictMixin,
21
- DefaultMixin,
22
- ForbiddenMixin,
23
- HandleMixin,
24
- NotFoundMixin,
25
- BadDataMixin,
26
- PaymentRequiredMixin,
27
- PreconditionFailedMixin,
28
- TooManyRequestsMixin,
29
- NotAcceptableMixin,
30
- GoneMixin,
31
- ExpectationFailedMixin
32
- )(ApiBase)
33
-
34
- class Api extends Behaviours {
35
- constructor (options) {
36
- super()
37
- this.options = Object.assign({
38
- retry: false,
39
- parseErrors: true,
40
- handlers: {}
41
- }, options)
42
-
43
- this.handlers = {}
44
- this.client = null
45
- this.resetRequest()
46
- }
47
-
48
- resetRequest () {
49
- this.config = {
50
- endpoint: null,
51
- method: 'get',
52
- payload: null,
53
- query: null,
54
- headers: {},
55
- overrides: {}
56
- }
57
- }
58
-
59
- getClient () {
60
- if (this.options.mock) {
61
- console.warn('@beyonk/http: Using mocked http client')
62
- return this.options.mock
63
- }
64
-
65
- if (this.client) {
66
- return this.client
67
- } else if (typeof window !== 'undefined') {
68
- return window.fetch.bind(window)
69
- }
70
-
71
- throw Error("No client provided and can't find one automatically")
72
- }
73
-
74
- async send (fn) {
75
- const endpoint = this.config.endpoint.includes('://') ? this.config.endpoint : `${this.options.baseUrl}/${this.config.endpoint}`
76
- const hasPayload = !!this.config.payload
77
-
78
- const options = Object.assign(
79
- {
80
- method: this.config.method,
81
- cors: true,
82
- credentials: 'include',
83
- headers: Object.assign(
84
- { Accept: 'application/json' },
85
- hasPayload ? { 'Content-Type': 'application/json' } : {},
86
- this.config.headers
87
- )
88
- },
89
- hasPayload ? { body: JSON.stringify(this.config.payload) } : {},
90
- this.config.overrides
91
- )
92
-
93
- const client = this.getClient()
94
- const ep = this.config.query ? `${endpoint}?${this.config.query}` : `${endpoint}`
95
-
96
- let result
97
- try {
98
- result = await this._doQuery(1, client, ep, options)
99
- } catch (e) {
100
- console.log(e)
101
- return this.handle(e, this.ctx)
102
- } finally {
103
- this.resetRequest()
104
- }
105
-
106
- const { json, httpStatus } = result
107
- return fn ? fn(json, httpStatus) : json
108
- }
109
-
110
- _hasContent (response) {
111
- const contentLength = parseInt(response.headers.get('content-length'), 10)
112
-
113
- const isNoContentResponse = response.status === 204
114
- if (isNoContentResponse) {
115
- return false
116
- }
117
-
118
- const headerExists = !isNaN(contentLength)
119
- return !headerExists || contentLength > 0
120
- }
121
-
122
- async _doQuery (attempt, client, endpoint, options) {
123
- const retry = this.options.retry || { attempts: 1 }
124
- try {
125
- const r = await client(endpoint, options)
126
-
127
- if (r.status >= 200 && r.status < 400) {
128
- let json
129
-
130
- if (this._hasContent(r)) {
131
- try {
132
- json = await r.json()
133
- } catch (e) {
134
- console.error('Unable to parse response json', e.message)
135
- }
136
- }
137
-
138
- return { httpStatus: r.status, json }
139
- }
140
-
141
- let content = ''
142
- try {
143
- content = this.options.parseErrors ? await r.json() : await r.text()
144
- } catch (e) {
145
- console.log('Failed to parse error body when asked.')
146
- }
147
-
148
- const ClientError = byCode(r.status)
149
- throw new ClientError(r.statusText, content)
150
- } catch (e) {
151
- if (attempt < retry.attempts && retry.errors.includes(e.code)) {
152
- console.warn(`Got ${e.code} when calling ${endpoint}. Retrying request (${attempt}/${retry.attempts})`)
153
- return this._doQuery(++attempt, client, endpoint, options)
154
- }
155
-
156
- throw e
157
- }
158
- }
159
-
160
- context (ctx) {
161
- if (ctx.fetch) {
162
- this.client = ctx.fetch
163
- }
164
- this.ctx = ctx
165
- return this
166
- }
167
-
168
- override (override) {
169
- this.config.overrides = override
170
- return this
171
- }
172
-
173
- headers (headers) {
174
- this.config.headers = headers
175
- return this
176
- }
177
-
178
- async get (fn) {
179
- this.config.method = 'GET'
180
- return this.send(fn)
181
- }
182
-
183
- async post (fn) {
184
- this.config.method = 'POST'
185
- return this.send(fn)
186
- }
187
-
188
- async patch (fn) {
189
- this.config.method = 'PATCH'
190
- return this.send(fn)
191
- }
192
-
193
- async put (fn) {
194
- this.config.method = 'PUT'
195
- return this.send(fn)
196
- }
197
-
198
- async del (fn) {
199
- this.config.method = 'DELETE'
200
- return this.send(fn)
201
- }
202
-
203
- endpoint (endpoint) {
204
- this.config.endpoint = endpoint
205
- return this
206
- }
207
-
208
- query (query) {
209
- const q = Object.entries(query).reduce((curr, [ k, v ]) => {
210
- if (typeof v === 'undefined') {
211
- return curr
212
- }
213
- if (Array.isArray(v)) {
214
- curr.push(...v.map(n => `${k}=${encodeURIComponent(n)}`))
215
- } else {
216
- curr.push(`${k}=${encodeURIComponent(v)}`)
217
- }
218
- return curr
219
- }, [])
220
-
221
- this.config.query = q.join('&')
222
- return this
223
- }
224
-
225
- payload (payload) {
226
- this.config.payload = payload
227
- return this
228
- }
229
- }
230
-
231
- export {
232
- Api
233
- }