Code Monkey home page Code Monkey logo

mers's Introduction

#Mers *_Mongoose *_Express *_Rest *_Service

Mers is a plugin for express to expose mongoose finders as simple crud/rest operations.  The
basic idea being you should just define your model/finders and the rest should be be magic.

build status

Usage

Install mers, mongoose, express and body-parser

  $ npm install express --save
  $ npm install mongoose --save
  $ npm install body-parser --save
  $ npm install mers --save
    //You really need body parser for things to work correctly
     var express = require('express'),
        mongoose = require('mongoose'),
        Schema = mongoose.Schema,
        bodyParser = require('body-parser')

    app.use(bodyParser.json())
    app.use(bodyParser.urlencoded({ extended: true }));
    var SampleSchema = new Schema({
        name:String,
        age:Number
    });

    mongoose.model('sample', SampleSchema);
    var mers = require('mers');
    app.use('/rest', mers({uri:'mongodb://localhost/your_db'}).rest());

Configuration options include:

  • uri:uri://mongoose (as shown above)
  • mongoose:{mongoose} (your mongoose instance)
  • error:{function} (your custom Error Handler)
  • responseStream:{function} (your custom respost stream. See: lib/streams.js)
  • transformer:{function} (your custom transformer factory)

inject:{Nojector} (custom nojector add resovlers, or whatever)

###If you had a schema such as

var mongoose = require('mongoose'), Schema = mongoose.Schema,
 ObjectId = mongoose.Schema.ObjectId;

var CommentSchema = new Schema({
 title:String, body:String, date:Date
});


var BlogPostSchema = new Schema({
 author:ObjectId,
 title:String,
 body:String,
 buf:Buffer,
 date:Date,
 comments:[CommentSchema],
 meta:{
     votes:Number, favs:Number
 }
});
/**
* Note this must return a query object.   If it doesn't well, I dunno what it'll do.
* @param q
* @param term
*/
BlogPostSchema.statics.findTitleLike = function findTitleLike(q, term) {
 return this.find({'title':new RegExp(q.title || term.shift() || '', 'i')});
}
var Comment = module.exports.Comment = mongoose.model('Comment', CommentSchema);
var BlogPost = module.exports.BlogPost = mongoose.model('BlogPost', BlogPostSchema);

you could then access it at listing.

http://localhost:3000/rest/blogpost/
http://localhost:3000/rest/blogpost/$id
http://localhost:3000/rest/blogpost/$id/comments
http://localhost:3000/rest/blogpost/$id/comments/$id
http://localhost:3000/rest/blogpost/$id/comments/0
http://localhost:3000/rest/blogpost/finder/findTitleLike/term

###Pagination Pagination is also supported via skip= and limit= query params.

http://localhost:3000/rest/blogpost/$id?skip=10&limit=10

###Population Mongoose populate is supported, but this will be changing shortly to allow for more fine grained controll over population. Currently you can do

http://localhost:3000/rest/blogpost?populate=comments

or to specify particular fields.

http://localhost:3000/rest/blogpost?skip=10&populate[comments]=title,date

###Filter Filtering is available for strings. To find all the blog posts with C in the title.

http://localhost:3000/rest/blogpost?filter[title]=C

Also you can and or nor the filters by using + (and) - (nor) or nothing or http://localhost:3000/rest/blogpost?filter[-title]=C http://localhost:3000/rest/blogpost?filter[+title]=C&filter[-body]=A

To filter all String fields that have a C in them

http://localhost:3000/rest/blogpost?filter=C

###Sorting Sorting is supported 1 ascending -1 ascending.

http://localhost:3000/rest/blogpost?sort=title:1,date:-1

###Transformer Transformers can be registered on startup. A simple TransformerFactory is included. If the function returns a promise, it will resolve the transformer asynchronously. The transformers follow the same injection rules.

To transform asynchronously just return a promise from your function. You can chain transformers. Transformers can also inject, but the first argument should be the object you want to transform.

app.use('/rest', require('mers').rest({
    mongoose:mongoose,
    transformers:{
           renameid: function(obj){
                obj.id = obj._id;
                delete obj._id;
                //don't forget to return the object.  Null will filter it from the results.
                return obj;
           },
           /**
            Injects the user into the function, and checks if the
            owner is the same as the current user.  Works with passport.
           */
           checkUser:function(obj, session$user){
              if (obj.owner_id !== session$user._id){
                //returning null, short circuits the other transformers. And will
                //not be included in the response.
                return null;
              }else{
               return obj;
              }

           },
           /**
             Uses injection and async resolution.
           */
           async:function(obj, query$doIt){
             if (query$doIt){
                var p = promise();
                setTimeout(function(){
                    obj.doneIt =true;
                    //Mpromise resolve.  Should work with other promises, or any object with a then function.
                    p.resolve(null, obj);
                },50);
                return p;
             }else{
             return obj;
             }

           }
      }
    }));
}

to get results transformered just add

 http://localhost:3000/rest/blogpost?transform=renameid

It handles get/put/post/delete I'll add some docs on that some day, but pretty much as you expect, or I expect anyways. see tests/routes-mocha.js for examples.

###Static Finders It should also be able to be used with Class finders. Now handles class finders. Note: They must return a query object. They are passed the query object and the rest of the url. All of the populate's, filters, transforms should work.

/**
 * Note this must return a query object.
 * @param q
 * @param term
 */
BlogPostSchema.statics.findTitleLike = function findTitleLike(q, term) {
    return this.find({'title':new RegExp(q.title || term.shift(), 'i')});
}

So you can get the url

http://localhost:3000/rest/blogpost/finder/findTitleLike?title=term

or

http://localhost:3000/rest/blogpost/finder/findTitleLike/term

Promises with finders

Occassionally you may want to do something like a double query within a finder. Mers has got your back.

      BlogPostSchema.statics.findByCallback = function onFindByCallback(query$id) {
          return this.find({_id: query$id}).exec();
      }

Error Handling

To create a custom error handler

   app.use('/rest', rest({
         error : function(err, req, res, next){
               res.send({
                   status:1,
                   error:err && err.message
               });
           }).rest());

Custom ResultStream

You can create your own result stream. It needs to subclass Stream and be writable. This can allow for other formats, and preventing the wrapping of data in the payload.

##Method You can invoke a method on a model. This useful to expose more complicated things that can't just be filtered. Of course you can return nested nestings too...

###Returning an Object This one just returns an object, from /department/$id/hello/name

DepartmentSchema.methods.hello = function DepartmentSchema$hello(){
    return {name:'hello '+this.name};
}

###Returning a Promise. This is returns a promise from /department/$id/promises. Really you just need to return an object with an then function. So any promise library should work.

DepartmentSchema.methods.promises = function (data){
    var p = promise();
    setTimeout(p.resolve.bind(p, null, {name:'hello '+this.name}), 100);
    return p;
}

Returning a Query object.

This is returns a query from /department/$id/superDo

DepartmentSchema.methods.superDo = function DepartmentSchema$hello(data){
   return Department.find({
       _id:this._id
   });
}

##Examples. An example of a customized rest service can be found at

https://github.com/jspears/backbone-directory

##Parameter injection When invoking a method you often need data from the request to process. To do this we have an injection system. You can inject a method on a model, or a transformer.

It resolves the prefix of the parameter name deliminated by $ to the scope. See nojector for more information there. The built in resolvers are session, param, query, body, args, require

url: http://localhost/rest/department/finders/byName?name=Stuff
DepartmentSchema.static.byName = function DepartmentSchema$hello(query$name){
   return Department.find({
        name:query$name
       });
}

works on instances to...

url: http://localhost/rest/department/$id/hello/?name=STuff
DepartmentSchema.method.hello = function DepartmentSchema$hello(query$name, session$user){
    //session.user === session$user
   return Department.find({
        name:query$name
       });
       
}

Delete

Deleting is follows the rules of as a put, however, it has an option, of deleteRef, when you are deleteing a nested ref'd object and want to delete it from the refer'd collection. see routes-user-mocha.js

mers's People

Contributors

0xbadc0ffee avatar adamsullovey avatar cchoong avatar jspears avatar oori avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mers's Issues

POST to /rest/model returns validation error with required

Having a UserSchema like:

UserSchema = new Schema({
    username:{type:String, required:true, unique:true, index:true}
});

and posting to /rest/user with
Content-Type: application/json
and stringified body

{"username":"Richard"}

results in a Object {payload: Array[0], status: 0, error: Object}

with e.g.

  • message: "Validator "required" failed for path username"
  • name: "ValidatorError"
  • path: "username"
  • type: "required"

Default query transformer?

Is there a way for me to specify a default transformer that will always be applied? I don't want people to be seeing passwords for example.

Validation errors on PUT cause crash

I'm using version 0.7.1-0, though I can see the same problem will probably occur with the master branch.

Basically, I put a data change through that I know will not pass validations, MERS will bail out and crash the server.

Looking near line 145 of lib/routes.js -
When the mongoose schema validations or pre save hooks return an err but no ret, the attempt to run ret.toJSON() will fail.

I believe the second part of the obj.save callback should be wrapped in an else statement, as we should only be trying to respond with the object if there is no error. If you agree, I will raise a pull request for this change.

I'm not yet sure why this doesn't happen for POST (it doesn't seem to hit the identical looking code in the router.post(reGet, ... callback

pos undefined
error saving  { message: 'Validation failed',
  name: 'ValidationError',
  errors:
   { type:
      { message: 'Validator "enum" failed for path type with value `blargh`',
        name: 'ValidatorError',
        path: 'type',
        type: 'enum',
        value: 'blargh' } } } ValidationError: Validator "enum" failed for path type with value `blargh`
    at model.Document.invalidate (/Users/cchoong/jobtend-api/node_modules/mongoose/lib/document.js:979:32)
    at /Users/cchoong/jobtend-api/node_modules/mongoose/lib/document.js:948:16
    at validate (/Users/cchoong/jobtend-api/node_modules/mongoose/lib/schematype.js:558:7)
    at /Users/cchoong/jobtend-api/node_modules/mongoose/lib/schematype.js:574:9
    at Array.forEach (native)
    at SchemaString.SchemaType.doValidate (/Users/cchoong/jobtend-api/node_modules/mongoose/lib/schematype.js:562:19)
    at /Users/cchoong/jobtend-api/node_modules/mongoose/lib/document.js:946:9
    at process._tickCallback (node.js:415:13)
127.0.0.1 - - [Mon, 25 Nov 2013 14:23:34 GMT] "PUT /rest/user/529352c7e94222833d000001 HTTP/1.1" 200 51 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.57 Safari/537.36"

/Users/cchoong/jobtend-api/node_modules/mongoose/lib/utils.js:419
        throw err;
              ^
TypeError: Cannot call method 'toJSON' of undefined
    at /Users/cchoong/jobtend-api/node_modules/mers/lib/routes.js:145:31
    at handleError (/Users/cchoong/jobtend-api/node_modules/mongoose/node_modules/hooks/hooks.js:92:18)
    at _next (/Users/cchoong/jobtend-api/node_modules/mongoose/node_modules/hooks/hooks.js:34:22)
    at fnWrapper (/Users/cchoong/jobtend-api/node_modules/mongoose/node_modules/hooks/hooks.js:159:8)
    at complete (/Users/cchoong/jobtend-api/node_modules/mongoose/lib/document.js:964:5)
    at /Users/cchoong/jobtend-api/node_modules/mongoose/lib/document.js:955:20
    at validate (/Users/cchoong/jobtend-api/node_modules/mongoose/lib/schematype.js:556:18)
    at /Users/cchoong/jobtend-api/node_modules/mongoose/lib/schematype.js:571:11
    at Promise.<anonymous> (/Users/cchoong/jobtend-api/node_modules/mongoose-unique-validator/index.js:34:9)
    at Promise.<anonymous> (/Users/cchoong/jobtend-api/node_modules/mongoose/node_modules/mpromise/lib/promise.js:162:8)

Auth Question

Justin, question for you.

I'm trying to build a simple auth system so that I can validate that someone is logged in or has some permissions before using the REST API. My initial thinking was to use the middleware approach to inject a function before the rest() middleware to check for auth. So...

app.use('/rest', function(req, res, next) {
  if ( ! loggedIn ) {
    res.redirect('/login_bitch');
  } else {
    next();
  }
});
app.use('/rest', rest({'mongoose':mongoose}).rest() ); 

First, can you think of a more sensible way to do this? And second, the issue I'm have is that the first piece of middleware is never called. If I remove mers then it runs but it's like mers overwrites it somehow. Any help is much appreciated.

Custom ResultStream issue

When I am trying to add new method to Schema

DepartmentSchema.methods.superDo = function DepartmentSchema$hello(data){
return Department.find({
_id:this._id
});
}

getting such error

{"status":1,"error":"Cast to ObjectId failed for value "superDo" at path "_id""}

URL is -> /department//superDo

When I am trying to do for instance like this

/department/550ad5972aa071895a364180/superDo

Works perfect

Restify?

Does mers work with restify as well?

If not, does it rely heavily on express only functionality?

How do you use transformers ?

I tried

app.use('/api/v1', mers({uri:'mongodb://localhost/database'}).rest({
    mongoose:mongoose,
    transformers: {
        renameid: function (obj) {
            obj.id = obj._id;
            delete obj._id;
            return obj;
        }
    }
}));

but i always getting the error "could not find transformer for renameid", how do I register a transformer ?

Fang

Filter by ObjectIds

Hello,

I have a collection where the documents are matched against a user_id. So my document looks something like this:

{
    "duration": "00:20",
    "name": "Samplename",
    "user_id": { "$oid" : "51d299b48e8ab7da3a000003" },
    "__v": 0,
    "_id": { "$oid" : "51d29c79579343a63b000003" }
}

Is there an easy way of just fetching documents where the user_id matches when I GET the documents? Filter doesn't work because you are using a RegEx which will not work with ObjectId fields.

Filter with $gt or $lt

For example, I'd like to select items within a date range. Is this currently possible?

POST, PUT, PATCH,DELETE methods ?

Is mers handling POST, PUT, PATCH, DELETE methods ?

I set mongoose in debug mode, and when sending a PUT request, nothing at all happens.

NPM version not latest

Commit 71c3f21 fixed a error in routes.js line 67 from an install from NPM. NPM also has version 0.9.3 while master is 0.9.2 Perhaps the version in NPM need to be updated?

Running the example

Any chance of providing some installation instructions. I've git "cloned" the project to my pc. I change to the example directory but the package.json doesn't appear to contain the dependencies I need so I started to npm install mers. Then try to run node server.js, it complains it needs mongoose. I npm install mongoose. Try to run node server.js again, it complains that it needs underscore. I npm install underscore. Try to run node server.js again, but it still complains that it needs underscore, and yet its listed in the node_modules directory. Not sure what else to try now. Can you advise please?

default transformer?

Don't see any facility to define a default transformer on a resource - ie; one that does not require passing transform=transformer_name in the url.

Let me know if I'm just not looking hard enough at the docs/code.

Otherwise, I would be happy to implement and raise a pull request for it.

MissingSchemaError instead of 404

Hi,

I tried mers in my project: app.use('/rest', mers({..}).rest())

...But when I visit /rest/none where none is an unknown schema, I get error:

   500 MissingSchemaError: Schema hasn't been registered for model "undefined". Use mongoose.model(name, schema)

It's strange to see 500 here, because "non-existant" has the code of 404.

app.del deprecated

Hey there, just flagging this for you that Express 4 deprecated app.del in favor of app.delete.
Just gives me an annoying warning message, otherwise still works.

express: app.del: Use app.delete instead

I'd submit a pull request but figured you probably want to maintain compatibility. Thoughts?

Populate Nested refernces

I was digging in the code and it appears that the ?populate feature will only work on top level documents. For example I have a Collection that contains 2 levels of nesting I'm not sure if I'm missing the way to populate nested values.

My Schema looks like the following

var CaseSchema = new Schema({
Plaintiff: {type: String },
Recipients: [RecipientSchema]
});

var RecipientSchema = new Schema({
service:{ type: ObjectId, ref: 'service' } ,
assignedId: {type: ObjectId},
Documents: [DocumentSchema],
});

I assume that out of the box I can't have MERS populate my service reference. I get the ID back but I have no way to specify the population of "nested" documents within Mongoose.

Thanks !
Adam

post save handler causes exception

I don't know why, but if I put a post save handler on my schema, like this

TeamSchema.post('save', function (doc) {
  console.log('JJR %s has been saved', doc._id);
})

I get a exception (when an actual PUT is precessed) with this stack trace:

/Users/joris/Development/App/Node/www/node_modules/mongoose/lib/utils.js:419
throw err;
^
TypeError: Cannot set property 'code' of null
at .extend (/Users/joris/Development/App/Node/www/node_modules/mers/node_modules/underscore/underscore.js:791:21)
at Array.forEach (native)
at .each..forEach (/Users/joris/Development/App/Node/www/node_modules/mers/node_modules/underscore/underscore.js:79:11)
at Function.
.extend (/Users/joris/Development/App/Node/www/node_modules/mers/node_modules/underscore/underscore.js:788:5)
at Promise.module.exports.router.del.m.findOneAndRemove.res.send.status (/Users/joris/Development/App/Node/www/node_modules/mers/lib/routes.js:113:16)
at Promise.onResolve (/Users/joris/Development/App/Node/www/node_modules/mongoose/node_modules/mpromise/lib/promise.js:162:8)
at Promise.EventEmitter.emit (events.js:96:17)
at Promise.emit (/Users/joris/Development/App/Node/www/node_modules/mongoose/node_modules/mpromise/lib/promise.js:79:38)
at Promise.fulfill (/Users/joris/Development/App/Node/www/node_modules/mongoose/n9 Jul 16:20:26 - [nodemon] app crashed - waiting for file changes before

It boils down to routes.js line 113 where a null obj (returned from the findOne function) is handed to _underscore (_u.extend).

Any idea?

Regards,
Joris

Populate with specific fields fails to populate at all

Using the formation of http://localhost:3000/rest/blogpost?skip=10&populate[comments]=title,date from the README I haven't been able to get it working. It seems from the code that this is not actually implemented, and that (to even make a start) flatJoin needs to know what the key is.

Is this not working or am I not implementing it correctly?

Find on Schema only ever returns 1 record

I am running a find on a schema, and when I run the find command in Mongo (via Robomongo for testing), I get all 112 records....when I do a find on the same schema in Mers, I only get 1 record instead of the 112.

I suspect I am missing something in my code, but I don't know.

Mongo find:

db.getCollection('inventories').find({store_id: 112});

and my mers code:

var inventorySchema = models.schema.inventory;

inventorySchema.statics.findByStoreId = function findByStoreId(q, term){
    return this.find({'store_id': parseInt(term)});
}
mongoose.model('inventory', inventorySchema);

Can't POST new doc

Hiya, Using curl, I'm able to GET docs and POST new values but I can't POST a new doc.

Problem trying to post a record to a nested collection

I'm having a problem trying to post a record to a nested collection

This is my schema:

var mongoose = require('mongoose'),
    Schema = mongoose.Schema,
    objectId = mongoose.Schema.ObjectId;

var EmployeeSchema = new Schema({
    firstname: {
        type: String,
        required: true,
        trim: true
    },
    lastname: {
        type: String,
        required: true,
        trim: true
    },
    email: {
        type: String,
        required: true,
        trim: true,
        index: true,
        validate: /\b[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}\b/
    },
    departmentId: {
        type: objectId,
        trim: true,
        required: true
    },
    enddate: {
        type: String,
        trim: true
    },
    active: {
        type: Boolean,
        "default": true
    }
});

var DepartmentSchema = new Schema({
    name: {
        type: String,
        required: true,
        trim: true,
        index: {
            unique: true
        }
    },
    employees: [EmployeeSchema]
});

module.exports.employee =  mongoose.model('employee', EmployeeSchema);
module.exports.department  = mongoose.model('department', DepartmentSchema);

This is my server startup code :

var express = require('express'),
    mers = require('mers');
    require('./Schemas/DataSchemas.js');

    process.env.NODE_ENV = 'development';

    var server = express();

    server.configure(function() {

        server.use(express.bodyParser());
        server.use('/app', express.static('app'));

        server.use(express.errorHandler({ dumpExceptions: true, showStack: true }));

        server.use('/api', mers({ uri:'mongodb://localhost:8120/staff' }).rest());
    });

    server.configure('development', function(){
        server.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
    });

    server.configure('production', function(){
        server.use(express.errorHandler());
    });

    server.listen(3000);

When I attempt to post to the following URL:

http://localhost:3000/api/department/1234/employees

I receive a 404. What am I doing wrong?

Error With Status of 0

Hello,
I am not sure what is causing this, but I have always used the status property of the Object returned from MERS to determine whether an error has occurred. I am getting an error from MongoDB about a duplicate id, (I know the this error isn't a MERS issues), but I was surprised when the object comes back from MERS with an "error" property and the status was 0. I was just curious if you had any insight into this, I know I am probably missing something obvious, but I am losing track of the code during this snippet from route.js

router.post(base + '/:type', function (req, res) {
        var Model = m(req);
        new Model(clean(req.body)).save(run(res));
    });

image

Thanks for any insight you may be able to provide

Put / create

Hey man, I love the project, thanks for the hard work. Qq. I checked the docs and examples but didn't see how to create objects. Is it assumed that I would roll my own for object creation?

Posting multi level schemas

This might be a dumb question, but i'm trying to contruct a post that can save an "advanced" schema.

My schema looks like this:

exports.Schemas = {};
exports.Schemas.Activity = new Schema({
  key: {type:String, required: true, unique: true},
  name: {type:String, required: true},
  zipcode: Number,
  city: {type: String, required: true},
  description: String,
  image: String,
  category: [String],
  type: {type: String, required: true},
  updated: { type: Date, default: Date.now },
  created: { type: Date, default: Date.now },
  openinghours: [this.Schemas.OpeningHour]
});

exports.Schemas.OpeningHour = new Schema({
  name: String,
  from: Date,
  to: Date,
  days: [this.Schemas.OpeningHourWeekday]
});

exports.Schemas.OpeningHourWeekday = new Schema({
  weekday: Number,
  openfrom: String,
  opento: String
});

What should my post look like to create an openinghours on my Activity?

i tried this, but it just created an activity without openinghours

key: "k"
city: "k"
description: "k"
name: "q1"
openinghours.from: "2014-04-01"
openinghours.name: "Season 1"
openinghours.to: "2014-04-30"
type: "k"
zipcode: "4"`

Post Data Not Saving

I have a simple mers app.

express = require "express"
mongoose = require "mongoose"
mers = require "mers"

app = express()

Schema = mongoose.Schema

BookSchema = new Schema
    title: String
    author: String

Book = mongoose.model "Book", BookSchema

app.use "/rest", mers(
    uri: "mongodb://localhost/library"
    mongoose: mongoose
).rest()

console.log app.routes

app.listen 3141

When I post data with curl.

curl -X POST -d '{"title": "Ready Player One","author": "Ernest Cline"}' -H "Content-Type: application/json" http://localhost:3141/rest/book

It creates an empty object.

{
    "payload": {
        "__v": 0,
        "_id": "52a7fb5667c42afe7e000007"
    },
    "status": 0
}

The same thing happens with PUT. Am I doing something wrong?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.