sharetribe-flex-sdk 1.14.0
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/.circleci/config.yml +22 -0
- package/.eslintignore +3 -0
- package/.eslintrc.js +19 -0
- package/CHANGELOG.md +231 -0
- package/LICENSE +201 -0
- package/README.md +76 -0
- package/build/sharetribe-flex-sdk-node.js +13592 -0
- package/build/sharetribe-flex-sdk-web.js +1 -0
- package/docs/README.md +20 -0
- package/docs/authentication.md +179 -0
- package/docs/calling-the-api.md +217 -0
- package/docs/configurations.md +95 -0
- package/docs/developing-sdk.md +131 -0
- package/docs/docpress.json +14 -0
- package/docs/features.md +14 -0
- package/docs/keep-alive.md +48 -0
- package/docs/object-query-parameters.md +36 -0
- package/docs/scripts.js +41 -0
- package/docs/serializing-types-to-json.md +40 -0
- package/docs/sharing-session-between-client-and-server.md +19 -0
- package/docs/styles.css +95 -0
- package/docs/token-store.md +114 -0
- package/docs/try-it-in-browser.md +32 -0
- package/docs/try-it-in-the-playground.md +153 -0
- package/docs/types.md +27 -0
- package/docs/writing-your-own-token-store.md +29 -0
- package/docs/your-own-types.md +61 -0
- package/examples/README.md +5 -0
- package/examples/getting-started-browser/README.md +22 -0
- package/examples/getting-started-browser/index.html +89 -0
- package/examples/getting-started-browser/index.js +156 -0
- package/examples/getting-started-browser/screenshots/screenshot1.png +0 -0
- package/examples/getting-started-browser/screenshots/screenshot2.png +0 -0
- package/examples/getting-started-node/README.md +23 -0
- package/examples/getting-started-node/index.js +139 -0
- package/examples/getting-started-node/screenshots/screenshot.png +0 -0
- package/package.json +83 -0
- package/playground.js +295 -0
- package/src/browser_cookie_store.js +26 -0
- package/src/context_runner.js +151 -0
- package/src/context_runner.test.js +185 -0
- package/src/detect.js +11 -0
- package/src/express_cookie_store.js +57 -0
- package/src/fake/adapter.js +130 -0
- package/src/fake/api.js +137 -0
- package/src/fake/auth.js +84 -0
- package/src/fake/token_store.js +231 -0
- package/src/index.js +25 -0
- package/src/interceptors/.eslintrc.js +5 -0
- package/src/interceptors/add_auth_header.js +32 -0
- package/src/interceptors/add_auth_header.test.js +50 -0
- package/src/interceptors/add_auth_token_response.js +16 -0
- package/src/interceptors/add_client_id_to_params.js +12 -0
- package/src/interceptors/add_client_secret_to_params.js +15 -0
- package/src/interceptors/add_grant_type_to_params.js +23 -0
- package/src/interceptors/add_idp_client_id_to_params.js +17 -0
- package/src/interceptors/add_idp_id_to_params.js +17 -0
- package/src/interceptors/add_idp_token_to_params.js +17 -0
- package/src/interceptors/add_scope_to_params.js +18 -0
- package/src/interceptors/add_subject_token_to_params.js +18 -0
- package/src/interceptors/add_token_exchange_grant_type_to_params.js +12 -0
- package/src/interceptors/auth_info.js +50 -0
- package/src/interceptors/clear_token_after_revoke.js +45 -0
- package/src/interceptors/default_params.js +12 -0
- package/src/interceptors/fetch_auth_token_from_api.js +33 -0
- package/src/interceptors/fetch_auth_token_from_store.js +27 -0
- package/src/interceptors/fetch_refresh_token_for_revoke.js +24 -0
- package/src/interceptors/multipart_request.js +35 -0
- package/src/interceptors/retry_with_anon_token.js +58 -0
- package/src/interceptors/retry_with_refresh_token.js +70 -0
- package/src/interceptors/save_token.js +20 -0
- package/src/interceptors/transit_request.js +27 -0
- package/src/interceptors/transit_request.test.js +58 -0
- package/src/interceptors/transit_response.js +27 -0
- package/src/memory_store.js +19 -0
- package/src/params_serializer.js +65 -0
- package/src/params_serializer.test.js +58 -0
- package/src/sdk.js +894 -0
- package/src/sdk.test.js +908 -0
- package/src/serializer.js +279 -0
- package/src/serializer.test.js +229 -0
- package/src/token_store.js +15 -0
- package/src/types.js +108 -0
- package/src/types.test.js +75 -0
- package/src/utils.js +68 -0
- package/src/utils.test.js +85 -0
- package/webpack.config.babel.js +47 -0
package/src/sdk.js
ADDED
|
@@ -0,0 +1,894 @@
|
|
|
1
|
+
import axios from 'axios';
|
|
2
|
+
import _ from 'lodash';
|
|
3
|
+
import { fnPath as urlPathToFnPath, trimEndSlash, formData } from './utils';
|
|
4
|
+
import paramsSerializer from './params_serializer';
|
|
5
|
+
import AddAuthHeader from './interceptors/add_auth_header';
|
|
6
|
+
import RetryWithRefreshToken from './interceptors/retry_with_refresh_token';
|
|
7
|
+
import RetryWithAnonToken from './interceptors/retry_with_anon_token';
|
|
8
|
+
import ClearTokenAfterRevoke from './interceptors/clear_token_after_revoke';
|
|
9
|
+
import FetchRefreshTokenForRevoke from './interceptors/fetch_refresh_token_for_revoke';
|
|
10
|
+
import AddAuthTokenResponse from './interceptors/add_auth_token_response';
|
|
11
|
+
import SaveToken from './interceptors/save_token';
|
|
12
|
+
import FetchAuthTokenFromApi from './interceptors/fetch_auth_token_from_api';
|
|
13
|
+
import FetchAuthTokenFromStore from './interceptors/fetch_auth_token_from_store';
|
|
14
|
+
import AddClientIdToParams from './interceptors/add_client_id_to_params';
|
|
15
|
+
import AddClientSecretToParams from './interceptors/add_client_secret_to_params';
|
|
16
|
+
import AddIdpClientIdToParams from './interceptors/add_idp_client_id_to_params';
|
|
17
|
+
import AddIdpIdToParams from './interceptors/add_idp_id_to_params';
|
|
18
|
+
import AddIdpTokenToParams from './interceptors/add_idp_token_to_params';
|
|
19
|
+
import AddSubjectTokenToParams from './interceptors/add_subject_token_to_params';
|
|
20
|
+
import AddGrantTypeToParams from './interceptors/add_grant_type_to_params';
|
|
21
|
+
import AddTokenExchangeGrantTypeToParams from './interceptors/add_token_exchange_grant_type_to_params';
|
|
22
|
+
import AddScopeToParams from './interceptors/add_scope_to_params';
|
|
23
|
+
import AuthInfo from './interceptors/auth_info';
|
|
24
|
+
import MultipartRequest from './interceptors/multipart_request';
|
|
25
|
+
import TransitRequest from './interceptors/transit_request';
|
|
26
|
+
import TransitResponse from './interceptors/transit_response';
|
|
27
|
+
import { createDefaultTokenStore } from './token_store';
|
|
28
|
+
import contextRunner from './context_runner';
|
|
29
|
+
|
|
30
|
+
/* eslint-disable class-methods-use-this */
|
|
31
|
+
|
|
32
|
+
const defaultSdkConfig = {
|
|
33
|
+
clientId: null,
|
|
34
|
+
clientSecret: null,
|
|
35
|
+
baseUrl: 'https://flex-api.sharetribe.com',
|
|
36
|
+
typeHandlers: [],
|
|
37
|
+
endpoints: [],
|
|
38
|
+
adapter: null,
|
|
39
|
+
version: 'v1',
|
|
40
|
+
httpAgent: null,
|
|
41
|
+
httpsAgent: null,
|
|
42
|
+
transitVerbose: false,
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
Basic configurations for different 'apis'.
|
|
47
|
+
|
|
48
|
+
Currently we have two apis:
|
|
49
|
+
|
|
50
|
+
- `api`: the marketplace API
|
|
51
|
+
- `auth`: the authentication API
|
|
52
|
+
|
|
53
|
+
These configurations will be passed to Axios library.
|
|
54
|
+
They define how to do the requets to the APIs, e.g.
|
|
55
|
+
how the parameters should be serialized,
|
|
56
|
+
what are the headers that should be always sent and
|
|
57
|
+
how to transform requests and response, etc.
|
|
58
|
+
*/
|
|
59
|
+
|
|
60
|
+
const createHeaders = transitVerbose => {
|
|
61
|
+
if (transitVerbose) {
|
|
62
|
+
return {
|
|
63
|
+
'X-Transit-Verbose': 'true',
|
|
64
|
+
Accept: 'application/transit+json',
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return {
|
|
69
|
+
Accept: 'application/transit+json',
|
|
70
|
+
};
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
const apis = {
|
|
74
|
+
api: ({ baseUrl, version, adapter, httpAgent, httpsAgent, transitVerbose }) => ({
|
|
75
|
+
headers: createHeaders(transitVerbose),
|
|
76
|
+
baseURL: `${baseUrl}/${version}`,
|
|
77
|
+
transformRequest: v => v,
|
|
78
|
+
transformResponse: v => v,
|
|
79
|
+
adapter,
|
|
80
|
+
paramsSerializer,
|
|
81
|
+
httpAgent,
|
|
82
|
+
httpsAgent,
|
|
83
|
+
}),
|
|
84
|
+
auth: ({ baseUrl, version, adapter, httpAgent, httpsAgent }) => ({
|
|
85
|
+
headers: {
|
|
86
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
87
|
+
Accept: 'application/json',
|
|
88
|
+
},
|
|
89
|
+
baseURL: `${baseUrl}/${version}/`,
|
|
90
|
+
transformRequest: [data => formData(data)],
|
|
91
|
+
// using default transformRequest, which can handle JSON and fallback to plain
|
|
92
|
+
// test if JSON parsing fails
|
|
93
|
+
adapter,
|
|
94
|
+
httpAgent,
|
|
95
|
+
httpsAgent,
|
|
96
|
+
}),
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
List of all known endpoints
|
|
101
|
+
|
|
102
|
+
- apiName: api / auth
|
|
103
|
+
- path: URL path to the endpoint
|
|
104
|
+
- internal: Is this method SDK internal only,
|
|
105
|
+
or will it be part of the public SDK interface
|
|
106
|
+
- method: HTTP method
|
|
107
|
+
*/
|
|
108
|
+
const endpointDefinitions = [
|
|
109
|
+
{
|
|
110
|
+
apiName: 'api',
|
|
111
|
+
path: 'marketplace/show',
|
|
112
|
+
internal: false,
|
|
113
|
+
method: 'get',
|
|
114
|
+
interceptors: [new TransitResponse()],
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
apiName: 'api',
|
|
118
|
+
path: 'users/show',
|
|
119
|
+
internal: false,
|
|
120
|
+
method: 'get',
|
|
121
|
+
interceptors: [new TransitResponse()],
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
apiName: 'api',
|
|
125
|
+
path: 'current_user/show',
|
|
126
|
+
internal: false,
|
|
127
|
+
method: 'get',
|
|
128
|
+
interceptors: [new TransitResponse()],
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
apiName: 'api',
|
|
132
|
+
path: 'current_user/create',
|
|
133
|
+
internal: false,
|
|
134
|
+
method: 'post',
|
|
135
|
+
interceptors: [new TransitResponse(), new TransitRequest()],
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
apiName: 'api',
|
|
139
|
+
path: 'current_user/create_with_idp',
|
|
140
|
+
internal: false,
|
|
141
|
+
method: 'post',
|
|
142
|
+
interceptors: [new TransitResponse(), new TransitRequest()],
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
apiName: 'api',
|
|
146
|
+
path: 'current_user/update_profile',
|
|
147
|
+
internal: false,
|
|
148
|
+
method: 'post',
|
|
149
|
+
interceptors: [new TransitResponse(), new TransitRequest()],
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
apiName: 'api',
|
|
153
|
+
path: 'current_user/change_email',
|
|
154
|
+
internal: false,
|
|
155
|
+
method: 'post',
|
|
156
|
+
interceptors: [new TransitResponse(), new TransitRequest()],
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
apiName: 'api',
|
|
160
|
+
path: 'current_user/change_password',
|
|
161
|
+
internal: false,
|
|
162
|
+
method: 'post',
|
|
163
|
+
interceptors: [new TransitResponse(), new TransitRequest()],
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
apiName: 'api',
|
|
167
|
+
path: 'current_user/verify_email',
|
|
168
|
+
internal: false,
|
|
169
|
+
method: 'post',
|
|
170
|
+
interceptors: [new TransitResponse(), new TransitRequest()],
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
apiName: 'api',
|
|
174
|
+
path: 'current_user/send_verification_email',
|
|
175
|
+
internal: false,
|
|
176
|
+
method: 'post',
|
|
177
|
+
interceptors: [new TransitResponse(), new TransitRequest()],
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
apiName: 'api',
|
|
181
|
+
path: 'current_user/create_stripe_account',
|
|
182
|
+
internal: false,
|
|
183
|
+
method: 'post',
|
|
184
|
+
interceptors: [new TransitResponse(), new TransitRequest()],
|
|
185
|
+
},
|
|
186
|
+
{
|
|
187
|
+
apiName: 'api',
|
|
188
|
+
path: 'current_user/update_stripe_account',
|
|
189
|
+
internal: false,
|
|
190
|
+
method: 'post',
|
|
191
|
+
interceptors: [new TransitResponse(), new TransitRequest()],
|
|
192
|
+
},
|
|
193
|
+
{
|
|
194
|
+
apiName: 'api',
|
|
195
|
+
path: 'current_user/delete_stripe_account',
|
|
196
|
+
internal: false,
|
|
197
|
+
method: 'post',
|
|
198
|
+
interceptors: [new TransitResponse(), new TransitRequest()],
|
|
199
|
+
},
|
|
200
|
+
{
|
|
201
|
+
apiName: 'api',
|
|
202
|
+
path: 'password_reset/request',
|
|
203
|
+
internal: false,
|
|
204
|
+
method: 'post',
|
|
205
|
+
interceptors: [new TransitResponse(), new TransitRequest()],
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
apiName: 'api',
|
|
209
|
+
path: 'password_reset/reset',
|
|
210
|
+
internal: false,
|
|
211
|
+
method: 'post',
|
|
212
|
+
interceptors: [new TransitResponse(), new TransitRequest()],
|
|
213
|
+
},
|
|
214
|
+
{
|
|
215
|
+
apiName: 'api',
|
|
216
|
+
path: 'listings/show',
|
|
217
|
+
internal: false,
|
|
218
|
+
method: 'get',
|
|
219
|
+
interceptors: [new TransitResponse()],
|
|
220
|
+
},
|
|
221
|
+
{
|
|
222
|
+
apiName: 'api',
|
|
223
|
+
path: 'own_listings/show',
|
|
224
|
+
internal: false,
|
|
225
|
+
method: 'get',
|
|
226
|
+
interceptors: [new TransitResponse()],
|
|
227
|
+
},
|
|
228
|
+
{
|
|
229
|
+
apiName: 'api',
|
|
230
|
+
path: 'listings/query',
|
|
231
|
+
internal: false,
|
|
232
|
+
method: 'get',
|
|
233
|
+
interceptors: [new TransitResponse()],
|
|
234
|
+
},
|
|
235
|
+
{
|
|
236
|
+
apiName: 'api',
|
|
237
|
+
path: 'own_listings/query',
|
|
238
|
+
internal: false,
|
|
239
|
+
method: 'get',
|
|
240
|
+
interceptors: [new TransitResponse()],
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
apiName: 'api',
|
|
244
|
+
path: 'listings/search',
|
|
245
|
+
internal: false,
|
|
246
|
+
method: 'get',
|
|
247
|
+
interceptors: [new TransitResponse()],
|
|
248
|
+
},
|
|
249
|
+
{
|
|
250
|
+
apiName: 'api',
|
|
251
|
+
path: 'own_listings/create',
|
|
252
|
+
internal: false,
|
|
253
|
+
method: 'post',
|
|
254
|
+
interceptors: [new TransitResponse(), new TransitRequest()],
|
|
255
|
+
},
|
|
256
|
+
{
|
|
257
|
+
apiName: 'api',
|
|
258
|
+
path: 'own_listings/create_draft',
|
|
259
|
+
internal: false,
|
|
260
|
+
method: 'post',
|
|
261
|
+
interceptors: [new TransitResponse(), new TransitRequest()],
|
|
262
|
+
},
|
|
263
|
+
{
|
|
264
|
+
apiName: 'api',
|
|
265
|
+
path: 'own_listings/publish_draft',
|
|
266
|
+
internal: false,
|
|
267
|
+
method: 'post',
|
|
268
|
+
interceptors: [new TransitResponse(), new TransitRequest()],
|
|
269
|
+
},
|
|
270
|
+
{
|
|
271
|
+
apiName: 'api',
|
|
272
|
+
path: 'own_listings/discard_draft',
|
|
273
|
+
internal: false,
|
|
274
|
+
method: 'post',
|
|
275
|
+
interceptors: [new TransitResponse(), new TransitRequest()],
|
|
276
|
+
},
|
|
277
|
+
{
|
|
278
|
+
apiName: 'api',
|
|
279
|
+
path: 'own_listings/update',
|
|
280
|
+
internal: false,
|
|
281
|
+
method: 'post',
|
|
282
|
+
interceptors: [new TransitResponse(), new TransitRequest()],
|
|
283
|
+
},
|
|
284
|
+
{
|
|
285
|
+
apiName: 'api',
|
|
286
|
+
path: 'own_listings/open',
|
|
287
|
+
internal: false,
|
|
288
|
+
method: 'post',
|
|
289
|
+
interceptors: [new TransitResponse(), new TransitRequest()],
|
|
290
|
+
},
|
|
291
|
+
{
|
|
292
|
+
apiName: 'api',
|
|
293
|
+
path: 'own_listings/close',
|
|
294
|
+
internal: false,
|
|
295
|
+
method: 'post',
|
|
296
|
+
interceptors: [new TransitResponse(), new TransitRequest()],
|
|
297
|
+
},
|
|
298
|
+
{
|
|
299
|
+
apiName: 'api',
|
|
300
|
+
path: 'own_listings/add_image',
|
|
301
|
+
internal: false,
|
|
302
|
+
method: 'post',
|
|
303
|
+
interceptors: [new TransitResponse(), new TransitRequest()],
|
|
304
|
+
},
|
|
305
|
+
{
|
|
306
|
+
apiName: 'api',
|
|
307
|
+
path: 'availability_exceptions/create',
|
|
308
|
+
internal: false,
|
|
309
|
+
method: 'post',
|
|
310
|
+
interceptors: [new TransitResponse(), new TransitRequest()],
|
|
311
|
+
},
|
|
312
|
+
{
|
|
313
|
+
apiName: 'api',
|
|
314
|
+
path: 'availability_exceptions/delete',
|
|
315
|
+
internal: false,
|
|
316
|
+
method: 'post',
|
|
317
|
+
interceptors: [new TransitResponse(), new TransitRequest()],
|
|
318
|
+
},
|
|
319
|
+
{
|
|
320
|
+
apiName: 'api',
|
|
321
|
+
path: 'availability_exceptions/query',
|
|
322
|
+
internal: false,
|
|
323
|
+
method: 'get',
|
|
324
|
+
interceptors: [new TransitResponse()],
|
|
325
|
+
},
|
|
326
|
+
{
|
|
327
|
+
apiName: 'api',
|
|
328
|
+
path: 'images/upload',
|
|
329
|
+
internal: false,
|
|
330
|
+
method: 'post',
|
|
331
|
+
interceptors: [new TransitResponse(), new MultipartRequest()],
|
|
332
|
+
},
|
|
333
|
+
{
|
|
334
|
+
apiName: 'api',
|
|
335
|
+
path: 'transactions/initiate',
|
|
336
|
+
internal: false,
|
|
337
|
+
method: 'post',
|
|
338
|
+
interceptors: [new TransitResponse(), new TransitRequest()],
|
|
339
|
+
},
|
|
340
|
+
{
|
|
341
|
+
apiName: 'api',
|
|
342
|
+
path: 'transactions/initiate_speculative',
|
|
343
|
+
internal: false,
|
|
344
|
+
method: 'post',
|
|
345
|
+
interceptors: [new TransitResponse(), new TransitRequest()],
|
|
346
|
+
},
|
|
347
|
+
{
|
|
348
|
+
apiName: 'api',
|
|
349
|
+
path: 'transactions/transition',
|
|
350
|
+
internal: false,
|
|
351
|
+
method: 'post',
|
|
352
|
+
interceptors: [new TransitResponse(), new TransitRequest()],
|
|
353
|
+
},
|
|
354
|
+
{
|
|
355
|
+
apiName: 'api',
|
|
356
|
+
path: 'transactions/transition_speculative',
|
|
357
|
+
internal: false,
|
|
358
|
+
method: 'post',
|
|
359
|
+
interceptors: [new TransitResponse(), new TransitRequest()],
|
|
360
|
+
},
|
|
361
|
+
{
|
|
362
|
+
apiName: 'api',
|
|
363
|
+
path: 'transactions/query',
|
|
364
|
+
internal: false,
|
|
365
|
+
method: 'get',
|
|
366
|
+
interceptors: [new TransitResponse()],
|
|
367
|
+
},
|
|
368
|
+
{
|
|
369
|
+
apiName: 'api',
|
|
370
|
+
path: 'transactions/show',
|
|
371
|
+
internal: false,
|
|
372
|
+
method: 'get',
|
|
373
|
+
interceptors: [new TransitResponse()],
|
|
374
|
+
},
|
|
375
|
+
{
|
|
376
|
+
apiName: 'api',
|
|
377
|
+
path: 'process_transitions/query',
|
|
378
|
+
internal: false,
|
|
379
|
+
method: 'get',
|
|
380
|
+
interceptors: [new TransitResponse()],
|
|
381
|
+
},
|
|
382
|
+
{
|
|
383
|
+
apiName: 'api',
|
|
384
|
+
path: 'bookings/query',
|
|
385
|
+
internal: false,
|
|
386
|
+
method: 'get',
|
|
387
|
+
interceptors: [new TransitResponse()],
|
|
388
|
+
},
|
|
389
|
+
{
|
|
390
|
+
apiName: 'api',
|
|
391
|
+
path: 'messages/query',
|
|
392
|
+
internal: false,
|
|
393
|
+
method: 'get',
|
|
394
|
+
interceptors: [new TransitResponse()],
|
|
395
|
+
},
|
|
396
|
+
{
|
|
397
|
+
apiName: 'api',
|
|
398
|
+
path: 'messages/send',
|
|
399
|
+
internal: false,
|
|
400
|
+
method: 'post',
|
|
401
|
+
interceptors: [new TransitResponse(), new TransitRequest()],
|
|
402
|
+
},
|
|
403
|
+
{
|
|
404
|
+
apiName: 'api',
|
|
405
|
+
path: 'reviews/query',
|
|
406
|
+
internal: false,
|
|
407
|
+
method: 'get',
|
|
408
|
+
interceptors: [new TransitResponse()],
|
|
409
|
+
},
|
|
410
|
+
{
|
|
411
|
+
apiName: 'api',
|
|
412
|
+
path: 'reviews/show',
|
|
413
|
+
internal: false,
|
|
414
|
+
method: 'get',
|
|
415
|
+
interceptors: [new TransitResponse()],
|
|
416
|
+
},
|
|
417
|
+
{
|
|
418
|
+
apiName: 'api',
|
|
419
|
+
path: 'timeslots/query',
|
|
420
|
+
internal: false,
|
|
421
|
+
method: 'get',
|
|
422
|
+
interceptors: [new TransitResponse()],
|
|
423
|
+
},
|
|
424
|
+
{
|
|
425
|
+
apiName: 'api',
|
|
426
|
+
path: 'stripe_account/create',
|
|
427
|
+
internal: false,
|
|
428
|
+
method: 'post',
|
|
429
|
+
interceptors: [new TransitResponse(), new TransitRequest()],
|
|
430
|
+
},
|
|
431
|
+
{
|
|
432
|
+
apiName: 'api',
|
|
433
|
+
path: 'stripe_account/fetch',
|
|
434
|
+
internal: false,
|
|
435
|
+
method: 'get',
|
|
436
|
+
interceptors: [new TransitResponse()],
|
|
437
|
+
},
|
|
438
|
+
{
|
|
439
|
+
apiName: 'api',
|
|
440
|
+
path: 'stripe_account/update',
|
|
441
|
+
internal: false,
|
|
442
|
+
method: 'post',
|
|
443
|
+
interceptors: [new TransitResponse(), new TransitRequest()],
|
|
444
|
+
},
|
|
445
|
+
{
|
|
446
|
+
apiName: 'api',
|
|
447
|
+
path: 'stripe_account_links/create',
|
|
448
|
+
internal: false,
|
|
449
|
+
method: 'post',
|
|
450
|
+
interceptors: [new TransitResponse(), new TransitRequest()],
|
|
451
|
+
},
|
|
452
|
+
{
|
|
453
|
+
apiName: 'api',
|
|
454
|
+
path: 'stripe_persons/create',
|
|
455
|
+
internal: false,
|
|
456
|
+
method: 'post',
|
|
457
|
+
interceptors: [new TransitResponse(), new TransitRequest()],
|
|
458
|
+
},
|
|
459
|
+
{
|
|
460
|
+
apiName: 'api',
|
|
461
|
+
path: 'stripe_setup_intents/create',
|
|
462
|
+
internal: false,
|
|
463
|
+
method: 'post',
|
|
464
|
+
interceptors: [new TransitResponse(), new TransitRequest()],
|
|
465
|
+
},
|
|
466
|
+
{
|
|
467
|
+
apiName: 'api',
|
|
468
|
+
path: 'stripe_customer/create',
|
|
469
|
+
internal: false,
|
|
470
|
+
method: 'post',
|
|
471
|
+
interceptors: [new TransitResponse(), new TransitRequest()],
|
|
472
|
+
},
|
|
473
|
+
{
|
|
474
|
+
apiName: 'api',
|
|
475
|
+
path: 'stripe_customer/add_payment_method',
|
|
476
|
+
internal: false,
|
|
477
|
+
method: 'post',
|
|
478
|
+
interceptors: [new TransitResponse(), new TransitRequest()],
|
|
479
|
+
},
|
|
480
|
+
{
|
|
481
|
+
apiName: 'api',
|
|
482
|
+
path: 'stripe_customer/delete_payment_method',
|
|
483
|
+
internal: false,
|
|
484
|
+
method: 'post',
|
|
485
|
+
interceptors: [new TransitResponse(), new TransitRequest()],
|
|
486
|
+
},
|
|
487
|
+
{
|
|
488
|
+
apiName: 'api',
|
|
489
|
+
path: 'stock_adjustments/query',
|
|
490
|
+
internal: false,
|
|
491
|
+
method: 'get',
|
|
492
|
+
interceptors: [new TransitResponse()],
|
|
493
|
+
},
|
|
494
|
+
{
|
|
495
|
+
apiName: 'api',
|
|
496
|
+
path: 'stock_adjustments/create',
|
|
497
|
+
internal: false,
|
|
498
|
+
method: 'post',
|
|
499
|
+
interceptors: [new TransitResponse(), new TransitRequest()],
|
|
500
|
+
},
|
|
501
|
+
{
|
|
502
|
+
apiName: 'api',
|
|
503
|
+
path: 'stock/compare_and_set',
|
|
504
|
+
internal: false,
|
|
505
|
+
method: 'post',
|
|
506
|
+
interceptors: [new TransitResponse(), new TransitRequest()],
|
|
507
|
+
},
|
|
508
|
+
{
|
|
509
|
+
apiName: 'auth',
|
|
510
|
+
path: 'token',
|
|
511
|
+
internal: true,
|
|
512
|
+
method: 'post',
|
|
513
|
+
interceptors: [],
|
|
514
|
+
},
|
|
515
|
+
{
|
|
516
|
+
apiName: 'auth',
|
|
517
|
+
path: 'revoke',
|
|
518
|
+
internal: true,
|
|
519
|
+
method: 'post',
|
|
520
|
+
interceptors: [],
|
|
521
|
+
},
|
|
522
|
+
{
|
|
523
|
+
apiName: 'auth',
|
|
524
|
+
path: 'auth_with_idp',
|
|
525
|
+
internal: true,
|
|
526
|
+
method: 'post',
|
|
527
|
+
interceptors: [],
|
|
528
|
+
},
|
|
529
|
+
|
|
530
|
+
/* ******************************************************************************** */
|
|
531
|
+
|
|
532
|
+
/* Deprecated endpoints */
|
|
533
|
+
|
|
534
|
+
/* ******************************************************************************** */
|
|
535
|
+
];
|
|
536
|
+
|
|
537
|
+
const authenticateInterceptors = [
|
|
538
|
+
new FetchAuthTokenFromStore(),
|
|
539
|
+
new FetchAuthTokenFromApi(),
|
|
540
|
+
new RetryWithAnonToken(),
|
|
541
|
+
new RetryWithRefreshToken(),
|
|
542
|
+
new AddAuthHeader(),
|
|
543
|
+
];
|
|
544
|
+
|
|
545
|
+
const loginInterceptors = [
|
|
546
|
+
new AddClientIdToParams(),
|
|
547
|
+
new AddGrantTypeToParams(),
|
|
548
|
+
new AddScopeToParams(),
|
|
549
|
+
new SaveToken(),
|
|
550
|
+
new AddAuthTokenResponse(),
|
|
551
|
+
];
|
|
552
|
+
|
|
553
|
+
const logoutInterceptors = [
|
|
554
|
+
new FetchAuthTokenFromStore(),
|
|
555
|
+
new ClearTokenAfterRevoke(),
|
|
556
|
+
new RetryWithRefreshToken(),
|
|
557
|
+
new AddAuthHeader(),
|
|
558
|
+
new FetchRefreshTokenForRevoke(),
|
|
559
|
+
];
|
|
560
|
+
|
|
561
|
+
const exchangeTokenInterceptors = [
|
|
562
|
+
new FetchAuthTokenFromStore(),
|
|
563
|
+
new RetryWithRefreshToken(),
|
|
564
|
+
new AddClientIdToParams(),
|
|
565
|
+
new AddClientSecretToParams(),
|
|
566
|
+
new AddSubjectTokenToParams(),
|
|
567
|
+
new AddTokenExchangeGrantTypeToParams(),
|
|
568
|
+
];
|
|
569
|
+
|
|
570
|
+
const authWithIdpInterceptors = [
|
|
571
|
+
new AddClientIdToParams(),
|
|
572
|
+
new AddClientSecretToParams(),
|
|
573
|
+
new AddIdpClientIdToParams(),
|
|
574
|
+
new AddIdpIdToParams(),
|
|
575
|
+
new AddIdpTokenToParams(),
|
|
576
|
+
new SaveToken(),
|
|
577
|
+
new AddAuthTokenResponse(),
|
|
578
|
+
];
|
|
579
|
+
|
|
580
|
+
/**
|
|
581
|
+
Take endpoint definitions and return SDK function definition.
|
|
582
|
+
*/
|
|
583
|
+
const sdkFnDefsFromEndpointDefs = epDefs =>
|
|
584
|
+
epDefs
|
|
585
|
+
.filter(({ internal = false }) => !internal)
|
|
586
|
+
.map(({ apiName, path, method }) => {
|
|
587
|
+
const fnPath = urlPathToFnPath(path);
|
|
588
|
+
const fullFnPath = [apiName, ...fnPath];
|
|
589
|
+
|
|
590
|
+
return {
|
|
591
|
+
method,
|
|
592
|
+
path: fnPath,
|
|
593
|
+
endpointInterceptorPath: fullFnPath,
|
|
594
|
+
interceptors: [...authenticateInterceptors],
|
|
595
|
+
};
|
|
596
|
+
});
|
|
597
|
+
|
|
598
|
+
/**
|
|
599
|
+
List of SDK methods that will be part of the SDKs public interface.
|
|
600
|
+
The list is created from the `endpointDefinitions` list.
|
|
601
|
+
|
|
602
|
+
The objects in the list have following fields:
|
|
603
|
+
|
|
604
|
+
- path (String | Array): The function name and path. I.e. if the path is `listings.show`,
|
|
605
|
+
then there will be a public SDK method `sdk.listings.show`
|
|
606
|
+
- endpointInterceptorPath (String | Array): Path to endpoint interceptor
|
|
607
|
+
- interceptors: List of additional interceptors.
|
|
608
|
+
|
|
609
|
+
*/
|
|
610
|
+
const endpointSdkFnDefinitions = sdkFnDefsFromEndpointDefs(endpointDefinitions);
|
|
611
|
+
|
|
612
|
+
/**
|
|
613
|
+
List of SDK methods that are not derived from the endpoints.
|
|
614
|
+
*/
|
|
615
|
+
const additionalSdkFnDefinitions = [
|
|
616
|
+
{
|
|
617
|
+
path: 'login',
|
|
618
|
+
endpointInterceptorPath: 'auth.token',
|
|
619
|
+
interceptors: loginInterceptors,
|
|
620
|
+
},
|
|
621
|
+
{
|
|
622
|
+
path: 'logout',
|
|
623
|
+
endpointInterceptorPath: 'auth.revoke',
|
|
624
|
+
interceptors: [...logoutInterceptors],
|
|
625
|
+
},
|
|
626
|
+
{
|
|
627
|
+
path: 'exchangeToken',
|
|
628
|
+
endpointInterceptorPath: 'auth.token',
|
|
629
|
+
interceptors: exchangeTokenInterceptors,
|
|
630
|
+
},
|
|
631
|
+
{ path: 'authInfo', interceptors: [new AuthInfo()] },
|
|
632
|
+
{
|
|
633
|
+
path: 'loginWithIdp',
|
|
634
|
+
endpointInterceptorPath: 'auth.authWithIdp',
|
|
635
|
+
interceptors: authWithIdpInterceptors,
|
|
636
|
+
},
|
|
637
|
+
];
|
|
638
|
+
|
|
639
|
+
// const logAndReturn = (data) => {
|
|
640
|
+
// console.log(data);
|
|
641
|
+
// return data;
|
|
642
|
+
// };
|
|
643
|
+
|
|
644
|
+
const handleSuccessResponse = response => {
|
|
645
|
+
const { status, statusText, data } = response;
|
|
646
|
+
|
|
647
|
+
return { status, statusText, data };
|
|
648
|
+
};
|
|
649
|
+
|
|
650
|
+
// GET requests: `params` includes query params. `queryParams` will be ignored
|
|
651
|
+
// POST requests: `params` includes body params. `queryParams` includes URL query params
|
|
652
|
+
const doRequest = ({ params = {}, queryParams = {}, httpOpts }) => {
|
|
653
|
+
const { method = 'get' } = httpOpts;
|
|
654
|
+
|
|
655
|
+
let data = null;
|
|
656
|
+
let query = null;
|
|
657
|
+
|
|
658
|
+
if (method.toLowerCase() === 'post') {
|
|
659
|
+
data = params;
|
|
660
|
+
query = queryParams;
|
|
661
|
+
} else {
|
|
662
|
+
query = params;
|
|
663
|
+
// leave `data` null
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
const req = {
|
|
667
|
+
...httpOpts,
|
|
668
|
+
method,
|
|
669
|
+
data,
|
|
670
|
+
params: query,
|
|
671
|
+
};
|
|
672
|
+
|
|
673
|
+
return axios.request(req).then(handleSuccessResponse);
|
|
674
|
+
};
|
|
675
|
+
|
|
676
|
+
/**
|
|
677
|
+
Creates a list of endpoint interceptors that call the endpoint with the
|
|
678
|
+
given parameters.
|
|
679
|
+
*/
|
|
680
|
+
const createEndpointInterceptors = ({ method, url, httpOpts }) => {
|
|
681
|
+
const { headers: httpOptsHeaders, ...restHttpOpts } = httpOpts;
|
|
682
|
+
|
|
683
|
+
return {
|
|
684
|
+
enter: ctx => {
|
|
685
|
+
const { params, queryParams, headers, perRequestOpts } = ctx;
|
|
686
|
+
return doRequest({
|
|
687
|
+
params,
|
|
688
|
+
queryParams,
|
|
689
|
+
httpOpts: {
|
|
690
|
+
...perRequestOpts,
|
|
691
|
+
method: method || 'get',
|
|
692
|
+
// Merge additional headers
|
|
693
|
+
headers: { ...httpOptsHeaders, ...headers },
|
|
694
|
+
...restHttpOpts,
|
|
695
|
+
url,
|
|
696
|
+
},
|
|
697
|
+
})
|
|
698
|
+
.then(res => ({ ...ctx, res }))
|
|
699
|
+
.catch(error => {
|
|
700
|
+
const errorCtx = { ...ctx, res: error.response };
|
|
701
|
+
// eslint-disable-next-line no-param-reassign
|
|
702
|
+
error.ctx = errorCtx;
|
|
703
|
+
throw error;
|
|
704
|
+
});
|
|
705
|
+
},
|
|
706
|
+
};
|
|
707
|
+
};
|
|
708
|
+
|
|
709
|
+
const formatError = e => {
|
|
710
|
+
/* eslint-disable no-param-reassign */
|
|
711
|
+
if (e.response) {
|
|
712
|
+
const { status, statusText, data } = e.response;
|
|
713
|
+
Object.assign(e, { status, statusText, data });
|
|
714
|
+
delete e.response;
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
if (e.ctx) {
|
|
718
|
+
// Remove context `ctx` from the error response.
|
|
719
|
+
//
|
|
720
|
+
// `ctx` is SDK internal and should be exposed as a part of the
|
|
721
|
+
// SDK public API. It can be added in the response for debugging
|
|
722
|
+
// purposes, if needed.
|
|
723
|
+
delete e.ctx;
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
if (e.config) {
|
|
727
|
+
// Axios attachs the config object that was used to the error.
|
|
728
|
+
//
|
|
729
|
+
// Remove context `config` from the error response.
|
|
730
|
+
//
|
|
731
|
+
// `ctx` is SDK internal and should be exposed as a part of the
|
|
732
|
+
// SDK public API. It can be added in the response for debugging
|
|
733
|
+
// purposes, if needed.
|
|
734
|
+
delete e.config;
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
throw e;
|
|
738
|
+
/* eslint-enable no-param-reassign */
|
|
739
|
+
};
|
|
740
|
+
|
|
741
|
+
const allowedPerRequestOpts = opts => _.pick(opts, ['onUploadProgress']);
|
|
742
|
+
|
|
743
|
+
const createSdkFnContextRunner = ({
|
|
744
|
+
params,
|
|
745
|
+
queryParams,
|
|
746
|
+
perRequestOpts,
|
|
747
|
+
ctx,
|
|
748
|
+
interceptors,
|
|
749
|
+
endpointInterceptors,
|
|
750
|
+
}) =>
|
|
751
|
+
contextRunner(_.compact([...interceptors, ...endpointInterceptors]))({
|
|
752
|
+
...ctx,
|
|
753
|
+
params,
|
|
754
|
+
queryParams,
|
|
755
|
+
perRequestOpts,
|
|
756
|
+
})
|
|
757
|
+
.then(({ res }) => res)
|
|
758
|
+
.catch(formatError);
|
|
759
|
+
const createSdkPostFn = sdkFnParams => (params = {}, queryParams = {}, perRequestOpts = {}) =>
|
|
760
|
+
createSdkFnContextRunner({
|
|
761
|
+
params,
|
|
762
|
+
queryParams,
|
|
763
|
+
perRequestOpts: allowedPerRequestOpts(perRequestOpts),
|
|
764
|
+
...sdkFnParams,
|
|
765
|
+
});
|
|
766
|
+
const createSdkGetFn = sdkFnParams => (params = {}) =>
|
|
767
|
+
createSdkFnContextRunner({ params, ...sdkFnParams });
|
|
768
|
+
/**
|
|
769
|
+
Creates a new SDK function.
|
|
770
|
+
|
|
771
|
+
'sdk function' is a function that will be attached to the SDK instance.
|
|
772
|
+
These functions will be part of the SDK's public interface.
|
|
773
|
+
|
|
774
|
+
It's meant to used by the user of the SDK.
|
|
775
|
+
*/
|
|
776
|
+
const createSdkFn = ({ method, ...sdkFnParams }) => {
|
|
777
|
+
if (method && method.toLowerCase() === 'post') {
|
|
778
|
+
return createSdkPostFn(sdkFnParams);
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
return createSdkGetFn(sdkFnParams);
|
|
782
|
+
};
|
|
783
|
+
|
|
784
|
+
// Take SDK configurations, do transformation and return.
|
|
785
|
+
const transformSdkConfig = ({ baseUrl, tokenStore, ...sdkConfig }) => ({
|
|
786
|
+
...sdkConfig,
|
|
787
|
+
baseUrl: trimEndSlash(baseUrl),
|
|
788
|
+
tokenStore:
|
|
789
|
+
tokenStore || createDefaultTokenStore(tokenStore, sdkConfig.clientId, !!sdkConfig.secure),
|
|
790
|
+
});
|
|
791
|
+
|
|
792
|
+
// Validate SDK configurations, throw an error if invalid, otherwise return.
|
|
793
|
+
const validateSdkConfig = sdkConfig => {
|
|
794
|
+
if (!sdkConfig.clientId) {
|
|
795
|
+
throw new Error('clientId must be provided');
|
|
796
|
+
}
|
|
797
|
+
|
|
798
|
+
if (!sdkConfig.baseUrl) {
|
|
799
|
+
throw new Error('baseUrl must be provided');
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
/* global window, console */
|
|
803
|
+
const isBrowser = typeof window !== 'undefined' && typeof window.document !== 'undefined';
|
|
804
|
+
|
|
805
|
+
if (isBrowser && sdkConfig.clientSecret && !sdkConfig.dangerouslyAllowClientSecretInBrowser) {
|
|
806
|
+
/* eslint-disable no-console */
|
|
807
|
+
console.warn(
|
|
808
|
+
'Security warning! You are using client secret in a browser. This may expose the client secret to the public.'
|
|
809
|
+
);
|
|
810
|
+
console.warn(
|
|
811
|
+
'If you know what you are doing and you have secured the website by other means (e.g. HTTP basic auth), you should set the SDK configuration `dangerouslyAllowClientSecretInBrowser` to `true` to dismiss this warning.'
|
|
812
|
+
);
|
|
813
|
+
console.warn(
|
|
814
|
+
'In the future SDK versions, we may change this warning to an error causing the site not to work properly, unless `dangerouslyAllowClientSecretInBrowser` is set'
|
|
815
|
+
);
|
|
816
|
+
/* eslint-enable no-console */
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
return sdkConfig;
|
|
820
|
+
};
|
|
821
|
+
|
|
822
|
+
export default class SharetribeSdk {
|
|
823
|
+
/**
|
|
824
|
+
Instantiates a new SharetribeSdk instance.
|
|
825
|
+
The constructor assumes the config options have been
|
|
826
|
+
already validated.
|
|
827
|
+
*/
|
|
828
|
+
constructor(userSdkConfig) {
|
|
829
|
+
// Transform and validation SDK configurations
|
|
830
|
+
const sdkConfig = validateSdkConfig(
|
|
831
|
+
transformSdkConfig({ ...defaultSdkConfig, ...userSdkConfig })
|
|
832
|
+
);
|
|
833
|
+
|
|
834
|
+
// Instantiate API configs
|
|
835
|
+
const apiConfigs = _.mapValues(apis, apiConfig => apiConfig(sdkConfig));
|
|
836
|
+
|
|
837
|
+
// Read the endpoint definitions and do some mapping
|
|
838
|
+
const endpointDefs = [...endpointDefinitions].map(epDef => {
|
|
839
|
+
const { path, apiName, method, interceptors = [] } = epDef;
|
|
840
|
+
const fnPath = urlPathToFnPath(path);
|
|
841
|
+
const fullFnPath = [apiName, ...fnPath];
|
|
842
|
+
const url = [apiName, path].join('/');
|
|
843
|
+
const httpOpts = apiConfigs[apiName];
|
|
844
|
+
|
|
845
|
+
const endpointInterceptors = [
|
|
846
|
+
...interceptors,
|
|
847
|
+
createEndpointInterceptors({ method, url, httpOpts }),
|
|
848
|
+
];
|
|
849
|
+
|
|
850
|
+
return {
|
|
851
|
+
...epDef,
|
|
852
|
+
fnPath,
|
|
853
|
+
fullFnPath,
|
|
854
|
+
endpointInterceptors,
|
|
855
|
+
};
|
|
856
|
+
});
|
|
857
|
+
|
|
858
|
+
// Create `endpointInterceptors` object, which is object
|
|
859
|
+
// containing interceptors for all defined endpoints.
|
|
860
|
+
// This object can be passed to other interceptors in the interceptor context so they
|
|
861
|
+
// are able to do API calls (e.g. authentication interceptors)
|
|
862
|
+
const endpointInterceptors = endpointDefs.reduce(
|
|
863
|
+
(acc, { fullFnPath, endpointInterceptors: interceptors }) =>
|
|
864
|
+
_.set(acc, fullFnPath, interceptors),
|
|
865
|
+
{}
|
|
866
|
+
);
|
|
867
|
+
|
|
868
|
+
// Create a context object that will be passed to the interceptor context runner
|
|
869
|
+
const ctx = {
|
|
870
|
+
tokenStore: sdkConfig.tokenStore,
|
|
871
|
+
endpointInterceptors,
|
|
872
|
+
clientId: sdkConfig.clientId,
|
|
873
|
+
clientSecret: sdkConfig.clientSecret,
|
|
874
|
+
typeHandlers: sdkConfig.typeHandlers,
|
|
875
|
+
transitVerbose: sdkConfig.transitVerbose,
|
|
876
|
+
};
|
|
877
|
+
|
|
878
|
+
// Create SDK functions
|
|
879
|
+
const sdkFns = [...endpointSdkFnDefinitions, ...additionalSdkFnDefinitions].map(
|
|
880
|
+
({ path, method, endpointInterceptorPath, interceptors }) => ({
|
|
881
|
+
path,
|
|
882
|
+
fn: createSdkFn({
|
|
883
|
+
method,
|
|
884
|
+
ctx,
|
|
885
|
+
endpointInterceptors: _.get(endpointInterceptors, endpointInterceptorPath) || [],
|
|
886
|
+
interceptors,
|
|
887
|
+
}),
|
|
888
|
+
})
|
|
889
|
+
);
|
|
890
|
+
|
|
891
|
+
// Assign SDK functions to 'this'
|
|
892
|
+
sdkFns.forEach(({ path, fn }) => _.set(this, path, fn));
|
|
893
|
+
}
|
|
894
|
+
}
|