@empathyco/x-adapter 8.1.0-alpha.2 → 8.1.0-alpha.20
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/README.md +169 -169
- package/dist/cjs/endpoint-adapter/endpoint-adapter.factory.js +6 -6
- package/dist/cjs/endpoint-adapter/endpoint-adapter.factory.js.map +1 -1
- package/dist/cjs/endpoint-adapter/index.js +1 -1
- package/dist/cjs/endpoint-adapter/index.js.map +1 -1
- package/dist/cjs/endpoint-adapter/types.js.map +1 -1
- package/dist/cjs/http-clients/__mocks__/fetch.mock.js +10 -9
- package/dist/cjs/http-clients/__mocks__/fetch.mock.js.map +1 -1
- package/dist/cjs/http-clients/errors/request-error.js.map +1 -1
- package/dist/cjs/http-clients/fetch.http-client.js +26 -5
- package/dist/cjs/http-clients/fetch.http-client.js.map +1 -1
- package/dist/cjs/http-clients/index.js.map +1 -1
- package/dist/cjs/http-clients/types.js.map +1 -1
- package/dist/cjs/http-clients/utils.js +3 -4
- package/dist/cjs/http-clients/utils.js.map +1 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/mappers/combine-mappers.js +3 -4
- package/dist/cjs/mappers/combine-mappers.js.map +1 -1
- package/dist/cjs/mappers/identity.mapper.js +1 -2
- package/dist/cjs/mappers/identity.mapper.js.map +1 -1
- package/dist/cjs/mappers/index.js.map +1 -1
- package/dist/cjs/mappers/schema-mapper.factory.js +3 -6
- package/dist/cjs/mappers/schema-mapper.factory.js.map +1 -1
- package/dist/cjs/mappers/types.js.map +1 -1
- package/dist/cjs/schemas/index.js +1 -1
- package/dist/cjs/schemas/index.js.map +1 -1
- package/dist/cjs/schemas/types.js.map +1 -1
- package/dist/cjs/schemas/utils.js +5 -8
- package/dist/cjs/schemas/utils.js.map +1 -1
- package/dist/cjs/utils/index.js.map +1 -1
- package/dist/cjs/utils/interpolate.js +3 -3
- package/dist/cjs/utils/interpolate.js.map +1 -1
- package/dist/esm/endpoint-adapter/endpoint-adapter.factory.js +5 -5
- package/dist/esm/endpoint-adapter/endpoint-adapter.factory.js.map +1 -1
- package/dist/esm/endpoint-adapter/index.js +1 -1
- package/dist/esm/endpoint-adapter/index.js.map +1 -1
- package/dist/esm/endpoint-adapter/types.js.map +1 -1
- package/dist/esm/http-clients/__mocks__/fetch.mock.js +8 -7
- package/dist/esm/http-clients/__mocks__/fetch.mock.js.map +1 -1
- package/dist/esm/http-clients/errors/request-error.js.map +1 -1
- package/dist/esm/http-clients/fetch.http-client.js +24 -4
- package/dist/esm/http-clients/fetch.http-client.js.map +1 -1
- package/dist/esm/http-clients/index.js.map +1 -1
- package/dist/esm/http-clients/types.js.map +1 -1
- package/dist/esm/http-clients/utils.js +1 -1
- package/dist/esm/http-clients/utils.js.map +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/mappers/combine-mappers.js +1 -1
- package/dist/esm/mappers/combine-mappers.js.map +1 -1
- package/dist/esm/mappers/identity.mapper.js.map +1 -1
- package/dist/esm/mappers/index.js.map +1 -1
- package/dist/esm/mappers/schema-mapper.factory.js +2 -4
- package/dist/esm/mappers/schema-mapper.factory.js.map +1 -1
- package/dist/esm/mappers/types.js.map +1 -1
- package/dist/esm/schemas/index.js +1 -1
- package/dist/esm/schemas/index.js.map +1 -1
- package/dist/esm/schemas/types.js.map +1 -1
- package/dist/esm/schemas/utils.js +2 -4
- package/dist/esm/schemas/utils.js.map +1 -1
- package/dist/esm/utils/index.js.map +1 -1
- package/dist/esm/utils/interpolate.js +2 -1
- package/dist/esm/utils/interpolate.js.map +1 -1
- package/dist/types/endpoint-adapter/endpoint-adapter.factory.d.ts +1 -1
- package/dist/types/endpoint-adapter/index.d.ts +1 -1
- package/dist/types/endpoint-adapter/types.d.ts +2 -2
- package/dist/types/http-clients/__mocks__/fetch.mock.d.ts +3 -4
- package/dist/types/http-clients/fetch.http-client.d.ts +22 -2
- package/dist/types/http-clients/types.d.ts +2 -2
- package/dist/types/http-clients/utils.d.ts +1 -1
- package/dist/types/mappers/combine-mappers.d.ts +2 -2
- package/dist/types/mappers/schema-mapper.factory.d.ts +2 -2
- package/dist/types/schemas/index.d.ts +1 -1
- package/dist/types/schemas/types.d.ts +6 -7
- package/dist/types/schemas/utils.d.ts +1 -1
- package/package.json +25 -23
package/README.md
CHANGED
|
@@ -14,7 +14,7 @@ Some features that it provides:
|
|
|
14
14
|
## Tech Stack
|
|
15
15
|
|
|
16
16
|
[](https://www.typescriptlang.org/)
|
|
17
|
-
[](https://vitest.dev/)
|
|
18
18
|
|
|
19
19
|
<br>
|
|
20
20
|
|
|
@@ -77,45 +77,45 @@ passed.
|
|
|
77
77
|
```ts
|
|
78
78
|
// API models
|
|
79
79
|
interface ApiRequest {
|
|
80
|
-
q?: string
|
|
81
|
-
id?: number
|
|
80
|
+
q?: string
|
|
81
|
+
id?: number
|
|
82
82
|
}
|
|
83
83
|
interface ApiSearchResponse {
|
|
84
|
-
products: ApiProduct[]
|
|
85
|
-
total: number
|
|
84
|
+
products: ApiProduct[]
|
|
85
|
+
total: number
|
|
86
86
|
}
|
|
87
87
|
interface ApiProduct {
|
|
88
|
-
id: number
|
|
89
|
-
title: string
|
|
90
|
-
price: number
|
|
88
|
+
id: number
|
|
89
|
+
title: string
|
|
90
|
+
price: number
|
|
91
91
|
}
|
|
92
92
|
|
|
93
93
|
// App models
|
|
94
94
|
interface AppSearchRequest {
|
|
95
|
-
query: string
|
|
95
|
+
query: string
|
|
96
96
|
}
|
|
97
97
|
interface AppSearchResponse {
|
|
98
|
-
products: AppProduct[]
|
|
99
|
-
total: number
|
|
98
|
+
products: AppProduct[]
|
|
99
|
+
total: number
|
|
100
100
|
}
|
|
101
101
|
interface AppProduct {
|
|
102
|
-
id: string
|
|
103
|
-
name: string
|
|
104
|
-
price: number
|
|
102
|
+
id: string
|
|
103
|
+
name: string
|
|
104
|
+
price: number
|
|
105
105
|
}
|
|
106
106
|
```
|
|
107
107
|
|
|
108
108
|
###### Adapter's factory function implementation
|
|
109
109
|
|
|
110
110
|
```ts
|
|
111
|
-
import { endpointAdapterFactory } from '@empathyco/x-adapter'
|
|
111
|
+
import { endpointAdapterFactory } from '@empathyco/x-adapter'
|
|
112
112
|
|
|
113
113
|
export const searchProducts = endpointAdapterFactory({
|
|
114
114
|
endpoint: 'https://dummyjson.com/products/search',
|
|
115
115
|
requestMapper({ query }: Readonly<AppSearchRequest>): ApiRequest {
|
|
116
116
|
return {
|
|
117
|
-
q: query // the request will be triggered as https://dummyjson.com/products/search?q=phone
|
|
118
|
-
}
|
|
117
|
+
q: query, // the request will be triggered as https://dummyjson.com/products/search?q=phone
|
|
118
|
+
}
|
|
119
119
|
},
|
|
120
120
|
responseMapper({ products, total }: Readonly<ApiSearchResponse>): AppSearchResponse {
|
|
121
121
|
return {
|
|
@@ -123,18 +123,18 @@ export const searchProducts = endpointAdapterFactory({
|
|
|
123
123
|
return {
|
|
124
124
|
id: product.id.toString(),
|
|
125
125
|
name: product.title,
|
|
126
|
-
price: product.price
|
|
127
|
-
}
|
|
126
|
+
price: product.price,
|
|
127
|
+
}
|
|
128
128
|
}),
|
|
129
|
-
total
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
})
|
|
129
|
+
total,
|
|
130
|
+
}
|
|
131
|
+
},
|
|
132
|
+
})
|
|
133
133
|
|
|
134
134
|
// Function call
|
|
135
135
|
async function searchOnClick() {
|
|
136
|
-
const response = await searchProducts({ query: 'phone' })
|
|
137
|
-
console.log('products', response.products)
|
|
136
|
+
const response = await searchProducts({ query: 'phone' })
|
|
137
|
+
console.log('products', response.products)
|
|
138
138
|
}
|
|
139
139
|
```
|
|
140
140
|
|
|
@@ -148,12 +148,12 @@ parameter is not found inside the request, an empty string will be used.
|
|
|
148
148
|
|
|
149
149
|
```ts
|
|
150
150
|
export const getItemById = endpointAdapterFactory({
|
|
151
|
-
endpoint: 'https://dummyjson.com/{section}/{id}'
|
|
151
|
+
endpoint: 'https://dummyjson.com/{section}/{id}',
|
|
152
152
|
// ... rest of options to configure
|
|
153
|
-
})
|
|
154
|
-
getItemById({ section: 'products', id: 1 })
|
|
155
|
-
getItemById({ section: 'quotes', id: 3 })
|
|
156
|
-
getItemById({ section: 'quotes' })
|
|
153
|
+
})
|
|
154
|
+
getItemById({ section: 'products', id: 1 }) // 'https://dummyjson.com/products/1'
|
|
155
|
+
getItemById({ section: 'quotes', id: 3 }) // 'https://dummyjson.com/quotes/3'
|
|
156
|
+
getItemById({ section: 'quotes' }) // 'https://dummyjson.com/quotes/'
|
|
157
157
|
```
|
|
158
158
|
|
|
159
159
|
For more complex use cases, you can use a mapper function. This function receives the request, and
|
|
@@ -161,9 +161,9 @@ must return the URL string.
|
|
|
161
161
|
|
|
162
162
|
```ts
|
|
163
163
|
export const getProductById = endpointAdapterFactory({
|
|
164
|
-
endpoint: ({ id }: GetProductByIdRequest) =>
|
|
164
|
+
endpoint: ({ id }: GetProductByIdRequest) => `https://dummyjson.com/products/${id}`,
|
|
165
165
|
// ... rest of options to configure
|
|
166
|
-
})
|
|
166
|
+
})
|
|
167
167
|
```
|
|
168
168
|
|
|
169
169
|
Additionally, you can also overwrite your adapter's endpoint definition using the
|
|
@@ -174,10 +174,10 @@ Additionally, you can also overwrite your adapter's endpoint definition using th
|
|
|
174
174
|
export const getItemById = endpointAdapterFactory({
|
|
175
175
|
endpoint: 'https://dummyjson.com/quotes/{id}',
|
|
176
176
|
// ... rest of options to configure
|
|
177
|
-
})
|
|
177
|
+
})
|
|
178
178
|
|
|
179
179
|
// You would pass the new endpoint in the function call
|
|
180
|
-
getItemById({ id: 1 }, { endpoint: 'https://dummyjson.com/products/{id}')
|
|
180
|
+
getItemById({ id: 1 }, { endpoint: 'https://dummyjson.com/products/{id}' })
|
|
181
181
|
```
|
|
182
182
|
|
|
183
183
|
<br>
|
|
@@ -194,39 +194,39 @@ object to make the request with.
|
|
|
194
194
|
```ts
|
|
195
195
|
// HTTP Client
|
|
196
196
|
const axiosHttpClient: HttpClient = (endpoint, options) =>
|
|
197
|
-
axios.get(endpoint, { params: options?.parameters }).then(response => response.data)
|
|
197
|
+
axios.get(endpoint, { params: options?.parameters }).then(response => response.data)
|
|
198
198
|
|
|
199
199
|
// Request Mapper
|
|
200
200
|
const customRequestMapper: Mapper<AppSearchRequest, ApiRequest> = ({ query }) => {
|
|
201
201
|
return {
|
|
202
|
-
q: query
|
|
203
|
-
}
|
|
204
|
-
}
|
|
202
|
+
q: query,
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
205
|
|
|
206
206
|
// Response Mapper
|
|
207
207
|
const customResponseMapper: Mapper<ApiSearchResponse, AppSearchResponse> = ({
|
|
208
208
|
products,
|
|
209
|
-
total
|
|
209
|
+
total,
|
|
210
210
|
}) => {
|
|
211
211
|
return {
|
|
212
212
|
products: products.map(product => {
|
|
213
213
|
return {
|
|
214
214
|
id: product.id.toString(),
|
|
215
215
|
name: product.title,
|
|
216
|
-
price: product.price
|
|
217
|
-
}
|
|
216
|
+
price: product.price,
|
|
217
|
+
}
|
|
218
218
|
}),
|
|
219
|
-
total
|
|
220
|
-
}
|
|
221
|
-
}
|
|
219
|
+
total,
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
222
|
|
|
223
223
|
// Adapter factory function implementation
|
|
224
224
|
export const searchProducts = endpointAdapterFactory({
|
|
225
225
|
endpoint: 'https://dummyjson.com/products/search',
|
|
226
226
|
httpClient: axiosHttpClient,
|
|
227
227
|
requestMapper: customRequestMapper,
|
|
228
|
-
responseMapper: customResponseMapper
|
|
229
|
-
})
|
|
228
|
+
responseMapper: customResponseMapper,
|
|
229
|
+
})
|
|
230
230
|
```
|
|
231
231
|
|
|
232
232
|
<br>
|
|
@@ -246,28 +246,28 @@ the value somehow.
|
|
|
246
246
|
```ts
|
|
247
247
|
// API models
|
|
248
248
|
interface ApiUserRequest {
|
|
249
|
-
q: string
|
|
249
|
+
q: string
|
|
250
250
|
}
|
|
251
251
|
interface ApiUserResponse {
|
|
252
|
-
users: ApiUser[]
|
|
253
|
-
total: number
|
|
252
|
+
users: ApiUser[]
|
|
253
|
+
total: number
|
|
254
254
|
}
|
|
255
255
|
interface ApiUser {
|
|
256
|
-
id: number
|
|
257
|
-
firstName: string
|
|
256
|
+
id: number
|
|
257
|
+
firstName: string
|
|
258
258
|
}
|
|
259
259
|
|
|
260
260
|
// App models
|
|
261
261
|
interface AppUserRequest {
|
|
262
|
-
query: string
|
|
262
|
+
query: string
|
|
263
263
|
}
|
|
264
264
|
interface AppUserResponse {
|
|
265
|
-
people: AppUser[]
|
|
266
|
-
total: number
|
|
265
|
+
people: AppUser[]
|
|
266
|
+
total: number
|
|
267
267
|
}
|
|
268
268
|
interface AppUser {
|
|
269
|
-
id: string
|
|
270
|
-
name: string
|
|
269
|
+
id: string
|
|
270
|
+
name: string
|
|
271
271
|
}
|
|
272
272
|
```
|
|
273
273
|
|
|
@@ -276,25 +276,25 @@ interface AppUser {
|
|
|
276
276
|
```ts
|
|
277
277
|
// Map both the request and the response to connect your model with the API you are working with.
|
|
278
278
|
const userSearchRequestMapper = schemaMapperFactory<AppUserRequest, ApiUserRequest>({
|
|
279
|
-
q: 'query'
|
|
280
|
-
})
|
|
279
|
+
q: 'query',
|
|
280
|
+
})
|
|
281
281
|
const userSearchResponseMapper = schemaMapperFactory<ApiUserResponse, AppUserResponse>({
|
|
282
282
|
people: ({ users }) =>
|
|
283
283
|
users.map(user => {
|
|
284
284
|
return {
|
|
285
285
|
id: user.id.toString(),
|
|
286
|
-
name: user.firstName
|
|
287
|
-
}
|
|
286
|
+
name: user.firstName,
|
|
287
|
+
}
|
|
288
288
|
}),
|
|
289
|
-
total: 'total'
|
|
290
|
-
})
|
|
289
|
+
total: 'total',
|
|
290
|
+
})
|
|
291
291
|
|
|
292
292
|
// Use the mappers in the Endpoint's adapter factory function
|
|
293
293
|
export const searchUsers = endpointAdapterFactory({
|
|
294
294
|
endpoint: 'https://dummyjson.com/users/search',
|
|
295
295
|
requestMapper: userSearchRequestMapper,
|
|
296
|
-
responseMapper: userSearchResponseMapper
|
|
297
|
-
})
|
|
296
|
+
responseMapper: userSearchResponseMapper,
|
|
297
|
+
})
|
|
298
298
|
```
|
|
299
299
|
|
|
300
300
|
<br>
|
|
@@ -310,46 +310,46 @@ them you just have to provide with the `Path` of the data to map, and the `Schem
|
|
|
310
310
|
```ts
|
|
311
311
|
// API models
|
|
312
312
|
interface ApiRequest {
|
|
313
|
-
q: string
|
|
313
|
+
q: string
|
|
314
314
|
}
|
|
315
315
|
interface ApiResponse {
|
|
316
|
-
users: ApiUser[]
|
|
317
|
-
total: number
|
|
316
|
+
users: ApiUser[]
|
|
317
|
+
total: number
|
|
318
318
|
}
|
|
319
319
|
interface ApiUser {
|
|
320
|
-
id: number
|
|
321
|
-
email: string
|
|
322
|
-
phone: string
|
|
323
|
-
address: ApiAddress
|
|
324
|
-
company: ApiAddress
|
|
320
|
+
id: number
|
|
321
|
+
email: string
|
|
322
|
+
phone: string
|
|
323
|
+
address: ApiAddress
|
|
324
|
+
company: ApiAddress
|
|
325
325
|
}
|
|
326
326
|
interface ApiAddress {
|
|
327
|
-
address: string
|
|
328
|
-
city: string
|
|
329
|
-
postalCode: string
|
|
327
|
+
address: string
|
|
328
|
+
city: string
|
|
329
|
+
postalCode: string
|
|
330
330
|
}
|
|
331
331
|
|
|
332
332
|
// App models
|
|
333
333
|
interface AppRequest {
|
|
334
|
-
query: string
|
|
334
|
+
query: string
|
|
335
335
|
}
|
|
336
336
|
interface AppResponse {
|
|
337
|
-
people: AppUser[]
|
|
338
|
-
count: number
|
|
337
|
+
people: AppUser[]
|
|
338
|
+
count: number
|
|
339
339
|
}
|
|
340
340
|
interface AppUser {
|
|
341
|
-
id: number
|
|
341
|
+
id: number
|
|
342
342
|
contact: {
|
|
343
|
-
email: string
|
|
344
|
-
phone: string
|
|
345
|
-
homeAddress: AppAddress
|
|
346
|
-
companyAddress: AppAddress
|
|
347
|
-
}
|
|
343
|
+
email: string
|
|
344
|
+
phone: string
|
|
345
|
+
homeAddress: AppAddress
|
|
346
|
+
companyAddress: AppAddress
|
|
347
|
+
}
|
|
348
348
|
}
|
|
349
349
|
interface AppAddress {
|
|
350
|
-
displayName: string
|
|
351
|
-
postalCode: number
|
|
352
|
-
city: string
|
|
350
|
+
displayName: string
|
|
351
|
+
postalCode: number
|
|
352
|
+
city: string
|
|
353
353
|
}
|
|
354
354
|
```
|
|
355
355
|
|
|
@@ -360,8 +360,8 @@ interface AppAddress {
|
|
|
360
360
|
const addressSchema: Schema<ApiAddress, AppUserAddress> = {
|
|
361
361
|
displayName: source => `${source.address}, ${source.postalCode} - ${source.city}`,
|
|
362
362
|
city: 'city',
|
|
363
|
-
postalCode: source => parseInt(source.postalCode)
|
|
364
|
-
}
|
|
363
|
+
postalCode: source => Number.parseInt(source.postalCode),
|
|
364
|
+
}
|
|
365
365
|
|
|
366
366
|
// User Schema definition with a subSchema
|
|
367
367
|
const userSchema: Schema<ApiUser, AppUser> = {
|
|
@@ -371,14 +371,14 @@ const userSchema: Schema<ApiUser, AppUser> = {
|
|
|
371
371
|
phone: 'phone',
|
|
372
372
|
homeAddress: {
|
|
373
373
|
$subSchema: addressSchema,
|
|
374
|
-
$path: 'address'
|
|
374
|
+
$path: 'address',
|
|
375
375
|
},
|
|
376
376
|
companyAddress: {
|
|
377
377
|
$subSchema: addressSchema,
|
|
378
|
-
$path: 'address'
|
|
379
|
-
}
|
|
380
|
-
}
|
|
381
|
-
}
|
|
378
|
+
$path: 'address',
|
|
379
|
+
},
|
|
380
|
+
},
|
|
381
|
+
}
|
|
382
382
|
```
|
|
383
383
|
|
|
384
384
|
###### Schema's mapper factory function implementation with subSchemas
|
|
@@ -388,21 +388,21 @@ const userSchema: Schema<ApiUser, AppUser> = {
|
|
|
388
388
|
const responseMapper = schemaMapperFactory<ApiSearchUsersResponse, AppSearchUsersResponse>({
|
|
389
389
|
people: {
|
|
390
390
|
$subSchema: userSchema,
|
|
391
|
-
$path: 'users'
|
|
391
|
+
$path: 'users',
|
|
392
392
|
},
|
|
393
|
-
count: 'total'
|
|
394
|
-
})
|
|
393
|
+
count: 'total',
|
|
394
|
+
})
|
|
395
395
|
|
|
396
396
|
const requestMapper = schemaMapperFactory<SearchUsersRequest, ApiSearchUsersRequest>({
|
|
397
|
-
q: 'query'
|
|
398
|
-
})
|
|
397
|
+
q: 'query',
|
|
398
|
+
})
|
|
399
399
|
|
|
400
400
|
// Endpoint Adapter Factory function implementation
|
|
401
401
|
export const searchUsersWithContactInfo = endpointAdapterFactory({
|
|
402
402
|
endpoint: 'https://dummyjson.com/users/search',
|
|
403
403
|
requestMapper,
|
|
404
|
-
responseMapper
|
|
405
|
-
})
|
|
404
|
+
responseMapper,
|
|
405
|
+
})
|
|
406
406
|
```
|
|
407
407
|
|
|
408
408
|
<br>
|
|
@@ -423,21 +423,21 @@ for different endpoint calls.
|
|
|
423
423
|
```ts
|
|
424
424
|
// API models
|
|
425
425
|
export interface ApiBaseObject {
|
|
426
|
-
id: number
|
|
427
|
-
body: string
|
|
426
|
+
id: number
|
|
427
|
+
body: string
|
|
428
428
|
}
|
|
429
429
|
|
|
430
430
|
// APP models
|
|
431
431
|
export interface AppBaseObject {
|
|
432
|
-
id: string
|
|
433
|
-
text: string
|
|
432
|
+
id: string
|
|
433
|
+
text: string
|
|
434
434
|
}
|
|
435
435
|
|
|
436
436
|
// Mutable Schema
|
|
437
437
|
export const baseObjectSchema = createMutableSchema<ApiBaseObject, AppBaseObject>({
|
|
438
438
|
id: ({ id }) => id.toString(),
|
|
439
|
-
text: 'body'
|
|
440
|
-
})
|
|
439
|
+
text: 'body',
|
|
440
|
+
})
|
|
441
441
|
```
|
|
442
442
|
|
|
443
443
|
Once we have the `MutableSchema`, we can use the following methods to fit our different APIs needs:
|
|
@@ -458,71 +458,71 @@ Once we have the `MutableSchema`, we can use the following methods to fit our di
|
|
|
458
458
|
###### Extend a MutableSchema to reuse it in two different endpoints with more fields
|
|
459
459
|
|
|
460
460
|
```ts
|
|
461
|
-
import { ApiBaseObject, AppBaseObject, baseObjectSchema } from '@/base-types'
|
|
461
|
+
import { ApiBaseObject, AppBaseObject, baseObjectSchema } from '@/base-types'
|
|
462
462
|
|
|
463
463
|
// Api models
|
|
464
464
|
interface ApiPost extends ApiBaseObject {
|
|
465
|
-
title: string
|
|
465
|
+
title: string
|
|
466
466
|
}
|
|
467
467
|
interface ApiPostsResponse {
|
|
468
|
-
posts: ApiPost[]
|
|
468
|
+
posts: ApiPost[]
|
|
469
469
|
}
|
|
470
470
|
|
|
471
471
|
interface ApiComment extends ApiBaseObject {
|
|
472
|
-
postId: number
|
|
472
|
+
postId: number
|
|
473
473
|
}
|
|
474
474
|
interface ApiCommentsResponse {
|
|
475
|
-
comments: ApiComment[]
|
|
475
|
+
comments: ApiComment[]
|
|
476
476
|
}
|
|
477
477
|
|
|
478
478
|
// App models
|
|
479
479
|
interface AppPost extends AppBaseObject {
|
|
480
|
-
postTitle: string
|
|
480
|
+
postTitle: string
|
|
481
481
|
}
|
|
482
482
|
interface AppPostsResponse {
|
|
483
|
-
posts: AppPost[]
|
|
483
|
+
posts: AppPost[]
|
|
484
484
|
}
|
|
485
485
|
|
|
486
486
|
interface AppComment extends AppBaseObject {
|
|
487
|
-
postId: number
|
|
487
|
+
postId: number
|
|
488
488
|
}
|
|
489
489
|
interface AppCommentsResponse {
|
|
490
|
-
comments: AppComment[]
|
|
490
|
+
comments: AppComment[]
|
|
491
491
|
}
|
|
492
492
|
|
|
493
493
|
// Extend for posts endpoint
|
|
494
494
|
const postSchema = baseObjectSchema.$extends<ApiPost, AppPost>({
|
|
495
|
-
postTitle: 'title'
|
|
496
|
-
})
|
|
495
|
+
postTitle: 'title',
|
|
496
|
+
})
|
|
497
497
|
|
|
498
498
|
const postsResponse = schemaMapperFactory<ApiPostsResponse, AppPostsResponse>({
|
|
499
499
|
posts: {
|
|
500
500
|
$subSchema: postSchema,
|
|
501
|
-
$path: 'posts'
|
|
502
|
-
}
|
|
503
|
-
})
|
|
501
|
+
$path: 'posts',
|
|
502
|
+
},
|
|
503
|
+
})
|
|
504
504
|
|
|
505
505
|
export const searchPosts = endpointAdapterFactory({
|
|
506
506
|
endpoint: 'https://dummyjson.com/posts',
|
|
507
|
-
responseMapper: postsResponse
|
|
508
|
-
})
|
|
507
|
+
responseMapper: postsResponse,
|
|
508
|
+
})
|
|
509
509
|
|
|
510
510
|
// Extend for comments endpoint
|
|
511
511
|
const commentSchema = baseObjectSchema.$extends<ApiComment, AppComment>({
|
|
512
|
-
postId: 'postId'
|
|
513
|
-
})
|
|
512
|
+
postId: 'postId',
|
|
513
|
+
})
|
|
514
514
|
|
|
515
515
|
const commentsResponse = schemaMapperFactory<ApiCommentsResponse, AppCommentsResponse>({
|
|
516
516
|
comments: {
|
|
517
517
|
$subSchema: commentSchema,
|
|
518
|
-
$path: 'comments'
|
|
519
|
-
}
|
|
520
|
-
})
|
|
518
|
+
$path: 'comments',
|
|
519
|
+
},
|
|
520
|
+
})
|
|
521
521
|
|
|
522
522
|
export const searchComments = endpointAdapterFactory({
|
|
523
523
|
endpoint: 'https://dummyjson.com/comments',
|
|
524
|
-
responseMapper: commentsResponse
|
|
525
|
-
})
|
|
524
|
+
responseMapper: commentsResponse,
|
|
525
|
+
})
|
|
526
526
|
```
|
|
527
527
|
|
|
528
528
|
###### Override a MutableSchema to add more fields
|
|
@@ -532,50 +532,50 @@ that doesn't differ too much against the one used in our "base project". That me
|
|
|
532
532
|
most of the types and schemas definitions, so we would only add a few new fields from the new API.
|
|
533
533
|
|
|
534
534
|
```ts
|
|
535
|
-
import { ApiBaseObject, AppBaseObject, baseObjectSchema } from '@/base-types'
|
|
535
|
+
import { ApiBaseObject, AppBaseObject, baseObjectSchema } from '@/base-types'
|
|
536
536
|
|
|
537
537
|
// Api models
|
|
538
538
|
interface ApiTodo {
|
|
539
|
-
completed: boolean
|
|
540
|
-
todo: string
|
|
541
|
-
userId: number
|
|
539
|
+
completed: boolean
|
|
540
|
+
todo: string
|
|
541
|
+
userId: number
|
|
542
542
|
}
|
|
543
543
|
|
|
544
544
|
interface ApiTodosResponse {
|
|
545
|
-
todos: ApiBaseObject[]
|
|
545
|
+
todos: ApiBaseObject[]
|
|
546
546
|
}
|
|
547
547
|
|
|
548
548
|
// App models
|
|
549
549
|
interface AppTodo {
|
|
550
|
-
completed: boolean
|
|
551
|
-
text: string
|
|
552
|
-
userId: string
|
|
550
|
+
completed: boolean
|
|
551
|
+
text: string
|
|
552
|
+
userId: string
|
|
553
553
|
}
|
|
554
554
|
|
|
555
555
|
interface AppTodosResponse {
|
|
556
|
-
todos: AppBaseObject[]
|
|
556
|
+
todos: AppBaseObject[]
|
|
557
557
|
}
|
|
558
558
|
|
|
559
559
|
// Response mapper
|
|
560
560
|
const todosResponse = schemaMapperFactory<ApiTodosResponse, AppTodosResponse>({
|
|
561
561
|
todos: {
|
|
562
562
|
$subSchema: baseObjectSchema,
|
|
563
|
-
$path: 'todos'
|
|
564
|
-
}
|
|
565
|
-
})
|
|
563
|
+
$path: 'todos',
|
|
564
|
+
},
|
|
565
|
+
})
|
|
566
566
|
|
|
567
567
|
// Endpoint Adapter
|
|
568
568
|
export const searchTodos = endpointAdapterFactory({
|
|
569
569
|
endpoint: 'https://dummyjson.com/todos',
|
|
570
|
-
responseMapper: todosResponse
|
|
571
|
-
})
|
|
570
|
+
responseMapper: todosResponse,
|
|
571
|
+
})
|
|
572
572
|
|
|
573
573
|
// Override the original Schema. The Schema changes to map: 'id', 'completed', 'text' and 'userId''
|
|
574
574
|
baseObjectSchema.$override<ApiTodo, AppTodo>({
|
|
575
575
|
completed: 'completed',
|
|
576
576
|
text: 'todo',
|
|
577
|
-
userId: ({ userId }) => userId.toString()
|
|
578
|
-
})
|
|
577
|
+
userId: ({ userId }) => userId.toString(),
|
|
578
|
+
})
|
|
579
579
|
```
|
|
580
580
|
|
|
581
581
|
###### Replace a MutableSchema to completely change it
|
|
@@ -585,50 +585,50 @@ whole adapter from scratch, as there are other parts of the API that aren't chan
|
|
|
585
585
|
should replace some `endpointAdapter`'s schemas.
|
|
586
586
|
|
|
587
587
|
```ts
|
|
588
|
-
import { ApiBaseObject, AppBaseObject, baseObjectSchema } from '@/base-types'
|
|
588
|
+
import { ApiBaseObject, AppBaseObject, baseObjectSchema } from '@/base-types'
|
|
589
589
|
|
|
590
590
|
// Api models
|
|
591
591
|
interface ApiQuote {
|
|
592
|
-
id: number
|
|
593
|
-
quote: string
|
|
594
|
-
author: string
|
|
592
|
+
id: number
|
|
593
|
+
quote: string
|
|
594
|
+
author: string
|
|
595
595
|
}
|
|
596
596
|
|
|
597
597
|
interface ApiQuotesResponse {
|
|
598
|
-
quotes: ApiBaseObject[]
|
|
598
|
+
quotes: ApiBaseObject[]
|
|
599
599
|
}
|
|
600
600
|
|
|
601
601
|
// App models
|
|
602
602
|
interface AppQuote {
|
|
603
|
-
quoteId: string
|
|
604
|
-
quote: string
|
|
605
|
-
author: string
|
|
603
|
+
quoteId: string
|
|
604
|
+
quote: string
|
|
605
|
+
author: string
|
|
606
606
|
}
|
|
607
607
|
|
|
608
608
|
interface AppQuotesResponse {
|
|
609
|
-
quotes: AppBaseObject[]
|
|
609
|
+
quotes: AppBaseObject[]
|
|
610
610
|
}
|
|
611
611
|
|
|
612
612
|
// Response mapper
|
|
613
613
|
const quotesResponse = schemaMapperFactory<ApiQuotesResponse, AppQuotesResponse>({
|
|
614
614
|
quotes: {
|
|
615
615
|
$subSchema: baseObjectSchema,
|
|
616
|
-
$path: 'quotes'
|
|
617
|
-
}
|
|
618
|
-
})
|
|
616
|
+
$path: 'quotes',
|
|
617
|
+
},
|
|
618
|
+
})
|
|
619
619
|
|
|
620
620
|
// Endpoint Adapter
|
|
621
621
|
export const searchQuotes = endpointAdapterFactory({
|
|
622
622
|
endpoint: 'https://dummyjson.com/quotes',
|
|
623
|
-
responseMapper: quotesResponse
|
|
624
|
-
})
|
|
623
|
+
responseMapper: quotesResponse,
|
|
624
|
+
})
|
|
625
625
|
|
|
626
626
|
// Replace the original Schema
|
|
627
627
|
baseObjectSchema.$replace<ApiQuote, AppQuote>({
|
|
628
628
|
quoteId: ({ id }) => id.toString(),
|
|
629
629
|
quote: 'quote',
|
|
630
|
-
author: 'author'
|
|
631
|
-
})
|
|
630
|
+
author: 'author',
|
|
631
|
+
})
|
|
632
632
|
```
|
|
633
633
|
|
|
634
634
|
<br>
|
|
@@ -642,9 +642,9 @@ you have built an adapter instance as a configuration object that contains all o
|
|
|
642
642
|
```ts
|
|
643
643
|
export const adapter = {
|
|
644
644
|
searchItem: getItemById,
|
|
645
|
-
searchList: searchComments
|
|
645
|
+
searchList: searchComments,
|
|
646
646
|
// Any endpoint adapter you are using to communicate with your API
|
|
647
|
-
}
|
|
647
|
+
}
|
|
648
648
|
|
|
649
649
|
adapter.searchList = searchComments.extends({
|
|
650
650
|
endpoint: 'https://dummyjson.com/comments/',
|
|
@@ -654,10 +654,10 @@ adapter.searchList = searchComments.extends({
|
|
|
654
654
|
defaultRequestOptions: {
|
|
655
655
|
parameters: {
|
|
656
656
|
limit: 10,
|
|
657
|
-
skip: 10
|
|
658
|
-
}
|
|
659
|
-
}
|
|
660
|
-
})
|
|
657
|
+
skip: 10,
|
|
658
|
+
},
|
|
659
|
+
},
|
|
660
|
+
})
|
|
661
661
|
```
|
|
662
662
|
|
|
663
663
|
For further detail, you can check the
|
|
@@ -668,7 +668,7 @@ needs.
|
|
|
668
668
|
|
|
669
669
|
## Test
|
|
670
670
|
|
|
671
|
-
**Empathy Adapter** features are tested using [
|
|
671
|
+
**Empathy Adapter** features are tested using [Vitest](https://vitest.dev/). You will find a
|
|
672
672
|
`__tests__` folder inside each of the project's sections.
|
|
673
673
|
|
|
674
674
|
```
|