onehilltech / blueprint Goto Github PK
View Code? Open in Web Editor NEWsolid framework for building APIs and backend services
solid framework for building APIs and backend services
The Blueprint messaging framework is built atop the node messaging framework. This frameworks executes its listeners synchronously. Unfortunately, this is not the intended behavior of the messaging framework because it can delay the emitter for extended periods of time if the listeners are not implemented correctly, or there are a large number of handlers for an event.
We need to update the framework so that all listeners execute in parallel, and the emitter has the option to either wait for all listeners, or continue without waiting. The latter approach will be the default, and extended behavior of the messaging framework.
The build works on the local development machine, but is failing on Travis CI.
This issue is to track the progress of integrating Alexa home into Blueprint. It will be a module that allows you to configure routes to handle commands from Alexa for the skill defined by your application.
Resource controllers could be made to emit an event whenever the underlying datastore has been modified, so that listeners can easily react to this change (via PUT, POST, DELETE, etc. but not GET HTTP methods).
Event data for create/update operations should include the updated or created document, while delete operations should include the deleted document.
The namespace of the event could be constructed like:
namespace = opts.prefix || 'resource' + '.' + collection_name + '.' + datastore_operation
...then, using blumate.messaging API, emit the event for consumption by listeners.
I'll go ahead and work up a PR if you're on board. Any suggestions or feedback would be great.
It would be great if we had a helper method in Blueprint.js to facilitate testing features that operate atop to messaging platform. Something like the following would be great:
blueprint.testing.waitFor (condition, interval, onComplete);
Add support for node cluster. This will allow a blueprint application to take advantages of the available cpus on a multi-core architecture.
It would be great if blueprint supported Swagger. Maybe a Blueprint.js module for Swagger (i.e., blueprint-swagger
). The Swagger specification could be integrated directly into the router definition, and the Blueprint.js Swagger module would auto-generate the definition.
Blueprint uses consolidate.js to integrate many view engines. There are scenarios where a view engine may not be supported by consolidate.js, and there is a need for a custom view engine. See isssue #29 for an example.
To address this problem, we need to support custom view engines in Blueprint. This custom view engines should be defined in app.config.js
.
This is a fake issue!
When loading a Blueprint.js server, I get an (extremely vague) error:
$ node ./app/index.js
info: configuration path: /home/bdfoster/Projects/fall2016-group1-apiserver/app/configs
info: configuration environment: development
/home/bdfoster/Projects/fall2016-group1-apiserver/node_modules/async/dist/async.js:985
if (fn === null) throw new Error("Callback was already called.");
^
Error: Callback was already called.
at /home/bdfoster/Projects/fall2016-group1-apiserver/node_modules/async/dist/async.js:985:32
at /home/bdfoster/Projects/fall2016-group1-apiserver/node_modules/@onehilltech/blueprint/lib/ApplicationModule.js:96:16
at PolicyManager.ResourceManager.load (/home/bdfoster/Projects/fall2016-group1-apiserver/node_modules/@onehilltech/blueprint/lib/ResourceManager.js:48:12)
at /home/bdfoster/Projects/fall2016-group1-apiserver/node_modules/@onehilltech/blueprint/lib/ApplicationModule.js:94:15
at nextTask (/home/bdfoster/Projects/fall2016-group1-apiserver/node_modules/async/dist/async.js:5208:14)
at /home/bdfoster/Projects/fall2016-group1-apiserver/node_modules/async/dist/async.js:5202:13
at apply (/home/bdfoster/Projects/fall2016-group1-apiserver/node_modules/async/dist/async.js:41:25)
at /home/bdfoster/Projects/fall2016-group1-apiserver/node_modules/async/dist/async.js:76:12
at /home/bdfoster/Projects/fall2016-group1-apiserver/node_modules/async/dist/async.js:988:16
at /home/bdfoster/Projects/fall2016-group1-apiserver/node_modules/@onehilltech/blueprint/lib/ApplicationModule.js:96:16
at /home/bdfoster/Projects/fall2016-group1-apiserver/node_modules/async/dist/async.js:484:16
at nextTask (/home/bdfoster/Projects/fall2016-group1-apiserver/node_modules/async/dist/async.js:5195:29)
at /home/bdfoster/Projects/fall2016-group1-apiserver/node_modules/async/dist/async.js:5202:13
at apply (/home/bdfoster/Projects/fall2016-group1-apiserver/node_modules/async/dist/async.js:41:25)
at /home/bdfoster/Projects/fall2016-group1-apiserver/node_modules/async/dist/async.js:76:12
at /home/bdfoster/Projects/fall2016-group1-apiserver/node_modules/async/dist/async.js:988:16
at /home/bdfoster/Projects/fall2016-group1-apiserver/node_modules/@onehilltech/blueprint/lib/ListenerManager.js:73:16
at /home/bdfoster/Projects/fall2016-group1-apiserver/node_modules/async/dist/async.js:484:16
at iteratorCallback (/home/bdfoster/Projects/fall2016-group1-apiserver/node_modules/async/dist/async.js:1084:13)
at /home/bdfoster/Projects/fall2016-group1-apiserver/node_modules/async/dist/async.js:988:16
at /home/bdfoster/Projects/fall2016-group1-apiserver/node_modules/async/dist/async.js:484:16
at nextTask (/home/bdfoster/Projects/fall2016-group1-apiserver/node_modules/async/dist/async.js:5195:29)
It leads me to believe that there's an issue with Blueprint.js itself, however I can't really confirm given the vague stack trace.
The code for this issue is living in https://github.com/CS450-ECE461/fall2016-group1-apiserver/tree/issue8. The issue occurred when updating from v0.48.1 to v1.1.1, and it was not occurring beforehand. In lib/ResourceController.js
, you will see a custom ResourceController
that is used in app/controllers/UserController.js
. Switching to using blueprint-mongodb
's ResourceController
has the same results.
NPM and Node.js versions:
$ npm -v
3.10.3
$ node -v
v6.7.0
For reference, here is my package tree:
$ npm list
[email protected] /home/bdfoster/Projects/fall2016-group1-apiserver
├─┬ @onehilltech/[email protected]
│ ├─┬ [email protected]
│ │ ├── [email protected]
│ │ ├── [email protected]
│ │ ├── [email protected]
│ │ ├─┬ [email protected]
│ │ │ ├── [email protected]
│ │ │ └── [email protected]
│ │ ├── [email protected]
│ │ ├─┬ [email protected]
│ │ │ └── [email protected]
│ │ ├─┬ [email protected]
│ │ │ └── [email protected]
│ │ └─┬ [email protected]
│ │ └── [email protected]
│ ├─┬ [email protected]
│ │ └── [email protected]
│ ├─┬ [email protected]
│ │ └── [email protected]
│ ├─┬ [email protected]
│ │ ├── [email protected]
│ │ └── [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ ├─┬ [email protected]
│ │ │ └── [email protected]
│ │ ├── [email protected]
│ │ ├── [email protected]
│ │ ├── [email protected]
│ │ ├── [email protected]
│ │ ├── [email protected]
│ │ ├── [email protected]
│ │ ├── [email protected]
│ │ ├── [email protected]
│ │ ├── [email protected]
│ │ ├── [email protected]
│ │ ├─┬ [email protected]
│ │ │ ├── [email protected]
│ │ │ └── [email protected]
│ │ ├── [email protected]
│ │ ├─┬ [email protected]
│ │ │ └── [email protected]
│ │ ├── [email protected]
│ │ ├── [email protected]
│ │ └── [email protected]
│ ├─┬ [email protected]
│ │ ├── [email protected]
│ │ ├── [email protected]
│ │ └─┬ [email protected]
│ │ ├── [email protected]
│ │ └── [email protected]
│ ├─┬ [email protected]
│ │ └── [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ ├── [email protected]
│ │ ├── [email protected]
│ │ ├── [email protected]
│ │ └─┬ [email protected]
│ │ └── [email protected]
│ ├─┬ [email protected]
│ │ └── [email protected]
│ ├─┬ [email protected]
│ │ ├── [email protected]
│ │ ├─┬ [email protected]
│ │ │ ├─┬ [email protected]
│ │ │ │ └── [email protected]
│ │ │ └─┬ [email protected]
│ │ │ └── [email protected]
│ │ ├─┬ [email protected]
│ │ │ ├─┬ [email protected]
│ │ │ │ └── [email protected]
│ │ │ └── [email protected]
│ │ ├── [email protected]
│ │ └── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ ├── [email protected]
│ │ └── [email protected]
│ ├─┬ [email protected]
│ │ ├─┬ [email protected]
│ │ │ ├─┬ [email protected]
│ │ │ │ ├── [email protected]
│ │ │ │ └─┬ [email protected]
│ │ │ │ └── [email protected]
│ │ │ ├── [email protected]
│ │ │ ├── [email protected]
│ │ │ ├── [email protected]
│ │ │ ├── [email protected]
│ │ │ ├── [email protected]
│ │ │ └─┬ [email protected]
│ │ │ └── [email protected]
│ │ ├─┬ [email protected]
│ │ │ ├─┬ [email protected]
│ │ │ │ └── [email protected]
│ │ │ ├─┬ [email protected]
│ │ │ │ └── [email protected]
│ │ │ └── [email protected]
│ │ ├─┬ [email protected]
│ │ │ ├─┬ [email protected]
│ │ │ │ └── [email protected]
│ │ │ └─┬ [email protected]
│ │ │ ├── [email protected]
│ │ │ └── [email protected]
│ │ ├── [email protected]
│ │ ├─┬ [email protected]
│ │ │ └── [email protected]
│ │ ├─┬ [email protected]
│ │ │ └── [email protected]
│ │ ├── [email protected]
│ │ └── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ └── [email protected]
├─┬ @onehilltech/[email protected]
│ └── @onehilltech/[email protected]
├── [email protected]
├── [email protected]
├─┬ [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ └── [email protected]
│ └── [email protected]
├─┬ [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ └─┬ [email protected]
│ └─┬ [email protected]
│ └─┬ [email protected]
│ └── [email protected]
├─┬ [email protected]
│ └─┬ [email protected]
│ └─┬ [email protected]
│ ├── [email protected]
│ └── [email protected]
├─┬ [email protected]
│ ├─┬ [email protected]
│ │ ├── [email protected]
│ │ ├── [email protected]
│ │ └─┬ [email protected]
│ │ └─┬ [email protected]
│ │ ├── [email protected]
│ │ └── [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ ├── [email protected]
│ │ ├─┬ [email protected]
│ │ │ └── [email protected]
│ │ ├─┬ [email protected]
│ │ │ └── [email protected]
│ │ └─┬ [email protected]
│ │ ├── [email protected]
│ │ ├── [email protected]
│ │ ├── [email protected]
│ │ └─┬ [email protected]
│ │ ├── [email protected]
│ │ ├─┬ [email protected]
│ │ │ ├─┬ [email protected]
│ │ │ │ └─┬ [email protected]
│ │ │ │ └── [email protected]
│ │ │ └── [email protected]
│ │ ├── [email protected]
│ │ └── [email protected]
│ ├─┬ [email protected]
│ │ ├─┬ [email protected]
│ │ │ └── [email protected]
│ │ ├── [email protected]
│ │ └── [email protected]
│ └─┬ [email protected]
│ └── [email protected]
├─┬ [email protected]
│ ├─┬ [email protected]
│ │ └── [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ └── [email protected]
│ ├─┬ [email protected]
│ │ ├── [email protected]
│ │ └── [email protected]
│ ├─┬ [email protected]
│ │ └─┬ [email protected]
│ │ ├── [email protected]
│ │ ├── [email protected]
│ │ └── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ └── [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ ├─┬ [email protected]
│ │ │ └── [email protected]
│ │ ├─┬ [email protected]
│ │ │ └── [email protected]
│ │ ├── [email protected]
│ │ └── [email protected]
│ ├─┬ [email protected]
│ │ ├─┬ [email protected]
│ │ │ └── [email protected]
│ │ └─┬ [email protected]
│ │ ├─┬ [email protected]
│ │ │ ├── [email protected]
│ │ │ └── [email protected]
│ │ └── [email protected]
│ ├─┬ [email protected]
│ │ ├── [email protected]
│ │ └── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ └── [email protected]
│ ├─┬ [email protected]
│ │ └── [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ └── [email protected]
│ ├─┬ [email protected]
│ │ └── [email protected]
│ ├─┬ [email protected]
│ │ └─┬ [email protected]
│ │ └── [email protected]
│ ├─┬ [email protected]
│ │ └─┬ [email protected]
│ │ ├── [email protected]
│ │ ├─┬ [email protected]
│ │ │ └── [email protected]
│ │ ├── [email protected]
│ │ └── [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ ├── [email protected]
│ │ ├── [email protected]
│ │ ├─┬ [email protected]
│ │ │ ├─┬ [email protected]
│ │ │ │ └─┬ [email protected]
│ │ │ │ ├─┬ [email protected]
│ │ │ │ │ └── [email protected]
│ │ │ │ ├── [email protected]
│ │ │ │ └── [email protected]
│ │ │ ├── [email protected]
│ │ │ └── [email protected]
│ │ ├─┬ [email protected]
│ │ │ └── [email protected]
│ │ ├── [email protected]
│ │ ├── [email protected]
│ │ ├── [email protected]
│ │ ├─┬ [email protected]
│ │ │ ├─┬ [email protected]
│ │ │ │ └── [email protected]
│ │ │ └── [email protected]
│ │ └─┬ [email protected]
│ │ ├── [email protected]
│ │ └── [email protected]
│ ├─┬ [email protected]
│ │ └── [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ └─┬ [email protected]
│ │ └── [email protected]
│ ├── [email protected]
│ └── [email protected]
├── [email protected]
├─┬ [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ ├── [email protected]
│ │ ├── [email protected]
│ │ ├─┬ [email protected]
│ │ │ ├── [email protected]
│ │ │ ├── [email protected]
│ │ │ ├── [email protected]
│ │ │ ├── [email protected]
│ │ │ ├── [email protected]
│ │ │ └── [email protected]
│ │ └── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ └─┬ [email protected]
│ │ └── [email protected]
│ ├─┬ [email protected]
│ │ └── [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ └── [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ └── [email protected]
│ ├─┬ [email protected]
│ │ └── [email protected]
│ └── [email protected]
├── [email protected]
├─┬ [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ └── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ └─┬ [email protected]
│ ├─┬ [email protected]
│ │ ├── [email protected]
│ │ └─┬ [email protected]
│ │ ├── [email protected]
│ │ ├── [email protected]
│ │ └── [email protected]
│ ├── [email protected]
│ └── [email protected]
├─┬ [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ ├── [email protected]
│ │ ├─┬ [email protected]
│ │ │ └─┬ [email protected]
│ │ │ └── [email protected]
│ │ └─┬ [email protected]
│ │ └── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ ├── [email protected]
│ │ └── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ └── [email protected]
├─┬ [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ └── [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ └── [email protected]
│ ├─┬ [email protected]
│ │ ├─┬ [email protected]
│ │ │ ├── [email protected]
│ │ │ ├─┬ [email protected]
│ │ │ │ └── [email protected]
│ │ │ └── [email protected]
│ │ └─┬ [email protected]
│ │ └── [email protected]
│ ├─┬ [email protected]
│ │ ├── [email protected]
│ │ ├── [email protected]
│ │ ├── [email protected]
│ │ └── [email protected]
│ ├─┬ [email protected]
│ │ ├── [email protected]
│ │ ├─┬ [email protected]
│ │ │ ├── [email protected]
│ │ │ ├── [email protected]
│ │ │ └── [email protected]
│ │ └─┬ [email protected]
│ │ ├── [email protected]
│ │ ├── [email protected]
│ │ ├── [email protected]
│ │ ├─┬ [email protected]
│ │ │ └── [email protected]
│ │ ├── [email protected]
│ │ ├─┬ [email protected]
│ │ │ └── [email protected]
│ │ ├── [email protected]
│ │ ├── [email protected]
│ │ └── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ └── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ └── [email protected]
├─┬ [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ └── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ └─┬ [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ └── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
└─┬ [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
└── [email protected]
The server configuration file only supports the http://
protocol. We need to enable support for the https://
protocol for secure communication with the server. The ideal method for enabling/configuring https://
support would be through server configuration file. Here is what the server configuration file may look like with https://
support enabled.
module.exports = exports = {
view_engine: 'jade', // this is optional (default=jade)
protocols : {
http : {
port : 8080 // Default port if not provided
},
https: {
port : 443, // Default port if not provided
options : {
// HTTPS module options
}
}
},
middleware : {
// Integrated middleware (e.g., express-session, passport, morgan, etc.)
custom : [
// Custom middleware implemented by application
]
}
};
Determine if is feasible to support node-coap as a protocol in blueprint.
npm install generated a xpression-init folder in blueprint/templates/ instead of the blueprint-init folder
There needs to be a way to seed the database when the application starts. This would be very useful when testing Blueprint applications.
The validation
property on the object returned from a controller method is assumed to be a function. There are times when the validation is to only use a schema from express-validator. Unfortunately, to do some requires writing the same one-liner function. It would be nice to either provide a validation function or schema to the validate
property. Something like this:
MyController.prototype.someMethod = function () {
return {
validate: {
// add validation schema here
}
}
In the last code snippet on the "Define the Controller Action" there's a typo.
HelloWorldController.prototype.deleteNames = function () {
return function (req, res) {
// reset the array of names
names = [];
// redirect to /helloworld so we can enter more names
res.redirect ('/helloword');
};
};
The res.redirect ('/helloword');
line should be res.redirect ('/helloworld');
.
Partial views (such as with handlebars) do not seem to be supported, but is a key element in the DRY (don't repeat yourself) principle. Is there a directory (or a way to configure a directory) where partial views can be imported into a parent view?
On that same line of thinking, is there a directory (...) where layouts can be created/specified in a view?
It would be awesome to integrate Socket.io for sending events to and from clients. I currently have it working in the following way:
var io = null;
blueprint.messaging.on('app.init', function (app) {
io = require ('socket.io')(app.server._protocols[0]._protocol);
});
I started the server node ./app
, server already running, but if i access http://localhost:8080/ has some error like on title
The goal of this is to integrate into Blueprint.js a messaging module. The messaging module allows Blueprint.js framework and controllers to send messages that correspond to different events. The web application can then register for these events. The objects that register for the events will be called listeners
.
The listeners
will reside in:
/app/listeners
The way we will register the listeners is based on directory naming. The name of the directory in the listeners directory will be the event of interest. For example, the directory
/app/listeners/app.init
corresponds to the app.init
event.
Each JavaScript file in the event directory will contain a single listener that is to be registered with the messaging service.
One can use the Policy.Definition
in the validate
property of a controller action. The current design, however, requires you to write a separate function to integrate Policy.Definition
. For example:
return {
validate: function (req, callback) {
Policy.Definition (['policy1', 'policy2']).evaluate (req, callback);
}
}
Instead of have writing a separate function to integrate the policies, the definition should adapt the list of policies to assignable directly to the validate
property:
return {
validate: Policy.Definition (['policy1', 'policy2'])
}
how to connect my blueprint app to mysql using sequelize
The initial creation of an app with blueprint seems to be expecting a "models" folder to exist, which is not necessarily created from blueprint-init. The error is coming from fs.js:856 when it is trying to read the directory (which is being called from the blueprint Application.js:59:9). This is bring thrown when I try to do a "node ./app" to start the application.
The current approach for integrating blueprint modules adds an additional complexity to the application. This is because you must ensure app/modules.js
coyntains modules that actually appear in package.json
. There can easily be a case where these two files become unsynchronized, such as manually editing the files.
Instead of using app/modules.js
, would should be able to auto-detect a module from package.json
. We can do this with the following design decisions:
blueprint-module
as a tag in package.json
.dependencies
section in package.json
.This approach will remove the unwanted overhead of needing to managing module definitions in multiple locations.
Add first
and last
methods to the resource controller. This will improve a client's ability to determine if their local cache is outdated.
The blueprint dependency generated by running the init template is incorrect. It references the repo directly. Instead, if should reference the version number of blueprint.
There are times when a controller will only export a single action. We should be able to use shorthand its integration with a router by only specifying the controller name. If there is no method in the action property, then it is assumed that the router is binding to a well-defined method.
This method should be named __invoke
.
It would be nice to integrate Validate.js (possibly by module), as a way to validate requests. This could be the basis of a "request model", making the use of Mongoose in blueprint-mongodb optional.
The ResourceController
supports queries on GET /resource
path. This is good for simple queries, such as:
Requests on GET /resource
path are not good for complex queries, such as:
This is because it is not easy to express complex queries via a URL query string. We therefore need to provide a improved mechanism that allows the client to execute complex queries. We will call this capability search
.
The search capability should have the following key features:
v4 will be a major update to the code base. It is expected to break existing code bases, and we will not provide support for backwards compatibility. The list below is a list of features we plan on putting in v4. As we work on the update, expect this list to change.
blueprint.
to built-in message typesIt would be nice to install all the dependencies of an new application when it is created. Otherwise, users have to run the same commands after creating the application before it can be used.
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.