bug-hunters / oas3-tools Goto Github PK
View Code? Open in Web Editor NEWThis project forked from apigee-127/swagger-tools
A Node.js and browser module that provides tooling around Swagger.
License: MIT License
This project forked from apigee-127/swagger-tools
A Node.js and browser module that provides tooling around Swagger.
License: MIT License
Custom Error Handler option is not persent
I tried to migrate from swagger 2 to oas3 using oas3-tools 2.2.2 and the security features are still a problem.
I can add the bearer stuff for JWT tokens and select methods to need mandatory such tockens. The UI then denies access if no token is delivered. But how is the content of the JWT ever validated? I can just enter dummy stuff and get accesss to that function back. Not the way I expected this to work.
// swaggerRouter configuration
var options = {
routing: {
controllers: path.join(__dirname, './controllers')
},
logging: {
format: 'combined',
errorLimit: 400
},
openApiValidator: {
validateSecurity: true,
validateRequests: true,
validateResponses: false
}
};
If I just set validateSecurity to true this doesn't check the inner values of the JWT at all it seems.
Now if I try to add a function of my own to this:
validateSecurity:
{
handlers: {
bearerauth: auth.verifyToken
}
},
The function I wrote checks the JWT token like it should and either returns false (access gets denied as it should), or it returns just true -> Access is still denied by
{
"message": "unauthorized",
"errors": [
{
"path": "/v1/test",
"message": "unauthorized"
}
]
}
Has the user provided auth.verifyToken function any changed pattern? Not returning boolean but anything else now?
When running the PetStore example i found that the POST route was not working. In the router, the req.openapi.swaggerParameters were not present, because in the swaggerParameters, the line:
if (!req.openapi || !req.openapi.schema || !req.openapi.schema.parameters) {
next();
return;
}
prevents swaggerParameters from being added if the method (POST in this case) does not define any parameters. I think this is a bug because it obligates the definition of parameters on all methods, in contradiction with the openAPI specification.
I used the editor at https://editor.swagger.io/ to generate code.
It included code from this library, which embeds a static copy of swagger-ui.
When I use the "Try it out" button, there is no place to enter a request body.
I've used the swagger-ui repo before, it offers a place to enter a request body with some of it pre-typed.
Perhaps swagger-ui could be included as a dependency instead of statically embedding it.
Hi bug hunters,
Thanks for fixing the issues with version 2.1.2. I can now successfully start the auto-generated node js stubs from swagger hub again.
Unfortunately there now seems to be a new error which I am having problems to fix.
I am usign the following specification on SwaggerHub to generate a node js server stub:
info:
version: 1.0.0
title: oas3-issue-minimal-sample
description: ''
servers:
# Added by API Auto Mocking Plugin
- description: Localhost Test Server
url: 'http://localhost:8080/1.1.0'
paths:
/measurement:
post:
summary: Endpoint that receives MetriX measurements
operationId: receive
responses:
'200':
description: Successful Operation
'400':
description: Invalid Request
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/Measurement'
description: A JSON object which contains the measurement
required: true
components:
schemas:
Measurement:
type: object
properties:
Id:
type: string
description: 'A simple field.'
When starting up the server with the oas3-tools 2.1.3, the server is not able to handle incoming messages. Instead it sends back
{
"message": "Route defined in OpenAPI specification (/1.1.0/measurement) but there is no defined onPOST operation."
}
to the client.
When downgrading to oas3-tools 2.0.2, everything works fine and the server responds with HTTP 200. Currently, version 2.0.2 is defined as the minimum requirement for auto-generated server stubs.
I would be happy if you could explain what is wrong with my specification.
Best,
Peter
3.0.2 is not supported in 1.0.2-RC2. See https://unpkg.com/browse/[email protected]/lib/helpers.js (line 163).
I'm unable to get my JWT validation function to execute.
I've tried both this:
var options = { oasSecurity: true, securityFile: { Bearer: verifyToken }, routing: { controllers: path.join(__dirname, './controllers'), } };
and this:
var options = { oasSecurity: true, routing: { securityFile: { Bearer: verifyToken }, controllers: path.join(__dirname, './controllers'), } };
Is this a known issue or am I missing something here? The routing is working fine otherwise but I've been trying everything I can think of and I just can't get the security authorization working.
Release 2.1.2 is totally broken. Check the code. It looks like the person publishing this forgot to build before upload to npm. Only the TS files were uploaded, but none of the JS files in dist/
. The package now is totally unusable because the dist/index.js
is missing.
Also the version makes little sense to me. The last version before was 2.0.2
so the next "feature"-version should be 2.1.0
not 2.1.2
.
The build
step should be added as a prepublish
or prepublishOnly
step. Also the TS files should not be uploaded anymore and therefore removed from the files
entry in the package.json
.
Line 35 in 03b5848
Missing support for OpenAPI 3.0.2
Thanks :)
Removal of the addValidator
function is a major, non-backwards-compatible, change to the API.
According to the rules of semantic versioning, this kind of change requires a major version update.
So I discovered this a few days ago when I attempted to auto-generate a NodeJS server from a swagger definition.
This is what I found:
/Users/marc.deniverville/Downloads/nodejs-server-server-generated/index.js:15
expressAppConfig.addValidator();
^
TypeError: expressAppConfig.addValidator is not a function
at Object.<anonymous> (/Users/marc.deniverville/Downloads/nodejs-server-server-generated/index.js:15:18)
at Module._compile (internal/modules/cjs/loader.js:778:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:789:10)
at Module.load (internal/modules/cjs/loader.js:653:32)
at tryModuleLoad (internal/modules/cjs/loader.js:593:12)
at Function.Module._load (internal/modules/cjs/loader.js:585:3)
at Function.Module.runMain (internal/modules/cjs/loader.js:831:12)
at startup (internal/bootstrap/node.js:283:19)
at bootstrapNodeJSCore (internal/bootstrap/node.js:623:3)
The auto-generated package.json file makes this reference to oas3-tools: "oas3-tools": "^2.0.2"
, accepting patch and minor point upgrades.
Steps to reproduce:
Note1: the API explorer from editor.swagger.io is working CORRECTLY. It's the nodejs server stub not working.
Note2: It seems the swagger-ui bundled with the oas3-tools NPM is pretty outdated. I tried to replace the swagger-ui files in oas3-tools, and it worked pretty well: the request body is visible.
Example yaml to show the error:
openapi: 3.0.1
info:
title: Demo error
version: 1.0.0
servers:
url: /demo
paths:
/test:
post:
operationId: testPOST
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/my_req_body'
required: true
responses:
200:
description: Success
x-swagger-router-controller: Default
components:
schemas:
my_req_body:
properties:
code:
type: string
message:
type: string
Validating the response value does not work as expected, the schema is not read from responses.[code].content.[media type].schema
. Leading to the following error:
swagger-tools:middleware:validator Response validation: +2ms
swagger-tools:middleware:validator Response code: 200 +0ms
swagger-tools:middleware:validator Validation: failed +1ms
swagger-tools:middleware:validator Reason: Value at index 0 is not a valid void: [object Object] +0ms
swagger-tools:middleware:validator Stack: +8ms
swagger-tools:middleware:validator at throwErrorWithCode (oas3-tools/lib/validators.js:116:13) +0ms
swagger-tools:middleware:validator at oas3-tools/lib/validators.js:489:9 +0ms
swagger-tools:middleware:validator at arrayEach (lodash/lodash.js:516:11) +0ms
swagger-tools:middleware:validator at Function.forEach (lodash/lodash.js:9344:14) +0ms
swagger-tools:middleware:validator at validateTypeAndFormat (oas3-tools/lib/validators.js:487:7) +0ms
swagger-tools:middleware:validator at Object.module.exports.validateSchemaConstraints (oas3-tools/lib/validators.js:643:7) +0ms
swagger-tools:middleware:validator at validateValue (oas3-tools/middleware/swagger-validator.js:130:16) +0ms
swagger-tools:middleware:validator at ServerResponse.res.end (oas3-tools/middleware/swagger-validator.js:302:9) +0ms
swagger-tools:middleware:validator at exports.listPets (snip/controllers/pets.ts:5:7) +0ms
swagger-tools:middleware:validator at swaggerRouter (oas3-tools/middleware/swagger-router.js:388:20) +0ms
connect:dispatcher <anonymous> : /pets +11ms
I used the following spec, but I had to add to update the version to 3.0.1 or nothing happened (the server never started), and add the x-swagger-router-controller
.
'use strict';
var path = require('path');
var http = require('http');
var oas3Tools = require('oas3-tools');
var serverPort = 8088;
// swaggerRouter configuration
var options = {
routing: {
controllers: path.join(__dirname, './controllers')
},
logging: {
format: 'combined',
errorLimit: 400
},
};
var expressAppConfig = oas3Tools.expressAppConfig(path.join(__dirname, 'api/openapi.yaml'), options);
var app = expressAppConfig.getApp();
const r = app.use((req, res, next) => {
console.log(req);
next();
});
// Initialize the Swagger middleware
http.createServer(app).listen(serverPort, function () {
console.log('Your server is listening on port %d (http://localhost:%d)', serverPort, serverPort);
console.log('Swagger-ui is available on http://localhost:%d/docs', serverPort);
});
This is the original generated code and an additional middleware for testing. using the routes never goes into the middleware
The problem is that the OAS 3.0.x specification moved the securityDefinitions
member of the req.swagger.swaggerObject
to req.swagger.swaggerObject.components.securitySchemas
but it seems like the code in swagger-security.js
was not updated to reflect this.
Just curious how this is still a lingering issue, does anyone else use security in their OAS projects?
Here is the fix to go in place of swagger-security.js:138-140
var secDef;
if (req.swagger.swaggerVersion < "2.0") {
// Swagger pre 2.0
secDef = req.swagger.resourceListing.authorizations[name];
} else if (req.swagger.swaggerVersion < "3.0") {
// Swagger 2.0 up to OAS 3.0
secDef = req.swagger.swaggerObject.securityDefinitions[name];
} else {
// OAS 3.0+
secDef = req.swagger.swaggerObject.components.securitySchemes[name];
}
[request entity too large error when using oas3-tools package,openapi 3.0 in node.js]
index.js file
'use strict';
var path = require('path');
var http = require('http');
var cors = require('cors');
var oas3Tools = require('oas3-tools');
require("dotenv").config({ path: ".env" });
console.log(`### Running on ~~~ ${process.env.Instance} ~~~ ENV ###`);
var serverPort = 8080;
function validate(request, scopes, schema) {
// security stuff here
return true;
}
// swaggerRouter configuration
var options = {
routing: {
controllers: path.join(__dirname, './controllers')
},
logging: {
format: 'combined',
errorLimit: 400
},
};
var expressAppConfig = oas3Tools.expressAppConfig(
path.join(__dirname, "./api/openapi.yaml"),
options
);
expressAppConfig.addValidator();
var app = expressAppConfig.getApp();
app.use(cors());
var json2xls = require('json2xls');
app.use(json2xls.middleware);
// Initialize the Swagger middleware
http.createServer(app).listen(serverPort, function () {
});
// Connect to database
var mongo = require("./utils/db");
----------------------------------------EOF----------------------------------------------
PFB the version of the tools which we've used. "express": "^4.17.1", "oas3-tools": "2.1.3"
I've tried body-parser and app.use(express.json({limit:'25mb'})). But nothing resolved the request entity too large error. It would be great if anyone suggest me any different solution.
Do you plan on submitting a pull request to the original repo?
hi i'm unable to make working the security of a JWT, i follow the syntax that i found for oas-tools but it's not working:
var options = {
controllers: path.join(__dirname, './controllers'),
oasSecurity: true,
securityFile: {
Bearer: verifyToken
},
or
securityFile: { Bearer: { issuer: 'ISA Auth', algorithms: ['HS256'], key: 'Secret' }
How can i overcome this issue? Thanks
When using Swagger Editor to build the NodeJS Server from a YAML structure, the Swagger UI and localhost:3000/api-docs works, no other endpoints are working, including the root. All of these return 404 errors with message :
localhost:3000/ "Cannot GET /"
localhost:3000/user?name=value "Cannot GET /user"
localhost:3000/api/v1/user?name=value "Cannot GET /api/v1/user"
My YAML Servers look like this:
servers:
- url: http://localhost:3000/api/v1
description: REST API Localhost
- url: https://stg.example.com:3000/api/v1
description: REST API Staging
- url: https://prd.example.com:3000/api/v1
description: REST API Production
The "/api/v1/user" endpoint is configured like this:
/user:
get:
tags:
- user
summary: Get user by Username, E-Mail, or ID.
description: Get User data by the Users Unique Username, E-Mail, or ID. /user?user={ username | email | id }
operationId: getUser
parameters:
- name: user
in: query
description: The user that needs to be fectched.
required: true
schema:
type: string
responses:
200:
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/User'
application/xml:
schema:
$ref: '#/components/schemas/User'
text/plain:
schema:
$ref: '#/components/schemas/User'
400:
description: Invalid username supplied
content:
application/json:
schema:
type: string
application/xml:
schema:
type: string
text/plain:
schema:
type: string
404:
description: User not found
content:
application/json:
schema:
type: string
application/xml:
schema:
type: string
text/plain:
schema:
type: string
default:
description: OK
content:
application/json:
schema:
type: string
application/xml:
schema:
type: string
text/plain:
schema:
type: string
x-swagger-router-controller: user
I don't know if the upcoming 2.0.0 release will change this, but as for 1.0.1, a bad request correctly returns a 400 status, but with HTML content, with no details about what was wrong in the request.
It would be nice to have a JSON response instead, with details about the wrong request
Console shows deprecation of body-parser:
body-parser deprecated undefined extended: provide extended option node_modules\oas3-tools\dist\middleware\express.app.config.js:22:33
Why to use both body-parser
and express parsers
?
oas3-tools/src/middleware/express.app.config.ts
Lines 30 to 32 in 9349490
and then again
oas3-tools/src/middleware/express.app.config.ts
Lines 35 to 36 in 9349490
Express can do the job on his own:
https://expressjs.com/fr/api.html#express.urlencoded
https://expressjs.com/fr/api.html#express.json
https://expressjs.com/fr/api.html#express.text
I would like to fiddle around with the app object to add middleware to be called before the swagger stuff.
But as the express app object is created within the oas3 module I could only add at the end of the process queue which will not work.
How can I either define my own app object and feed it to the oas3 middleware constructor or add some definition to get to this goal?
PS: I would also try to just fork the module but nodejs module handling is all new to me, so that is too much work for the moment. I cannot even rebuild the unchanged module by now. A how-to-hack this module doc would be great too.
Hello,
I am struggling to add CORS support to my app running on swagger server. I tried using swagger-express-middleware but that dint do the trick. Looks like they are not yet supporting openapi 3.0 specs.
Need some pointers please.
I have a middleware code as shown in the example:
'use strict';
var path = require('path');
var http = require('http');
var oas3Tools = require('oas3-tools');
var serverPort = 8080;
const createMiddleware = require('@apidevtools/swagger-express-middleware');
// swaggerRouter configuration
var options = {
controllers: path.join(__dirname, './controllers')
};
var expressAppConfig = oas3Tools.expressAppConfig(path.join(__dirname, 'api/openapi.yaml'), options);
expressAppConfig.addValidator();
var app = expressAppConfig.getApp();
createMiddleware( __dirname + '/api/openapi.yaml', app, function(err, middleware) {
app.use(
middleware.metadata(),
middleware.CORS(),
middleware.files(),
middleware.parseRequest(),
middleware.validateRequest(),
middleware.mock()
);
// Show the CORS headers as HTML
app.use(function(req, res, next) {
res.send('<pre>' + util.inspect(res._headers) + '</pre>');
});
app.listen(8080, function() {
console.log('Go to http://localhost:8080/docs');
});
});
My curl call is resulting in a 405 error.
curl -I -v http://localhost:8080/v2/url/my_test_alias
* Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 8080 (#0)
> HEAD /v2/url/ali_test_alias HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.54.0
> Accept: */*
>
< HTTP/1.1 405 Method Not Allowed
HTTP/1.1 405 Method Not Allowed
< X-Powered-By: Express
X-Powered-By: Express
< Content-Type: application/json; charset=utf-8
Content-Type: application/json; charset=utf-8
< Content-Length: 118
Content-Length: 118
< ETag: W/"76-HftMGD7rVmxkEyOoP10+GyQtLQY"
ETag: W/"76-HftMGD7rVmxkEyOoP10+GyQtLQY"
< Date: Sat, 28 Mar 2020 00:52:39 GMT
Date: Sat, 28 Mar 2020 00:52:39 GMT
< Connection: keep-alive
Connection: keep-alive
<
I am sure I am doing something wrong. Appreciate any pointers.
When adding oas3-tools into an application of "type":"module"
(package.json), import xxxx from '/xxxx.js'
syntax (instead of require) is not enabled in "controllers" files.
So to be able to use regular "import" syntax, one should use file extensions .cjs or .mjs which is not accepted by hereunder line:
accepted files are limited ! maybe put it in options?
The custom routes are not longer working with the latest update
'use strict';
var path = require('path');
var http = require('http');
var oas3Tools = require('oas3-tools');
var serverPort = 8080;
// swaggerRouter configuration
var options = {
routing: {
controllers: path.join(__dirname, './controllers')
},
};
var expressAppConfig = oas3Tools.expressAppConfig(path.join(__dirname, 'api/openapi.yaml'), options);
var app = expressAppConfig.getApp();
/** THIS CUSTOM ROUTE IS NOT LONGER ACCESSIBLE **/
app.get('/foo', (req, res) => { res.send('foo')})
// Initialize the Swagger middleware
http.createServer(app).listen(serverPort, function () {
console.log('Your server is listening on port %d (http://localhost:%d)', serverPort, serverPort);
console.log('Swagger-ui is available on http://localhost:%d/docs', serverPort);
});
Hi Bug Hunters,
I'm using oas3-tools indirectly as a npm module when I'm generating a nodejs server with the Swagger UI, and it seems that the middleware
folder isn't getting copied and compiled over to the dist
folder.
Steps to recreate:
Edit > Convert to YAML
Edit > Convert to Open API 2
Generate Server > nodejs-server
npm start
which will build and try to run the server which will bonk on this particular error mentioned.Here's the Stackoverflow question for more context:
Currently, in SwaggerRouter, if req.openapi
is undefined, then operation
is undefined and the if (operation)
check falls through to its else
, which returns send405()
However, there are two normal cases where the validator may not have set req.openapi
-- if the path should be explicitly ignored, and if it does not fall within the baseURL. In addition, if req.openapi
is undefined, send405()
is just going to throw an exception anyway when it tries to access the .openApiRoute
property on it.
Wouldn't it be more correct to check for an undefined req.openapi
early, and return next(rErr)
?
Any chance to get example for using the package in typescript environment?
Now an old version has been published and there is no way to install the latest version from npm.
Hi.
I am trying to validate my API responses, but no matter what is send as a response, there is no indication of an error.
Steps to reproduce:
git clone [email protected]:bug-hunters/oas3-tools.git
cd oas3-tools
npm install
npm run build
cd examples/petstore
npm install
diff --git a/examples/petstore/example.js b/examples/petstore/example.js
index d33681d..f4d0fcd 100644
--- a/examples/petstore/example.js
+++ b/examples/petstore/example.js
@@ -21,6 +21,7 @@ var options = {
errorLimit: 400
},
openApiValidator: {
+ validateResponses: true,
validateSecurity: {
handlers: {
diff --git a/examples/petstore/services/PetService.js b/examples/petstore/services/PetService.js
index fc835a3..0874c0d 100644
--- a/examples/petstore/services/PetService.js
+++ b/examples/petstore/services/PetService.js
@@ -62,7 +62,7 @@ exports.getPetById = function(petId) {
var examples = {};
examples['application/json'] = {
'photoUrls' : [ 'photoUrls', 'photoUrls' ],
- 'name' : 'doggie',
'id' : 0,
'category' : {
'name' : 'name',
npm start
curl localhost:8080/pet/0 -H api_key:test
{
"photoUrls": [
"photoUrls",
"photoUrls"
],
"id": 0,
"category": {
"name": "name",
"id": 6
},
"tags": [
{
"name": "name",
"id": 1
},
{
"name": "name",
"id": 1
}
],
"status": "available"
}
I would expect to receive an error in this case.
Using the express-openapi-validator
directly instead works:
const express = require('express');
const path = require('path');
const bodyParser = require('body-parser');
const http = require('http');
const PetService = require('./services/PetService');
const OpenApiValidator = require('express-openapi-validator');
const port = 8080;
const app = express();
const apiSpec = path.join(__dirname, 'api/petstore.yaml');
// 1. Install bodyParsers for the request types your API will support
app.use(express.urlencoded({ extended: false }));
app.use(express.text());
app.use(express.json());
// Optionally serve the API spec
app.use('/spec', express.static(apiSpec));
// 2. Install the OpenApiValidator on your express app
app.use(
OpenApiValidator.middleware({
apiSpec,
validateResponses: true, // default false
}),
);
// 3. Add routes
app.get('/pet/:petId', async (req, res, next) => {
const body = await PetService.getPetById(req.params.petId + 0);
res.send(body);
});
http.createServer(app).listen(port);
console.log(`Listening on port ${port}`);
$ node serve.js
Listening on port 8080
Internal Server Error: .response should have required property 'name'
at ResponseValidator._validate (/home/claudio/github/oas3-tools/examples/petstore/node_modules/express-openapi-validator/dist/middlewares/openapi.response.validator.js:154:19)
at /home/claudio/github/oas3-tools/examples/petstore/node_modules/express-openapi-validator/dist/middlewares/openapi.response.validator.js:42:33
at ServerResponse.json_hook (/home/claudio/github/oas3-tools/examples/petstore/node_modules/express-openapi-validator/dist/framework/modded.express.mung.js:35:24)
at ServerResponse.send (/home/claudio/github/oas3-tools/examples/petstore/node_modules/express/lib/response.js:158:21)
at /home/claudio/github/oas3-tools/examples/petstore/serve.js:31:9
at processTicksAndRejections (internal/process/task_queues.js:95:5)
Consider the following openapi doc:
openapi: 3.0.3
info:
title: Parameter ReferenceObject
description: test
version: '1'
termsOfService: https://www.google.be
contact:
email: [email protected]
security:
- basicAuth: []
servers:
- url: http://localhost
description: local host
paths:
/subject:
get:
summary: Test
operationId: doTest
parameters:
- in: query
name: firstParam
schema:
type: string
- $ref: "#/components/parameters/FromDateTime"
- in: query
name: secondParam
schema:
$ref: "/components/schemas/SecondParam"
responses:
... (abbreviated for clarity)
components:
schemas:
SecondParam:
type: string
parameters:
FromDateTime:
in: query
name: fromDateTime
required: false
schema:
type: string
When parsing this, the controller will have both parameters (firstParam and fromDateTime), however if at runtime values are provided for fromDateTime
they are not sent to the corresponding controller file.
The controller function 'doTest' will have 6 variables: req, res, next, firstParam, fromDateTime, secondParam
GET /subject?firstParam=test&fromDateTime=2022-01-01
If a value is provided for 'secondParam', the controller will have that value in 'fromDateTime' and not in 'secondParam' at runtime.
GET /subject?fromDateTime=2022-01-01&secondParam=testing
controller function 'doTest' variables:
Of course I'd like the proper parameters to receive the proper value
Getting this error in my browser:
Could not find component JsonSchema_undefined swagger-ui-bundle.js:23508
Just FYI. I don't know if it has anything to do with #2
bodyParser expects the extended option to be passed on its urlencoded method, and it casts an error at startup :
body-parser deprecated undefined extended: provide extended option at node_modules/oas3-tools/dist/middleware/express.app.config.js:22:33
the call to bodyParser.urlencoded() is hardcoded in express.app.config.js so there is no other way to fix it than modifying the package file directly, preventing any further update !
Can you please fix this ?
It seems there is no CI setup.
https://github.com/bug-hunters/oas3-tools/blob/master/.travis.yml
In absence of maintenance and response I created a patch package on npmjs: https://www.npmjs.com/package/oas3-tools-cors
There are many tagged releases missing:
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.