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
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Keep-Alive
|
|
2
|
+
|
|
3
|
+
*Node.js only*
|
|
4
|
+
|
|
5
|
+
By default, Node.js `http.Agent` and `https.Agent` create a new
|
|
6
|
+
connection for each request. After the request is completed, the
|
|
7
|
+
connection is closed. By keeping the connection open and reusing it
|
|
8
|
+
for subsequent requests, the request time can be reduced. This is
|
|
9
|
+
escpecially true for HTTPS connections, where the SSL handshake adds
|
|
10
|
+
extra overhead for each request.
|
|
11
|
+
|
|
12
|
+
The SDK can be configured to use custom `httpAgent` and `httpsAgent`,
|
|
13
|
+
where the `keepAlive` can be set to `true`.
|
|
14
|
+
|
|
15
|
+
Using persistent Keep-Alive connections is **recommended**.
|
|
16
|
+
|
|
17
|
+
**Example:**
|
|
18
|
+
|
|
19
|
+
``` js
|
|
20
|
+
const express = require('express');
|
|
21
|
+
const http = require('http');
|
|
22
|
+
const https = require('https');
|
|
23
|
+
const sharetribeSdk = require('sharetribe-flex-sdk');
|
|
24
|
+
|
|
25
|
+
const app = express();
|
|
26
|
+
|
|
27
|
+
// Instantiate HTTP(S) Agents with keepAlive set to true.
|
|
28
|
+
// This will reduce the request time for consecutive requests by
|
|
29
|
+
// reusing the existing TCP connection, thus eliminating the time used
|
|
30
|
+
// for setting up new TCP connections.
|
|
31
|
+
const httpAgent = new http.Agent({ keepAlive: true });
|
|
32
|
+
const httpsAgent = new https.Agent({ keepAlive: true });
|
|
33
|
+
|
|
34
|
+
app.get('/', (req, res) => {
|
|
35
|
+
// Initialize the SDK instance
|
|
36
|
+
const sdk = sharetribeSdk.createInstance({
|
|
37
|
+
clientId: "<your Client ID>",
|
|
38
|
+
baseUrl: "<your Base URL>",
|
|
39
|
+
httpAgent: httpAgent,
|
|
40
|
+
httpsAgent: httpsAgent
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
// Call the SDK to preload listings
|
|
44
|
+
sdk.listings.search({ ... }).then((listingsResult) => {
|
|
45
|
+
// do rendering etc.
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
```
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Object query parameters
|
|
2
|
+
|
|
3
|
+
Some endpoints in the Flex Marketplace API require a specific syntax that allows
|
|
4
|
+
passing one or more key-value pairs as the value of a single query parameter.
|
|
5
|
+
The keys and values are colon-separated whereas the pairs are separated by
|
|
6
|
+
semicolons. For example, when requesting custom image variants:
|
|
7
|
+
|
|
8
|
+
``` js
|
|
9
|
+
sdk.listings.show({
|
|
10
|
+
id: listingId,
|
|
11
|
+
include: ["images"],
|
|
12
|
+
"fields.image": ["variants.my-variant"],
|
|
13
|
+
"imageVariant.my-variant": "w:640;h:1280;fit:scale"
|
|
14
|
+
}).then(res => {
|
|
15
|
+
// res.data contains the response data
|
|
16
|
+
});
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
To simplify building requests like these, the SDK provides a utility method:
|
|
20
|
+
`sharetribeSdk.util.objectQueryString`. It serializes an object into the correct
|
|
21
|
+
string syntax. Using this method, the request above can be written as follows:
|
|
22
|
+
|
|
23
|
+
``` js
|
|
24
|
+
sdk.listings.show({
|
|
25
|
+
id: listingId,
|
|
26
|
+
include: ["images"],
|
|
27
|
+
"fields.image": ["variants.my-variant"],
|
|
28
|
+
"imageVariant.my-variant": sharetribeSdk.util.objectQueryString({
|
|
29
|
+
w: 640,
|
|
30
|
+
h: 1280,
|
|
31
|
+
fit: 'scale'
|
|
32
|
+
})
|
|
33
|
+
}).then(res => {
|
|
34
|
+
// res.data contains the response data
|
|
35
|
+
});
|
|
36
|
+
```
|
package/docs/scripts.js
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
(function() {
|
|
2
|
+
|
|
3
|
+
function anchorLink(id) {
|
|
4
|
+
var div = document.createElement('div');
|
|
5
|
+
div.className = 'heading-anchor';
|
|
6
|
+
|
|
7
|
+
if (id) {
|
|
8
|
+
// SVG Icon from: https://octicons.github.com/icon/link/
|
|
9
|
+
div.innerHTML = '<a href="#' + id + '"><svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><title>link</title><path d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z" fill="#000" fill-rule="evenodd"/></svg></a>'
|
|
10
|
+
}
|
|
11
|
+
return div;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function renderAnchors() {
|
|
15
|
+
["h1", "h2", "h3", "h4", "h5"].forEach(function(tagName) {
|
|
16
|
+
Array.from(document.getElementsByTagName(tagName)).forEach(function(headerElem) {
|
|
17
|
+
headerElem.prepend(anchorLink(headerElem.id));
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function printWelcomeMessage() {
|
|
23
|
+
console.log("");
|
|
24
|
+
console.log("✨ Try the SDK in browser! ✨");
|
|
25
|
+
console.log("");
|
|
26
|
+
console.log("The SDK is loaded in window.sharetribeSdk global variable.");
|
|
27
|
+
console.log("");
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
document.addEventListener('DOMContentLoaded', function() {
|
|
31
|
+
// Render anchors when page is loaded
|
|
32
|
+
renderAnchors();
|
|
33
|
+
printWelcomeMessage();
|
|
34
|
+
}, false);
|
|
35
|
+
|
|
36
|
+
document.addEventListener('pjax:success', function() {
|
|
37
|
+
// Render anchors when page is changed
|
|
38
|
+
renderAnchors();
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
})();
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Serializing types to and from JSON
|
|
2
|
+
|
|
3
|
+
The SDK provides two helper functions to serialize and deserialize the
|
|
4
|
+
data to and from JSON while retaining the type information.
|
|
5
|
+
|
|
6
|
+
- `types.reviver`: Function to be passed to `JSON.parse`
|
|
7
|
+
- `types.replacer`: Function to be passed to `JSON.stringify`
|
|
8
|
+
|
|
9
|
+
Serializing the data to JSON may be necessary if you are saving the
|
|
10
|
+
data to
|
|
11
|
+
[LocalStorage](https://developer.mozilla.org/en-US/docs/Web/API/Storage/LocalStorage)
|
|
12
|
+
or if you have a server that fetches the data and you want to pass the
|
|
13
|
+
preloaded state to your [Redux
|
|
14
|
+
store](https://redux.js.org/recipes/server-rendering#inject-initial-component-html-and-state).
|
|
15
|
+
|
|
16
|
+
**Example:**
|
|
17
|
+
|
|
18
|
+
```js
|
|
19
|
+
const { reviver, replacer, UUID } = require('sharetribe-flex-sdk').types;
|
|
20
|
+
|
|
21
|
+
const testData = {
|
|
22
|
+
id: new UUID('f989541d-7e96-4c8a-b550-dff1eef25815')
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const roundtrip = JSON.parse(JSON.stringify(testData, replacer), reviver);
|
|
26
|
+
|
|
27
|
+
assert(roundtrip.id.constructor.name === 'UUID');
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
**Please note:** [Your own types](#your-own-types) are not serialized.
|
|
31
|
+
|
|
32
|
+
**Please note:** When the API call fails, [the error
|
|
33
|
+
response](./calling-the-api.md#error-response) is wrapped in
|
|
34
|
+
[Error](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error)
|
|
35
|
+
object. Stringifying Error object may result in unexpected results,
|
|
36
|
+
e.g. in some browsers `JSON.stringify(new Error("error"))` returns an
|
|
37
|
+
empty object. Because of this, it's recommended that you do not
|
|
38
|
+
stringify the whole SDK responses as is, but instead pick the
|
|
39
|
+
`status`, `statusText` and `data` fields from the response, and store
|
|
40
|
+
and stringify those.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Sharing session between client and server
|
|
2
|
+
|
|
3
|
+
For server side rendering, the server needs to be able to prefetch the
|
|
4
|
+
page data using the same user session than the client is using. For
|
|
5
|
+
example, if the user logs in as "joe", the client needs to pass the
|
|
6
|
+
session information to the server, so that the server is able to make
|
|
7
|
+
requests as "joe". In other words, the client and server need share
|
|
8
|
+
the same session information.
|
|
9
|
+
|
|
10
|
+
The sharing of the session can be achieved by cookies. When the client
|
|
11
|
+
SDK is configured to use the [Browser cookie
|
|
12
|
+
store](./token-store.md#browser-cookie-store) (default) and the server
|
|
13
|
+
SDK is configured to use the [Express cookie
|
|
14
|
+
store](./token-store.md#express-cookie-store), both client and server
|
|
15
|
+
are reading and writing the session to the same cookie. Thus, the
|
|
16
|
+
session information will be shared between server and client.
|
|
17
|
+
|
|
18
|
+
Have a look at the [Token store](./token-store.md) examples on how to
|
|
19
|
+
configure the cookie stores.
|
package/docs/styles.css
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The fonts included are copyrighted by the vendor listed below.
|
|
3
|
+
*
|
|
4
|
+
* Vendor: Mostardesign
|
|
5
|
+
* License URL: https://www.fontspring.com/licenses/mostardesign/webfont
|
|
6
|
+
*
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
@font-face {
|
|
10
|
+
font-family: 'sofiapro';
|
|
11
|
+
src: url('https://assets-sharetribecom.sharetribe.com/webfonts/sofiapro/sofiapro-extralight-webfont.woff2') format('woff2');
|
|
12
|
+
url('https://assets-sharetribecom.sharetribe.com/webfonts/sofiapro/sofiapro-extralight-webfont.woff') format('woff');
|
|
13
|
+
font-weight: 200;
|
|
14
|
+
font-style: normal;
|
|
15
|
+
}
|
|
16
|
+
@font-face {
|
|
17
|
+
font-family: 'sofiapro';
|
|
18
|
+
src: url('https://assets-sharetribecom.sharetribe.com/webfonts/sofiapro/sofiapro-light-webfont.woff2') format('woff2');
|
|
19
|
+
url('https://assets-sharetribecom.sharetribe.com/webfonts/sofiapro/sofiapro-light-webfont.woff') format('woff');
|
|
20
|
+
font-weight: 300;
|
|
21
|
+
font-style: normal;
|
|
22
|
+
}
|
|
23
|
+
@font-face {
|
|
24
|
+
font-family: 'sofiapro';
|
|
25
|
+
src: url('https://assets-sharetribecom.sharetribe.com/webfonts/sofiapro/sofiapro-regular-webfont.woff2') format('woff2');
|
|
26
|
+
url('https://assets-sharetribecom.sharetribe.com/webfonts/sofiapro/sofiapro-regular-webfont.woff') format('woff');
|
|
27
|
+
font-weight: 400;
|
|
28
|
+
font-style: normal;
|
|
29
|
+
}
|
|
30
|
+
@font-face {
|
|
31
|
+
font-family: 'sofiapro';
|
|
32
|
+
src: url('https://assets-sharetribecom.sharetribe.com/webfonts/sofiapro/sofiapro-medium-webfont.woff2') format('woff2'),
|
|
33
|
+
url('https://assets-sharetribecom.sharetribe.com/webfonts/sofiapro/sofiapro-medium-webfont.woff') format('woff');
|
|
34
|
+
font-weight: 500; /* Medium */
|
|
35
|
+
font-style: normal;
|
|
36
|
+
}
|
|
37
|
+
@font-face {
|
|
38
|
+
font-family: 'sofiapro';
|
|
39
|
+
src: url('https://assets-sharetribecom.sharetribe.com/webfonts/sofiapro/sofiapro-semibold-webfont.woff2') format('woff2'),
|
|
40
|
+
url('https://assets-sharetribecom.sharetribe.com/webfonts/sofiapro/sofiapro-semibold-webfont.woff') format('woff');
|
|
41
|
+
font-weight: 600; /* SemiBold */
|
|
42
|
+
font-style: normal;
|
|
43
|
+
}
|
|
44
|
+
@font-face {
|
|
45
|
+
font-family: 'sofiapro';
|
|
46
|
+
src: url('https://assets-sharetribecom.sharetribe.com/webfonts/sofiapro/sofiapro-bold-webfont.woff2') format('woff2'),
|
|
47
|
+
url('https://assets-sharetribecom.sharetribe.com/webfonts/sofiapro/sofiapro-bold-webfont.woff') format('woff');
|
|
48
|
+
font-weight: 700; /* Bold */
|
|
49
|
+
font-style: normal;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
body {
|
|
53
|
+
-webkit-font-smoothing: antialiased; /* http://szafranek.net/blog/2009/02/22/font-smoothing-explained/ */
|
|
54
|
+
-moz-osx-font-smoothing: grayscale; /* http://szafranek.net/blog/2009/02/22/font-smoothing-explained/ */
|
|
55
|
+
text-rendering: optimizeSpeed;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.markdown-body {
|
|
59
|
+
font-family: sofiapro, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
h1, h2, h3, h4, h5 {
|
|
63
|
+
/* Position relative is needed for the hover anchor element */
|
|
64
|
+
position: relative;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
h1:hover .heading-anchor,
|
|
68
|
+
h2:hover .heading-anchor,
|
|
69
|
+
h3:hover .heading-anchor,
|
|
70
|
+
h4:hover .heading-anchor,
|
|
71
|
+
h5:hover .heading-anchor {
|
|
72
|
+
display: block;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
.heading-anchor {
|
|
76
|
+
display: none;
|
|
77
|
+
position: absolute;
|
|
78
|
+
left: -20px; /* -16px - right padding */
|
|
79
|
+
padding-right: 4px;
|
|
80
|
+
cursor: pointer;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
.heading-anchor svg {
|
|
84
|
+
/* Make SVG inline block, so that we can finetune the bottom margin */
|
|
85
|
+
display: inline-block;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
h1 .heading-anchor svg {
|
|
89
|
+
/* Fine tuning for nicer vertical alignment with the big h1 font size */
|
|
90
|
+
margin-bottom: 0.1em;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.heading-anchor:hover {
|
|
94
|
+
display: block;
|
|
95
|
+
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# Token store
|
|
2
|
+
|
|
3
|
+
Token store is a pluggable SDK module, that stores the user's session information.
|
|
4
|
+
|
|
5
|
+
The SDK ships with three token store implementations. They are:
|
|
6
|
+
|
|
7
|
+
### Browser cookie store
|
|
8
|
+
|
|
9
|
+
Reads and stores the session information to HTTP cookie. This token store
|
|
10
|
+
is used by default, if SDK is used in environment where cookie are
|
|
11
|
+
available (i.e. browser).
|
|
12
|
+
|
|
13
|
+
The constructor takes the following options:
|
|
14
|
+
|
|
15
|
+
| Key | Descriotion |
|
|
16
|
+
| --- | ----------- |
|
|
17
|
+
| `clientId` | The clientId |
|
|
18
|
+
| `secure` | Boolean. When `true`, the cookie will be transferred only with HTTPS requests |
|
|
19
|
+
|
|
20
|
+
**Please note:** Some browsers, like Google Chrome, do not set cookies
|
|
21
|
+
when using `file:///` protocol. In this case, you can use [Memory
|
|
22
|
+
store](#memory-store).
|
|
23
|
+
|
|
24
|
+
### Express cookie store
|
|
25
|
+
|
|
26
|
+
This token store is meant to be used with
|
|
27
|
+
[Express.js](https://expressjs.com/) server. Read and stores the
|
|
28
|
+
session information to HTTP cookie.
|
|
29
|
+
|
|
30
|
+
The constructor takes the following options:
|
|
31
|
+
|
|
32
|
+
| Key | Descriotion |
|
|
33
|
+
| --- | ----------- |
|
|
34
|
+
| `clientId` | The clientId |
|
|
35
|
+
| `req` | Express.js request |
|
|
36
|
+
| `res` | Express.js response |
|
|
37
|
+
| `secure` | Boolean. When `true`, the cookie will be transferred only with HTTPS requests |
|
|
38
|
+
|
|
39
|
+
**Example:** Create new SDK instance with Express cookie store:
|
|
40
|
+
|
|
41
|
+
``` js
|
|
42
|
+
const express = require('express');
|
|
43
|
+
const cookieParser = require('cookie-parser');
|
|
44
|
+
const sharetribeSdk = require('sharetribe-flex-sdk');
|
|
45
|
+
|
|
46
|
+
const app = express();
|
|
47
|
+
|
|
48
|
+
// The token store expects that cookieParser middleware is in use
|
|
49
|
+
app.use(cookieParser());
|
|
50
|
+
|
|
51
|
+
app.get('/', (req, res) => {
|
|
52
|
+
// Initialize the SDK instance
|
|
53
|
+
const sdk = sharetribeSdk.createInstance({
|
|
54
|
+
clientId: "<your Client ID>",
|
|
55
|
+
baseUrl: "<your Base URL>",
|
|
56
|
+
tokenStore: sharetribeSdk.tokenStore.expressCookieStore({
|
|
57
|
+
clientId: "<your Client ID>",
|
|
58
|
+
req,
|
|
59
|
+
res,
|
|
60
|
+
secure: true // Set to true, if you are using HTTPS
|
|
61
|
+
}),
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
// Call the SDK to preload listings
|
|
65
|
+
sdk.listings.search({ ... }).then((listingsResult) => {
|
|
66
|
+
// do rendering etc.
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
**Serious security note:** Always create a new SDK instance per each request! Do not store and reuse the SDK instance or you may end up mixing user sessions.
|
|
72
|
+
|
|
73
|
+
**❌ Example:** DON'T DO THIS!
|
|
74
|
+
|
|
75
|
+
``` js
|
|
76
|
+
// DON'T DO THIS!
|
|
77
|
+
//
|
|
78
|
+
let sdk;
|
|
79
|
+
|
|
80
|
+
app.get('/', (req, res) => {
|
|
81
|
+
// Initialize the SDK instance
|
|
82
|
+
sdk = sharetribeSdk.createInstance({
|
|
83
|
+
clientId: "<your Client ID>",
|
|
84
|
+
baseUrl: "<your Base URL>",
|
|
85
|
+
tokenStore: sharetribeSdk.tokenStore.expressCookieStore({
|
|
86
|
+
clientId: "<your Client ID>",
|
|
87
|
+
req,
|
|
88
|
+
res,
|
|
89
|
+
secure: true // Set true, if you are using HTTPS
|
|
90
|
+
}),
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
// Call the SDK to preload listings
|
|
94
|
+
sdk.listings.search({ ... }).then((listingsResult) => {
|
|
95
|
+
// do rendering etc.
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
app.get('/something_else', (req, res) => {
|
|
100
|
+
// OOPS! The previous user session is used here!
|
|
101
|
+
sdk.listings.search({ ... }).then((listingsResult) => {
|
|
102
|
+
// do rendering etc.
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## Memory store
|
|
109
|
+
|
|
110
|
+
Memory store stores the session information to application memory. The session information is lost when the page is refreshed.
|
|
111
|
+
|
|
112
|
+
This store is mainly used for testing and development.
|
|
113
|
+
|
|
114
|
+
In case you are testing locally from `file:///`, you may need to use memory store, because some browsers (e.g. Google Chrome) do not save cookies when using `file:///` making the default [Browser cookie store](#browser-cookie-store) unusable.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Try it in browser!
|
|
2
|
+
|
|
3
|
+
The SDK is loaded in **this page!**
|
|
4
|
+
|
|
5
|
+
To try the SDK, just open the Console in your browser's Developer
|
|
6
|
+
Tools and call `sharetribeSdk.createInstance(...)` to create a new SDK
|
|
7
|
+
instance.
|
|
8
|
+
|
|
9
|
+
Then copy-paste the following commands to the Console:
|
|
10
|
+
|
|
11
|
+
Set your clientId:
|
|
12
|
+
|
|
13
|
+
```js
|
|
14
|
+
const clientId = "<your clientId here>";
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Create new SDK instance:
|
|
18
|
+
|
|
19
|
+
```js
|
|
20
|
+
const sdk = sharetribeSdk.createInstance({clientId});
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Fetch 10 listings:
|
|
24
|
+
|
|
25
|
+
```js
|
|
26
|
+
sdk.listings.query({per_page: 10}).then(response => {
|
|
27
|
+
console.log("Fetched " + response.data.data.length + " listings.");
|
|
28
|
+
response.data.data.forEach(listing => {
|
|
29
|
+
console.log(listing.attributes.title);
|
|
30
|
+
})
|
|
31
|
+
})
|
|
32
|
+
```
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
# Try it in the API Playground!
|
|
2
|
+
|
|
3
|
+
The SDK ships with a command-line based API Playground. You can use
|
|
4
|
+
the Playground to try out the SDK with real API access to learn and
|
|
5
|
+
test things. It also supports executing scripts against the API.
|
|
6
|
+
|
|
7
|
+
To start the Playground, go to the directory where you cloned the SDK
|
|
8
|
+
Git repository and type:
|
|
9
|
+
|
|
10
|
+
```
|
|
11
|
+
$ yarn run playground --clientid <CLIENT-ID>
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
or use the shorthand:
|
|
15
|
+
```
|
|
16
|
+
$ yarn run pg -c <CLIENT-ID>
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
This will start the playground using your Marketplace API Client ID to
|
|
20
|
+
connect to to your marketplace. You can create a new or find your
|
|
21
|
+
existing Client ID in Flex Console at
|
|
22
|
+
https://flex-console.sharetribe.com/applications.
|
|
23
|
+
|
|
24
|
+
## Making API Requests
|
|
25
|
+
|
|
26
|
+
You can make API requests to the Marketplace API and print the results
|
|
27
|
+
using the built-in response printer:
|
|
28
|
+
|
|
29
|
+
```js
|
|
30
|
+
sdk.listings.query({per_page: 5}).then(printResponse);
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Alternatively you can use the pr() helper function:
|
|
34
|
+
```js
|
|
35
|
+
sdk.listings.query({per_page: 5});
|
|
36
|
+
pr();
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
You can also do custom processing of responses:
|
|
40
|
+
|
|
41
|
+
```js
|
|
42
|
+
sdk.listings.query({per_page: 10}).then(response => {
|
|
43
|
+
console.log("Fetched " + response.data.data.length + " listings.");
|
|
44
|
+
response.data.data.forEach(listing => {
|
|
45
|
+
console.log(listing.attributes.title);
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Authenticated access
|
|
51
|
+
|
|
52
|
+
To start the Playground in a user authenticated mode you can pass in
|
|
53
|
+
the user info you want to log in with:
|
|
54
|
+
|
|
55
|
+
```
|
|
56
|
+
$ yarn run pg -c <CLIENT-ID> -u useremail@yourdomain.com -s user-secret-password
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
In the Playground you can now make requests authenticated as the user:
|
|
60
|
+
|
|
61
|
+
```js
|
|
62
|
+
sdk.currentUser.show().then(printResponse);
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Viewing Marketplace API reference documentation
|
|
66
|
+
|
|
67
|
+
The Playground has a command for opening the Marketplace API reference
|
|
68
|
+
documentation in browser:
|
|
69
|
+
|
|
70
|
+
```
|
|
71
|
+
$ yarn run pg --apidocs
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
You can also do this in a playground session using the built-in
|
|
75
|
+
apiDocs function:
|
|
76
|
+
|
|
77
|
+
```js
|
|
78
|
+
apiDocs();
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Scripting support
|
|
82
|
+
|
|
83
|
+
The Playground also supports reading commands from a script file. The
|
|
84
|
+
commands from the given file are read as if they were lines entered
|
|
85
|
+
into an interactive Playground.
|
|
86
|
+
|
|
87
|
+
Let's say you have a script file create-listing.js for creating a new
|
|
88
|
+
listing for the logged in user:
|
|
89
|
+
|
|
90
|
+
```js
|
|
91
|
+
sdk.ownListings.query().then(res => {
|
|
92
|
+
console.log(`You have ${res.data.data.length} listings.`);
|
|
93
|
+
}).then(_ => {
|
|
94
|
+
console.log('Creating a new listings');
|
|
95
|
+
return sdk.ownListings.create({
|
|
96
|
+
title: "My new listings",
|
|
97
|
+
description: "A shiny new listing",
|
|
98
|
+
geolocation: new LatLng(40.64542, -74.08508),
|
|
99
|
+
price: new Money(1590, "USD"),
|
|
100
|
+
publicData: {
|
|
101
|
+
category: 'Electric',
|
|
102
|
+
gears: 22
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
}).then(res => {
|
|
106
|
+
console.log(`Created a new listings with id ${res.data.data.id.uuid}`);
|
|
107
|
+
return sdk.ownListings.query();
|
|
108
|
+
}).then(res => {
|
|
109
|
+
console.log(`You now have ${res.data.data.length} listings.`);
|
|
110
|
+
});
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
You can execute the script by running:
|
|
114
|
+
|
|
115
|
+
```
|
|
116
|
+
$ yarn run pg -c <CLIENT-ID> -u useremail@yourdomain.com -s user-secret-password --script create-listing.js
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
The output will look something like:
|
|
120
|
+
|
|
121
|
+
```
|
|
122
|
+
Initializing SDK instance with Client ID: <CLIENT-ID>...
|
|
123
|
+
Successfully connected to Saunatime marketplace.
|
|
124
|
+
Logging in user useremail@yourdomain.com...
|
|
125
|
+
Executing script...
|
|
126
|
+
|
|
127
|
+
> sdk.ownListings.query().then(res => {
|
|
128
|
+
... console.log(`You have ${res.data.data.length} listings.`);
|
|
129
|
+
... }).then(() => {
|
|
130
|
+
... console.log('Creating a new listing');
|
|
131
|
+
... return sdk.ownListings.create({
|
|
132
|
+
..... title: "My new listings",
|
|
133
|
+
..... description: "A shiny new listing",
|
|
134
|
+
..... geolocation: new LatLng(40.64542, -74.08508),
|
|
135
|
+
..... price: new Money(1590, "USD"),
|
|
136
|
+
..... publicData: {
|
|
137
|
+
....... category: 'Electric',
|
|
138
|
+
....... gears: 22
|
|
139
|
+
....... }
|
|
140
|
+
..... });
|
|
141
|
+
... }).then(res => {
|
|
142
|
+
... console.log(`Created a new listing with id ${res.data.data.id.uuid}`);
|
|
143
|
+
... return sdk.ownListings.query();
|
|
144
|
+
... }).then(res => {
|
|
145
|
+
... console.log(`You now have ${res.data.data.length} listings.`);
|
|
146
|
+
... });
|
|
147
|
+
|
|
148
|
+
> You have 10 listings.
|
|
149
|
+
Creating a new listing
|
|
150
|
+
Created a new listing with id 5e579343-0241-4d73-a50a-d8c5062feb86
|
|
151
|
+
You now have 11 listings.
|
|
152
|
+
```
|
|
153
|
+
|
package/docs/types.md
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Types
|
|
2
|
+
|
|
3
|
+
The SDK provides a set of types that complement the data types
|
|
4
|
+
JavaScript supports out-of-the box. When calling the API endpoints,
|
|
5
|
+
the SDK returns data using these types. It also expects these types
|
|
6
|
+
given as parameters for the *queries* and *commands*.
|
|
7
|
+
|
|
8
|
+
Here's a list of the provided types:
|
|
9
|
+
|
|
10
|
+
| Name | Description | Constructor | Properties |
|
|
11
|
+
| ---- | ----------- | ----------- | ---------- |
|
|
12
|
+
| `UUID` | [UUID](https://en.wikipedia.org/wiki/Universally_unique_identifier) | `new UUID(uuid)` | `uuid`<br /> |
|
|
13
|
+
| `Money` | Amount of money in certain currency | `new Money(amount: Number, currency: String)` | `amount` The amount in subunit.<br />`currency`<br /> |
|
|
14
|
+
| `LatLng` | Geolocation | `new LatLng(lat: Number, lng: Number)` | `lat`<br />`lng`<br /> |
|
|
15
|
+
| `LatLngBounds` | Bounding box limited by North-East and South-West corners | `new LatLngBounds(ne: LatLng, sw: LatLng)` | `ne`<br />`sw`<br /> |
|
|
16
|
+
| `BigDecimal` | Arbitrary precision decimal value | `new BigDecimal(value: String)` | `value` |
|
|
17
|
+
|
|
18
|
+
**Example:**
|
|
19
|
+
|
|
20
|
+
```js
|
|
21
|
+
const { Money } = require('sharetribe-flex-sdk').types;
|
|
22
|
+
|
|
23
|
+
const price = new Money(5000, 'USD');
|
|
24
|
+
|
|
25
|
+
console.log("Amount in subunit (i.e. cents): " + price.amount)
|
|
26
|
+
console.log("Currency: " + price.currency)
|
|
27
|
+
```
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Writing your own token store
|
|
2
|
+
|
|
3
|
+
The SDK ships with three built-in token store implementations: Browser
|
|
4
|
+
cookie store, Express cookie store and memory store. However, in some
|
|
5
|
+
cases you may need to write your own cookie store, for example, if you
|
|
6
|
+
want to save the cookie in some other location, such as
|
|
7
|
+
[LocalStorage](https://developer.mozilla.org/en-US/docs/Web/API/Storage/LocalStorage).
|
|
8
|
+
|
|
9
|
+
## Interface
|
|
10
|
+
|
|
11
|
+
The Token store interface has three methods. Any token store
|
|
12
|
+
implementation must implement all of them:
|
|
13
|
+
|
|
14
|
+
**`setToken(Object) : null | Promise(null)`**
|
|
15
|
+
|
|
16
|
+
Stores the new token. Returns either `null` or a `Promise`.
|
|
17
|
+
|
|
18
|
+
**`getToken() : Object | Promise(Object)`**
|
|
19
|
+
|
|
20
|
+
Reads the token from the store. Returns either a token or a Promise
|
|
21
|
+
holding the token as a value.
|
|
22
|
+
|
|
23
|
+
**`removeToken : null | Promise(null)`**
|
|
24
|
+
|
|
25
|
+
Removes the stored token. Returns either `null` or a Promise.
|
|
26
|
+
|
|
27
|
+
## Examples
|
|
28
|
+
|
|
29
|
+
See the built-in token store implementations.
|