getconversio / node-bigcommerce Goto Github PK
View Code? Open in Web Editor NEWA node module for authentication and use with the BigCommerce API
License: MIT License
A node module for authentication and use with the BigCommerce API
License: MIT License
The documentation shows verify method as a Promise, i.e. bigCommerce.verify(...).then()
However, the verify
method seems to synchronously return the data object itself, rather than a Promise. Is this a mistake in the documentation?
Hi, looking for some advice..
So I have created an app for BigCommerce. In the BigCommerce app I have the auth callback configured so that it calls my backend
`
export async function oauth(event, context, callback) {
bigCommerce.authorize(JSON.stringify(event.queryStringParameters))
.then(data => {
console.log('Authorized! ' + JSON.stringify(data));
callback(null, {
statusCode: 302,
headers: {
Location: '<some path in my app>',
},
})
}).catch(error => {
callback(null, failure(error));
});
}
`
when I authorize I get something like the following back fro bigcommerce {"context":"stores/xxxx","code":"gpkof3rxxxxxxxwqjkv77dffq7w","scope":"store_v2_default"}
So I assume I do something like this:
have I got this correct ? thanks
Add response body to error object on JSON.parse fail, would aid in debugging. Pull request incoming.
Allow gzip/deflate encoding, as the BigCommerce API allows this (at least in V3), and some larger requests get limited to 8mb responses if they aren't encoded. Pull request incoming
Allow use of an https agent, keep-alive would reduce socket usage in a high volume environment. Pull request incoming.
Hi, BigCommerce provides different types of authentication nowadays. While going through the library I couldn't see an SSO integration basically which generates a single sign-in URL. Source
While going through the official library I saw there are methods to achieve it. It's a small piece of code easy to plugin. But at the same time I didn't see any implementation of SSO in this library. Have I missed it or the implementation is missing?
Sample code from Official Library
/**
* @param int $id
* @param string $redirectUrl
* @param string $requestIp
* @return string
*/
public static function getCustomerLoginToken($id, $redirectUrl = '', $requestIp = '')
{
if (empty(self::$client_secret)) {
throw new Exception('Cannot sign customer login tokens without a client secret');
}
$payload = array(
'iss' => self::$client_id,
'iat' => time(),
'jti' => bin2hex(random_bytes(32)),
'operation' => 'customer_login',
'store_hash' => self::$store_hash,
'customer_id' => $id
);
if (!empty($redirectUrl)) {
$payload['redirect_to'] = $redirectUrl;
}
if (!empty($requestIp)) {
$payload['request_ip'] = $requestIp;
}
return JWT::encode($payload, self::$client_secret, 'HS256');
}
missing adding the agent to the request options for the auth request
async authorize(query) {
if (!query) throw new Error('The URL query paramaters are required.');
const payload = {
client_id: this.config.clientId,
client_secret: this.config.secret,
redirect_uri: this.config.callback,
grant_type: 'authorization_code',
code: query.code,
scope: query.scope,
context: query.context
};
const request = new Request('login.bigcommerce.com', {
failOnLimitReached: this.config.failOnLimitReached
});
return await request.run('post', '/oauth2/token', payload);
}
should be
async authorize(query) {
if (!query) throw new Error('The URL query paramaters are required.');
const payload = {
client_id: this.config.clientId,
client_secret: this.config.secret,
redirect_uri: this.config.callback,
grant_type: 'authorization_code',
code: query.code,
scope: query.scope,
context: query.context
};
const request = new Request('login.bigcommerce.com', {
failOnLimitReached: this.config.failOnLimitReached,
agent: this.config.agent
});
return await request.run('post', '/oauth2/token', payload);
}
Hi everyone, could you please advise on how to PUT to update a product's metadata?
Specifically I'm trying to update ShipperHQ metadata. I can get the existing metadata fields this way:
await bigCommerce.get(
"/products/24751",
);
And that gives me:
Got existing metadata = { data:
[ { id: 18352,
key: 'shipping-groups',
value: '["foo"]',
namespace: 'shipping.shipperhq',
permission_set: 'write',
resource_type: 'product',
resource_id: 24751,
description: 'ShipperHQ shipping group rules associated with this product/sku',
date_created: '2018-11-07T16:03:40+00:00',
date_modified: '2018-11-07T16:03:40+00:00' },
{ id: 18353,
key: 'shipping-origins',
value: '["baz"]',
namespace: 'shipping.shipperhq',
permission_set: 'write',
resource_type: 'product',
resource_id: 24751,
description: 'ShipperHQ shipping origins associated with this product/sku',
date_created: '2018-11-07T16:03:40+00:00',
date_modified: '2018-11-07T16:03:40+00:00' } ],
But when I try to write metadata using a PUT, BigCommerce complains:
product.metadata = [{
namespace: "shipping.shipperhq",
key: "shipping-groups",
value: '["update1"]',
}]
const productUpdateRes = await bigCommerce.put(
"/products/24769",
product
);
"The supplied namespace
shipping.shipperhq is invalid."
I have tried every possible variation of "shipping", "global", "shipping-groups", etc for the namespace. Nothing seems to work.
Any ideas?
So I've been getting a nasty error anytime I hit something other than a 200. I've seen this similar stacktrace when I hit a 401 and 404 as well as 500.
{ Error: Request returned error code: 500 and body:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Error</title>
<link rel="shortcut icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAlFJREFUeNqUU8tOFEEUPVVdNV3dPe8xYRBnjGhmBgKjKzCIiQvBoIaNbly5Z+PSv3Aj7DSiP2B0rwkLGVdGgxITSCRIJGSMEQWZR3eVt5sEFBgTb/dN1yvnnHtPNTPG4PqdHgCMXnPRSZrpSuH8vUJu4DE4rYHDGAZDX62BZttHqTiIayM3gGiXQsgYLEvATaqxU+dy1U13YXapXptpNHY8iwn8KyIAzm1KBdtRZWErpI5lEWTXp5Z/vHpZ3/wyKKwYGGOdAYwR0EZwoezTYApBEIObyELl/aE1/83cp40Pt5mxqCKrE4Ck+mVWKKcI5tA8BLEhRBKJLjez6a7MLq7XZtp+yyOawwCBtkiBVZDKzRk4NN7NQBMYPHiZDFhXY+p9ff7F961vVcnl4R5I2ykJ5XFN7Ab7Gc61VoipNBKF+PDyztu5lfrSLT/wIwCxq0CAGtXHZTzqR2jtwQiXONma6hHpj9sLT7YaPxfTXuZdBGA02Wi7FS48YiTfj+i2NhqtdhP5RC8mh2/Op7y0v6eAcWVLFT8D7kWX5S9mepp+C450MV6aWL1cGnvkxbwHtLW2B9AOkLeUd9KEDuh9fl/7CEj7YH5g+3r/lWfF9In7tPz6T4IIwBJOr1SJyIGQMZQbsh5P9uBq5VJtqHh2mo49pdw5WFoEwKWqWHacaWOjQXWGcifKo6vj5RGS6zykI587XeUIQDqJSmAp+lE4qt19W5P9o8+Lma5DcjsC8JiT607lMVkdqQ0Vyh3lHhmh52tfNy78ajXv0rgYzv8nfwswANuk+7sD/Q0aAAAAAElFTkSuQmCC">
<style>
html, body, pre {
margin: 0;
padding: 0;
font-family: Monaco, 'Lucida Console', monospace;
background: #ECECEC;
}
h1 {
margin: 0;
background: #A31012;
padding: 20px 45px;
color: #fff;
text-shadow: 1px 1px 1px rgba(0,0,0,.3);
border-bottom: 1px solid #690000;
font-size: 28px;
}
p#detail {
margin: 0;
padding: 15px 45px;
background: #F5A0A0;
border-top: 4px solid #D36D6D;
color: #730000;
text-shadow: 1px 1px 1px rgba(255,255,255,.3);
font-size: 14px;
border-bottom: 1px solid #BA7A7A;
}
</style>
</head>
<body>
<h1>Oops, an error occurred</h1>
<p id="detail">
This exception has been logged with id <strong>75kime1lk</strong>.
</p>
</body>
</html>
at IncomingMessage.<anonymous> ([scrubbed for privacy reasons]/node-bigcommerce/lib/request.js:103:21)
at emitNone (events.js:91:20)
at IncomingMessage.emit (events.js:185:7)
at endReadableNT (_stream_readable.js:974:12)
at _combinedTickCallback (internal/process/next_tick.js:80:11)
at process._tickDomainCallback [as _tickCallback] (internal/process/next_tick.js:128:9) code: 500 }
{ Error: Request returned error code: 404 and body: [{"status":404,"message":"The requested resource was not found."}]
at IncomingMessage.<anonymous> ([scrubbed for privacy reasons]/node-bigcommerce/lib/request.js:103:21)
at emitNone (events.js:91:20)
at IncomingMessage.emit (events.js:185:7)
at endReadableNT (_stream_readable.js:974:12)
at _combinedTickCallback (internal/process/next_tick.js:80:11)
at process._tickDomainCallback [as _tickCallback] (internal/process/next_tick.js:128:9) code: 404 }
Any idea what I can do to make sure this doesn't happen? I'm using the git version to the best of my knowledge as my package json reads
"node-bigcommerce": "git://github.com/getconversio/node-bigcommerce.git",
Hi, I am trying to get my stores current theme but this does not seem to be working:
var BigCommerce = require('node-bigcommerce');
var bigCommerce = new BigCommerce({
clientId: 'clientId',
storeHash: 'hash',
accessToken: 'token',
responseType: 'json'
});
bigCommerce.get('/themes', function(err, data, response){
console.log(data)
});
I am getting this error
(node:64686) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: Request returned error code: 404 and body: The route is not found, check the URL
Hi,
All my errors come in gzipped, is there a way to handle this without an external package?
My config is using apiVersion:3.
For the tutorial for creating the BigCommerce App, there is a function call verifyJWT. However, I cannot find that from the class here
https://developer.bigcommerce.com/docs/ZG9jOjE4MjIyODMy-step-2-connect-your-app-to-big-commerce
I tried to replace verify with verifyJWT on the tutorial that doesn't work. Is that such a function that we can use?
A copy of the code from the tutorial: https://github.com/bigcommerce/sample-app-nodejs/blob/step-3-add-database/lib/auth.ts
Screenshot
When querying customer attribute with name:in it gives 422 error
{
"errors": {},
"status": 422,
"title": "The filter(s): name:in are not valid filter parameter(s).",
"type": "https://developer.bigcommerce.com/api-docs/getting-started/api-status-codes"
}
Tested via https://developer.bigcommerce.com/api-reference/store-management/customers-v3/customer-attributes/customersattributesget and node-bigcommerce
Strangely name:like is working
Today the lib does not support calls to customer apis, right?
like GET https://api.bigcommerce.com/stores/{store_hash}/v3/customers
I have the following block of code to allow me to install the webhooks onto a client store.
var config = require('../config');
var BigCommerce = require('node-bigcommerce');
var _ = require("lodash");
var async = require("async");
var install_webhooks = function(req,data,next){
req.bigCom = new BigCommerce({
"logLevel":"info",
"clientId": config.bigcom_config.clientId,
"accessToken":data.bigcom_token,
"storeHash": data.bigcom_hash.split("/")[1],
"responseType":"json"
});
var webhook_settings = {
"scope":"store/order/created",
"destination":config.bigcom_config.callback+"/new_orders",
"is_active":true,
};
async.waterfall([
function(next){
console.log(JSON.stringify(webhook_settings,null,2));
req.bigCom.post('/hooks',webhook_settings,function(err,data,response){
next(err,data,response);
})
},
function(data,response,next){
console.log(data);
console.log(response);
next();
}
],function(err){
next(err);
});
}
My results are as follows...
Installing Webhooks
{
"scope": "store/order/created",
"destination": "https://09c18e00.ngrok.io/new_orders",
"is_active": true
}
Info: Requesting Data from: https://api.bigcommerce.com/stores/vbo4xq/v2/hooks.json Using the post method
Info: Starting Request, with options: { hostname: 'api.bigcommerce.com',
path: '/stores/{hash}/v2/hooks.json',
method: 'POST',
port: 443,
headers:
{ 'User-Agent': 'node-bigcommerce/2.1.0',
'Content-Type': 'application/json',
'X-Auth-Client': 'correct clientId',
'X-Auth-Token': 'correct auth token',
'Content-Length': 101 } }
Info: Sending Data: {"scope":"store/order/created","destination":"https://09c18e00.ngrok.io/new_orders","is_active":true}
Info: Status Returned: 404
Info: Headers Returned: {"server":"nginx","date":"Tue, 17 Jan 2017 20:37:17 GMT","content-type":"application/json; charset=utf-8","content-length":"66","connection":"keep-alive","x-bc-stapler":"1","cache-control":"no-cache","x-bc-store-version":"7.6.0","x-newrelic-app-data":"PxQDVV5bARABUFJaAQcEREgTYVYAMhEDXhFZAUxRW1xvSmwTWD0cCwpSUhlIE1BDEkhRTAcBB1ZUHQYdUlVbUwROFVMUGlEBV11YUAhVUFFSVQ8EB1saH1YFDRFSbA==","x-bc-apilimit-remaining":"20000"}
Info: Request complete
Error: Request failed with code: 404 and body: [{"status":404,"message":"The requested resource was not found."}]
{ [Error: Request failed with code: 404 and body: [{"status":404,"message":"The requested resource was not found."}]] code: 404 }
I've also found that removing the .json extension causes it to work, but commenting it out completely makes the system return XML which is not what I'm looking to use at this time (unless I have no other choice)
Any help to make it better would be nice. Thank you for your time.
As mentioned here: #11 it could be cool to add 'authorize' function names as a lot of libraries are doing that and some developers are used to this sort of naming :)
I haven't had a lot of experience in using node and BigCommerce together and this is really my first time trying. I've been stuck on a problem for several days now and was wondering if I could get some support here. I have a NodeJS deployed on Amazon's AWS EB, at the moment when I try to install my draft App on BigCommerce, it gets stuck in the installation and the progress indicator stays indefinitely.
At the moment my config looks like:
const bigCommerce = new BigCommerce({
logLevel: "info",
clientId: "my id",
secret: "my secret",
callback: "hostname",
responseType: "json",
apiVersion: "v3" // Default is v2
});
and the code I'm using for auth, load, uninstall:
const app = express();
const router = express.Router();
router.get("/auth", (req, res, next) => {
bigCommerce
.authorize(req.query)
.then(data => res.render("auth", { title: "Authorized!", data: data }))
.catch(next);
});
router.get("/load", (req, res, next) => {
try {
const data = bigCommerce.verify(req.query["signed_payload"]);
res.render("load", { title: "Welcome!", data: data });
} catch (err) {
next(err);
}
});
router.get("/uninstall", (req, res, next) => {
try {
const data = bigCommerce.verify(req.query["signed_payload"]);
res.render("uninstall", { title: "Uninstalled!", data: data });
} catch (err) {
next(err);
}
});
app.use(router);
I've also tried using regular app.get('/', cb) as well, nothing.
Also I've seen the following get returned in data by auth:
{ title: "Authorized!", data: "<html><body>You are being <a href="https://login.bigcommerce.com/login">redirected</a>.</body></html>" }
I'm not quite sure how to approach this, and there isn't too much documentation on working with node and BC together =( If I could get some advice or perhaps pointed to the direction of where I might be able to get some it'd be greatly appreciated!
Thanks!
Catalog API is now at V3, which is backwards compatible, but enables new features. Addressed by #18.
Wondering if this works for the storefront api V3. Specifically Add-To-Cart, Cart, and Order API.
In generic request errors (such as timeout), the library fails if used with promises, as the callback function is not supplied:
Error: Error: socket hang up
/Users/rfink/code/node-bigcommerce/lib/request.js:156
return cb(e);
^
TypeError: cb is not a function
at ClientRequest. (/Users/rfink/code/node-bigcommerce/lib/request.js:156:12)
at emitOne (events.js:115:13)
at ClientRequest.emit (events.js:210:7)
at TLSSocket.socketCloseListener (_http_client.js:377:9)
at emitOne (events.js:120:20)
at TLSSocket.emit (events.js:210:7)
at _handle.close (net.js:549:12)
at TCP.done [as _onclose] (_tls_wrap.js:350:7)
Pull request incoming
Thank you in advance! I am struggling here.
Can you please provide complete instructions on how my users can authenticate and receive their token. There are scattered instructions between your readme and the BigCommerce docs but the exact process with nodejs is very cryptic. Any help on this is appreciated.
Adding .on('error') handler for https requests, as socket hang ups can crash an app. Pull request incoming.
I just tried to use the example for /products get products api. However, it doesn't work without the store hash. I am working on server-to-server call. I don't know what needs to be done.
Get request error: the access token and store hash are required to call the BigCommerce API
Hello,
This isn't an issue but a feature request.
It would be great if node-bigcommerce could have an option to save the access object to a mongodb db. This is the only thing I am missing and I am struggling to get this working with my app.
Great module :)
Many thanks
Is it possible to make integration with Nestjs, and if is, is there any guide on how to do it?
I am implementing a a Big Commerce (BC) app which will be a single page app created from React.js. There will be no backend/node.js server but rather multiple serverless api gateway endpoints that will be called from the react.js app.
correct me if I am wrong on the way things should work in terms of authentiation with my app:
I am trying to use the /catalog/products/{product_id}/metafields
endpoint to fetch metafields for the product. This product whose id
I used exists, it has a metafields and the store api credentials are valid. But I keep getting this response.
Why is this so and how to get around this problem?
I have also tried /products/{product_id}/metafields
as the get request endpoint.
The code I am trying.
const bigCommerce = new BigCommerce({
storeHash: 'xxxxxxxx',
clientId: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
accessToken: 'xxxxxxxxxxxxxxxxxxxxxxxxxxx',
responseType: 'json',
});
module.exports = {
fetchProductMetafields: productId => {
return bigCommerce.get(`/catalog/products/${productId}/metafields`)
.then(metafields => {
return metafields;
});
}
}
Am I doing something wrong?
If the API responds with a 4xx or 5xx code, it's next to impossible to get the response body, because it's swallowed here:
node-bigcommerce/lib/request.js
Line 112 in 1ac28d8
The only way would be to parse it from the Error's message, which would be very ugly.
In my app my customers will need to login as if they were on the bc store. I am able to verify that the provided email and password are correct. I cant find a method to exchange the user_id and my app credentials for a token that can be used in sso (described here)
I used the python sdk before and the part I want to do now in nodejs is the following
bc_client = b.api.BigcommerceApi(client_id, store_hash, access_token)
login_token = sdk.customer_login_token.create(bc_client, customer.id)
I dont have a problem to report. I just need help.
The following is what my app looks like now.
const BigCommerce = require('node-bigcommerce');
const bigCommerce = new BigCommerce({
logLevel: 'info',
clientId: 'from app creation',
secret: 'from app creation',
callback: 'http://localhost:3200/auth',
responseType: 'json',
apiVersion: 'v3',
accessToken: 'from an api account created in bc store admin',
storeHash: 'ziq4j28bpo'
});
router.get("/auth", (req, res, next) => {
bigCommerce
.authorize(req.query)
.then(data => res.render("auth", { title: "Authorized!", data: data }))
.catch(next);
});
What can I do now to get the token? I am trying GET http://localhost:3200/api/auth
but that returns a message "you are being redirected to"... It must be obvious to most but I cant figure out how to use the authorize function. Please Help!
Is there a way to just do Basic Auth with this, or is this OAuth only? I am new to this so forgive my ignorance, but I am trying to test this using a get request:
`var BigCommerce = require('node-bigcommerce');
var bigCommerce = new BigCommerce({
clientId: '128ecf542a35ac5270a87dc740918404'
accessToken: '9df3b01c60df20d13843841ff0d4482c',
responseType: 'json'
});
bigCommerce.get('/products', function(err, data, response){
// Catch any errors, or handle the data returned
// The response object is passed back for convenience
});`
However I am getting an error saying I need the store hash
Do you no why my error responses from BigCommerce are not readable?
"error": "Error: Request returned error code: 422 and body: \u001f�\b\u0000\u0000\u0000\u0000\u0000\u0000\u00004�»\u000eÂ0\fEÅ\nk\u001fRÅÔ����\u001f\b�i-µq°ÝJ¨ê¿�\n\u0018,ÝáÜ{¼95o�ºþÜu�3²\t]ïn¤Ji\u0000\u0016 \u0014X\u0004��àk!Á\bOÂ)ª+ø;\u001fôh�µoÛ�+N�Q�\u0007\r�ç\u0019%`SBë3�ÊÕ_Y\u001d8âÑG\u0011�âÞÜê�|²2v\u001fI!\u000bÇ¥(G¯ÀÙ��Vðcàz��ü¿qûþ\u0001\u0000\u0000ÿÿ\u0003\u0000ÿ\u001byÇÅ\u0000\u0000\u0000"
No default engine was specified and no extension was provided.what should i do
Hello!
Are you going to add promise support in foreseeable future?
I would also suggest adding support to usage of work 'authorize' to 'authorise'. I'm used to using 'authorize', though both variants are possible :)
After adding a product to my cart like this:
function addToCart(req){
return new Promise(
(resolve, reject) => {
bigCommerce.post('/carts', {
"line_items": [
{
"quantity": req.body.amount,
"product_id": req.body.id,
"variant_id": req.body.variant_id
}
]
})
.then(data => {
resolve(data)
})
.catch(err => reject(err))
});
}
app.post('/:route/:productName/add-to-cart', (req, res) => {
const contentType = req.get('Content-Type')
addToCart(req)
.then( data => {
req.session.cartId = data['data'].id
if(contentType === 'text/plain') {
res.render('checkout', data)
}
if(contentType === 'application/json') {
res.json(data)
}
})
.catch(err => console.error(err))
})
I try to remove the product like this:
function deleteFromCart(req){
return new Promise(
(resolve, reject) => {
bigCommerce.delete(`/carts/${req.session.cartId}/items/${req.body.id}`)
.then(data => {
resolve(data)
})
.catch(err => reject(err))
});
}
app.post('/update-cart', (req, res) => {
const contentType = req.get('Content-Type')
deleteFromCart(req)
.then( data => {
if(contentType === 'text/plain') {
res.render('checkout', data)
}
if(contentType === 'application/json') {
res.json(data)
}
})
.catch(err => console.error(err))
})
When trying this with the same product, data will return the same quantity of 1 which was added in the addToCart function. I've tried swapping it with put
and setting the quantity
to 0 without success.
Am I missing something?
Hi,
I would like to know why I am getting the response as
<html><body>You are being <a href="https://login.bigcommerce.com/login">redirected</a>.</body></html>
when I should have got an example data object as mentioned in the documentation.
Here is my code snippet.
var app = express();
BigCommerce = require('node-bigcommerce');
const bigCommerce = new BigCommerce({
logLevel: 'info',
clientId: '(Removed for obvious reasons)',
secret: '(Removed for obvious reasons)',
callback: 'https://priyanamdtest.mybigcommerce.com',
responseType: 'json',
apiVersion: 'v3'
});
app.get('/auth', function(req, res, next) {
bigCommerce
.authorize(req.query)
.then(data => res.write(data))
.catch(next);
});
var port = process.env.PORT || 8080;
app.listen(port);
module.exports = app;
Hi,
Following the docs, we have put together the following snippet which fails with a 401 and the error message of "X-Auth-Client and X-Auth-Token headers are required":
import BigCommerce from 'node-bigcommerce'
...
const bigCommerce = new BigCommerce({
clientId: 'xyz',
accessToken: 'abc',
storeHash: 'some_shop',
responseType: 'json',
apiVersion: 'v3'
})
bigCommerce.get('/catalog/products')
.then(data => {
console.log('data')
})
However, using Postman with the same properties does return the data that is expected.
We are testing the JavaScript in a localhost
application using Chrome dev tools.
Any ideas as to what may be causing the issue? I believe it may be a CORS issue but I am not certain.
I am having trouble generating a jwt token that can be used to sign my users in. My attempt is explained below.
Any help?
I tested PR #80 and this fixes the gibberish when receiving errors.
Is it possible to merge this?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.