GithubHelp home page GithubHelp logo

arb / celebrate Goto Github PK

View Code? Open in Web Editor NEW
1.3K 8.0 66.0 533 KB

A joi validation middleware for Express.

License: MIT License

JavaScript 100.00%
express-middleware joi validation express express-validation

celebrate's Introduction

celebrate

Current Version Build Status airbnb-style Code Coverage Total Downloads

celebrate is an express middleware function that wraps the joi validation library. This allows you to use this middleware in any single route, or globally, and ensure that all of your inputs are correct before any handler function. The middleware allows you to validate req.params, req.headers, and req.query.

The middleware will also validate:

celebrate lists joi as a formal dependency. This means that celebrate will always use a predictable, known version of joi during the validation and compilation steps. There are two reasons for this:

  1. To ensure that celebrate can always use the latest version of joi as soon as it's published
  2. So that celebrate can export the version of joi it uses to the consumer to maximize compatibility

express Compatibility

celebrate is tested and has full compatibility with express 4 and 5. It likely works correctly with express 3, but including it in the test matrix was more trouble than it's worth. This is primarily because express 3 exposes route parameters as an array rather than an object.

Example Usage

Example of using celebrate on a single POST route to validate req.body.

const express = require('express');
const BodyParser = require('body-parser');
const { celebrate, Joi, errors, Segments } = require('celebrate');

const app = express();
app.use(BodyParser.json());

app.post('/signup', celebrate({
  [Segments.BODY]: Joi.object().keys({
    name: Joi.string().required(),
    age: Joi.number().integer(),
    role: Joi.string().default('admin')
  }),
  [Segments.QUERY]: {
    token: Joi.string().token().required()
  }
}), (req, res) => {
  // At this point, req.body has been validated and 
  // req.body.role is equal to req.body.role if provided in the POST or set to 'admin' by joi
});
app.use(errors());

Example of using celebrate to validate all incoming requests to ensure the token header is present and matches the supplied regular expression.

const express = require('express');
const { celebrate, Joi, errors, Segments } = require('celebrate');
const app = express();

// validate all incoming request headers for the token header
// if missing or not the correct format, respond with an error
app.use(celebrate({
  [Segments.HEADERS]: Joi.object({
    token: Joi.string().required().regex(/abc\d{3}/)
  }).unknown()
}));
app.get('/', (req, res) => { res.send('hello world'); });
app.get('/foo', (req, res) => { res.send('a foo request'); });
app.use(errors());

API

celebrate does not have a default export. The following methods encompass the public API.

celebrate(schema, [joiOptions], [opts])

Returns a function with the middleware signature ((req, res, next)).

  • requestRules - an object where key can be one of the values from Segments and the value is a joi validation schema. Only the keys specified will be validated against the incoming request object. If you omit a key, that part of the req object will not be validated. A schema must contain at least one valid key.
  • [joiOpts] - optional object containing joi options that are passed directly into the validate function. Defaults to { warnings: true }.
  • [opts] - an optional object with the following keys. Defaults to {}.
    • reqContext - bool value that instructs joi to use the incoming req object as the context value during joi validation. If set, this will trump the value of joiOptions.context. This is useful if you want to validate part of the request object against another part of the request object. See the tests for more details.
    • mode - optional Modes for controlling the validation mode celebrate uses. Defaults to partial.

celebrator([opts], [joiOptions], schema)

This is a curried version of celebrate. It is curried with lodash.curryRight so it can be called in all the various fashions that API supports. Returns a function with the middleware signature ((req, res, next)).

  • [opts] - an optional object with the following keys. Defaults to {}.
    • reqContext - bool value that instructs joi to use the incoming req object as the context value during joi validation. If set, this will trump the value of joiOptions.context. This is useful if you want to validate part of the request object against another part of the request object. See the tests for more details.
    • mode - optional Modes for controlling the validation mode celebrate uses. Defaults to partial.
  • [joiOpts] - optional object containing joi options that are passed directly into the validate function. Defaults to { warnings: true }.
  • requestRules - an object where key can be one of the values from Segments and the value is a joi validation schema. Only the keys specified will be validated against the incoming request object. If you omit a key, that part of the req object will not be validated. A schema must contain at least one valid key.
Sample usage

This is an example use of curried celebrate in a real server.

  const express = require('express');
  const { celebrator, Joi, errors, Segments } = require('celebrate');
  const app = express();

  // now every instance of `celebrate` will use these same options so you only
  // need to do it once.
  const celebrate = celebrator({ reqContext: true }, { convert: true });

  // validate all incoming request headers for the token header
  // if missing or not the correct format, respond with an error
  app.use(celebrate({
    [Segments.HEADERS]: Joi.object({
      token: Joi.string().required().regex(/abc\d{3}/)
    }).unknown()
  }));
  app.get('/', celebrate({
    [Segments.HEADERS]: Joi.object({
      name: Joi.string().required()
    })
  }), (req, res) => { res.send('hello world'); });
  app.use(errors());

Here are some examples of other ways to call celebrator

  const opts = { reqContext: true };
  const joiOpts = { convert: true };
  const schema = {
    [Segments.HEADERS]: Joi.object({
      name: Joi.string().required()
    })
  };

  let c = celebrator(opts)(joiOpts)(schema);
  c = celebrator(opts, joiOpts)(schema);
  c = celebrator(opts)(joiOpts, schema);
  c = celebrator(opts, joiOpts, schema);

  // c would function the same in all of these cases.

errors([opts])

Returns a function with the error handler signature ((err, req, res, next)). This should be placed with any other error handling middleware to catch celebrate errors. If the incoming err object is an error originating from celebrate, errors() will respond a pre-build error object. Otherwise, it will call next(err) and will pass the error along and will need to be processed by another error handler.

  • [opts] - an optional object with the following keys
    • statusCode - number that will be used for the response status code in the event of an error. Must be greater than 399 and less than 600. It must also be a number available to the node HTTP module. Defaults to 400.
    • message - string that will be used for the message value sent out by the error handler. Defaults to 'Validation failed'

If the error response format does not suite your needs, you are encouraged to write your own and check isCelebrateError(err) to format celebrate errors to your liking.

Errors origintating from the celebrate() middleware are CelebrateError objects.

Joi

celebrate exports the version of joi it is using internally. For maximum compatibility, you should use this version when creating schemas used with celebrate.

Segments

An enum containing all the segments of req objects that celebrate can validate against.

{
  BODY: 'body',
  COOKIES: 'cookies',
  HEADERS: 'headers',
  PARAMS: 'params',
  QUERY: 'query',
  SIGNEDCOOKIES: 'signedCookies',
}

Modes

An enum containing all the available validation modes that celebrate can support.

  • PARTIAL - ends validation on the first failure. Does not apply joi transformations if any part of the request is invalid.
  • FULL - validates the entire request object and collects all the validation failures in the result. Does not apply joi transformations if any part of the request is invalid.
    • Note: In order for this to work, you will need to pass abortEarly: false to #joiOptions. Or to get the default behavior along with this, { abortEarly: false, warnings: true }

new CelebrateError([message], [opts])

Creates a new CelebrateError object. Extends the built in Error object.

  • message - optional string message. Defaults to 'Validation failed'.
  • [opts] - optional object with the following keys
    • celebrated - bool that, when true, adds Symbol('celebrated'): true to the result object. This indicates this error as originating from celebrate. You'd likely want to set this to true if you want the celebrate error handler to handle errors originating from the format function that you call in user-land code. Defaults to false.

CelebrateError has the following public properties:

  • details - a Map of all validation failures. The key is a Segments and the value is a joi validation error. Adding to details is done via details.set. The value must be a joi validation error or an exception will be thrown.
Sample usage
  const result = Joi.validate(req.params.id, Joi.string().valid('foo'), { abortEarly: false });
  const err = new CelebrateError(undefined, { celebrated: true });
  err.details.set(Segments.PARAMS, result.error);

isCelebrateError(err)

Returns true if the provided err object originated from the celebrate middleware, and false otherwise. Useful if you want to write your own error handler for celebrate errors.

  • err - an error object

Additional Details

Validation Order

celebrate validates request values in the following order:

  1. req.headers
  2. req.params
  3. req.query
  4. req.cookies (assuming cookie-parser is being used)
  5. req.signedCookies (assuming cookie-parser is being used)
  6. req.body (assuming body-parser is being used)

Mutation Warning

If you use any of joi's updating validation APIs (default, rename, etc.) celebrate will override the source value with the changes applied by joi (assuming the request is valid).

For example, if you validate req.query and have a default value in your joi schema, if the incoming req.query is missing a value for default, during validation celebrate will overwrite the original req.query with the result of joi.validate. This is done so that once req has been validated, you can be sure all the inputs are valid and ready to consume in your handler functions and you don't need to re-write all your handlers to look for the query values in res.locals.*.

Additional Info

According the the HTTP spec, GET requests should not include a body in the request payload. For that reason, celebrate does not validate the body on GET requests.

Issues

Before opening issues on this repo, make sure your joi schema is correct and working as you intended. The bulk of this code is just exposing the joi API as express middleware. All of the heavy lifting still happens inside joi. You can go here to verify your joi schema easily.

celebrate's People

Contributors

aarifkhamdi avatar adarah avatar arb avatar bboystatix avatar billylaing avatar brainsiq avatar btalayeminaei avatar cjihrig avatar eduardostuart avatar gerkindev avatar giltho avatar gonenduk avatar hoangnguyennn avatar ikokostya avatar irwin-r avatar isaachinman avatar jdtzmn avatar justin-calleja avatar kandros avatar lbevilacqua avatar loganarnett avatar markmssd avatar olsonpm avatar spyndutz avatar twrayden 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

celebrate's Issues

Clean up Error Handler

The current error handler spits back the entire Joi validation message which could be a pretty bad information leak as it contains the entire object.

The hapi response looks something like this:

{
  "statusCode": 400,
  "error": "Bad Request",
  "message": "child \"name\" fails because [\"name\" is not allowed to be empty]",
  "validation": {
    "source": "payload",
    "keys": [
      "name"
    ]
  }
}

exported Joi type definitions are missing

  • node version - 6.11.4
  • celebrate version - 7.0.1
  • joi version (via npm ls --depth=0 | grep joi) - 13.0.2

The issue I am having with celebrate is:

Type definitions for exported Joi are missing. The index.d.ts defines exported Joi as of type object. Consider defining the type as Joi from @types/joi.

Expose isCelebrate

We should probably export the isCelebrate Symbol so that users could use it if they didn't want to use our error handler function but wanted to know if the passed in err was from celebrate or not.

How to validate multipart/form-data

Hi, there.
Sorry to bother you but
I've got problems to validate multipart/form-data
from an angular app

Express

exports.create = {
  body: {
    content: Joi.string().required(),
    title: Joi.string().required()
  }
};

router.post('',
  celebrate(validators.create),
  jwtVerify,
  extractFile,
  controllers.create
);

Angular

add(data): Observable<Post> {
    const { title, content, isDraft, image } = data;
    const postData = new FormData();
    postData.append('title', title);
    postData.append('content', content);
    postData.append('isDraft', isDraft);
    postData.append('image', image, title);
    return this.http.post<Post>(this.postsUrl, postData)
   .pipe(catchError((error: any) => HttpErrorHandler.handle(error)));
  }

The error message is
{"isJoi":true,"name":"ValidationError","details":[{"message":""content" is required","path":["content"],"type":"any.required","context":{"key":"content","label":"content"}}],"_object":{},"_meta":{"source":"body"}}

Can you help me, please ?

Custom Joi

The issue I am having with celebrate is:

I was wondering how I could use an extended Joi object with celetabre, the idea is that I could have custom validations.

Possible enhancement for @types

I see there's already type definitions, which is awesome!
However, I don't understand why the schema has all 4 params, headers, query, and body set as required. Shouldn't they be set as optional, as such:

{
    params?: object,
    headers?: object,
    query?: object,
    body?: object,
}

For example, if I want to validate only the params, I shouldn't have to specify an empty headers, query and body.

Thanks for considering!

TypeScript compiler can't found declaration

  • node version - v8.6.0
  • celebrate version - 5.0.1
  • joi version (via npm ls --depth=0 | grep joi) -

Explain the problem here

Now TypeScript declaration https://github.com/continuationlabs/celebrate/blob/master/lib/index.d.ts is presented in npm package, but can't be found by TypeScript compiler:

$ ls node_modules/celebrate/lib/index.d.ts 
node_modules/celebrate/lib/index.d.ts
$ ./node_modules/.bin/tsc 

t.ts(1,28): error TS7016: Could not find a declaration file for module 'celebrate'. '/home/kostya/tmp/ts-test/node_modules/celebrate/lib/index.js' implicitly has an 'any' type.
  Try `npm install @types/celebrate` if it exists or add a new declaration (.d.ts) file containing `declare module 'celebrate';`

1 import * as celebrate from 'celebrate';
                             ~~~~~~~~~~~

For fix this need to add property types to package.json of Celebrate package:

{
+ "types": "./lib/index.d.ts"
}

Log error/warning on Celebrate rejection

This is mostly a question, so the other stuff didn't seem relevant
The issue I am having with celebrate is:

I am looking for a simple way to log when Celebrate errors occur. I just started user testing linkmelater.win, and have a couple of users who are experiencing issues signing up. I think I know the root cause, but I want to confirm in my logs before I get back to them. Currently, celebrate just returns the 400 and a message describing what's missing. Since I don't have much user-defined input, I would like for that error message to just get logged on my server too. any advice? Looking to avoid writing an error handler if I can (still pretty novice with Joi).

Send Back All Validation Errors

celebrate seems to only send back one validation error at a time even if there are multiple validation errors.
Is it possible to have it validate all errors and then send back all of them?

Relocate `_schema`

Hide it behind a symbol or something. Maybe have a schema function that returns this information?

celebrate undefined

The docs show to require celebrate like below:

// try-celebrate.js
const { celebrate, Joi, errors } = require('celebrate');
console.log('celebrate', celebrate);

terminal

$ node try-celebrate.js 
celebrate undefined

but celebrate is undefined. The below is what works for me to get the celebrate object:

const celebrate = require('celebrate')
const { Joi, errors } = celebrate
console.log('celebrate', celebrate)

How to validate file extension (.mp3, wmv)

how to validate file extension with Celebrate Joi,

My Joi schema is like this

body: Joi.object().keys({ Audio: Joi.string().regex(/\.(?:wav|mp3)$/i).optional().options({ language: { any: { allowOnly: 'request id is required' }, label: 'audio file' } }).label('please provide [.mp3] or [.wav] file'), indexname: Joi.string().required() })

in audio my file is attached

curl -X POST --header 'Content-Type: multipart/form-data' --header 'Accept: application/json' -F Audio=@"33107045414_f1b635aea6_k.jpg" -F indexname=1222 'http://172.24.5.22:3000/api/v1/audio'

so how can i validate file format with the help of joi regex function

Remove Fast Series

joi validation is sync, so there really isn't a good reason so use an async library.

[email protected]

If you've been following along, you've seen that I've recently made some changes to celebrate and I wanted to explain why this is a major release and not a minor.

The most recent round of changes, I removed stuff (fast-series and the conditional check for how to set updated values back to req). Writing values on req is the change I'm most unsure of and is the main impetus for making this a major rather than a minor.

All of MY tests pass which is great but I can't be 100% that these changes won't impact your running instances. I decided the safest thing to do would be to make a new major so you can opt into it and let me know if there are any major bugs.

There are no new features for this release. Just code cleanup and some performance gains (about 1000 operations per second improvement)

This also includes a new version of Joi which will definitely include breaking changes to your schema. Please see the joi v14 release notes for more information.

Unit testing validators

  • node version - 8.9.0
  • celebrate version - ^7.0.1
  • joi version (via npm ls --depth=0 | grep joi) -^13.0.2

Am I to be using Joi.validate(), or does Celebrate expose its own custom validator?

Joi 13+

What are we going to do about joi@13 and beyond? I doubt express is ever going to be as aggressive about their supported versions of node as the hapi ecosystem.

Do we want to have two versions of celebrate? I don't really like that idea, but I actually don't have a better one. I don't think we can stick with 12 forever.

Joi Update

Bump the peerDep to joi 11. Should this be a major?

node v6 support (joi v12)

  • node version - 6.14.2
  • celebrate version - 8.0.0

Is using the latest v7.x.x release the best way to work with node v6 (joi v12 is the last version that supports node v6)?

Why? I'm deploying to firebase / google cloud functions that run node v6 (limiting joi to v12). 😿

Thanks for the great module!

Validate a Query param base on a Params value

My joi schema looks like this:

const ConfigSchema = {
    params: Joi.object().keys({
        param1: Joi.string().required().valid([
            'a',
            'b'
        ])
    }),
    query: Joi.alternatives()
              .when('params.param1, {
                  is: 'a',
                  then: Joi.object().keys({
                      query1: Joi.string().required()
                  }),
                  otherwhise: Joi.any()
              })
};

Here is an example value that is not working as expected:

{ params: { param1: 'a' }, query: { query1: 'blha' }} 

or

{ params: { param1: 'b' } }

The issue I am having with celebrate is:

I want to validate query field based on the values that a params may have

Is it possible?? Using the given schema I will get always:
"value" not matching any of the allowed alternatives'
If I remove the query property from the schema both example values works so the error may be when referencing the params.param1

Regards.

Body Checks

Skip body check on "GET" and "HEAD" requests.
Add test for req.body being undefined.

Possible Enhancement

Hey guys,

First of all, thank you very much for the repo you created. I have used Celebrate at the company I work at with great success, and it is used in production.

I recently built a library that exposes a fluent interface for Celebrate. You can find it here: https://github.com/naveedn/vayder

I built the library because the Express middleware pipeline lends itself to declaratively chaining validations, and the facade pattern makes it easy to understand what Celebrate is doing.

I was wondering if you guys were interested in having this interface directly incorporated in your repo?

Thanks again!

Relocate Validated values

Rather than overwrite req.x, with the updated values, attach them to res.locals.celebrate.x. We should do this because it's the blessed location for middleware to attach things to res. Also, with the current implementation, we have no way to get the initial values back at all.

Additionally, we need this for express 5 compatibility.

how to extend joi schema

  • node version - 8.0.0
  • celebrate version - 6.0.0
  • joi version (via npm ls --depth=0 | grep joi) - 12.x.x

My joi schema looks like this:

body: Joi.object().keys({ request_id: Joi.string().required().options({ language: { any: { allowOnly: 'request id is required' }, label: 'request id' } }).label('please provide request id'), topic_name: Joi.string().required().options({ language: { any: { allowOnly: 'topic name is required' }, label: 'topic name' } }).label('The name of the topic is required'), additional_title: Joi.string().optional(), additional_search_tags: Joi.string().optional(), topic_level: Joi.string().optional(), parent_topic: Joi.array().sparse(), properties: Joi.object(), region: Joi.array().sparse(), published_start_date: Joi.date().optional(), published_end_date: Joi.date().optional() })

Here is an example value that is not working as expected:

body: Joi.object().keys({ request_id: Joi.string().required().options({ language: { any: { allowOnly: 'request id is required' }, label: 'request id' } }).label('please provide request id'), topic_name: Joi.string().required().options({ language: { any: { allowOnly: 'topic name is required' }, label: 'topic name' } }).label('The name of the topic is required'), additional_title: Joi.string().optional(), additional_search_tags: Joi.string().optional(), topic_level: Joi.string().optional(), parent_topic: Joi.array().sparse(), properties: Joi.object(), region: Joi.array().sparse(), published_start_date: Joi.date().format('YYYY-MM-DD').optional(), published_end_date: Joi.date().format('YYYY-MM-DD').optional() })

The issue I am having with celebrate is: i am using joi-date-extensions to extend date format but show me this error "Cannot read property 'extend' of undefined
screenshot from 2017-11-08 12 34 26
"
So Please let me know how i can solve this issue

Celebrate stripping out all keys

  • node version - 6.7.0
  • celebrate version - 4.0.1
  • joi version (via npm ls --depth=0 | grep joi) - 10.2.0

My joi schema looks like this:

 export const JUserSchema = Joi.object().keys({
        "name"          : Joi.string().min(3).max(200).required(),
        "description"   : Joi.string().min(0).max(2000).optional()
});

Here is an example value that is not working as expected:

  curl -H "Content-Type: application/json" -X POST -d '{"name":"test", "description":"xyz"}' http://localhost:5000/users

The issue I am having with celebrate is:

import { JUserSchema } from '../schemas/joi/user';
import { MUser } from '../schemas/users';
 
const Celebrate = require('celebrate');
const users = Router();

users.post('/', Celebrate({body:JUserSchema}), function(request, response, next) {
    
    MUser.create(request.body, function(error,doc) {
        if(error) response.status(500).json(error);

        response.status(200).json(doc);
    });
 });

Basically this goes ahead and creates an object without the name and description keys (i.e. an object with just the mongo id), even though it is a compliant object. The same happens when the object is incorrectly sent (e.g. if i remove the name key from the POST submission)

So there are three issues:

  1. It is lettering error prone objects flow past the middleware.
  2. They are getting created.
  3. No proper error messaging

Bump Jest

A few places where we could use describe.each to cut down on test boilerplate

HTTP Status Code On Error

Recently, I started using express with celebrate as a middleware for request body validation and there's a tiny detail that I'm wondering:

When a Joi constraint is violated, a response body is serialized and sent with a HTTP Status 400 (Bad Request).

By definition:

400 Bad Request
This response means that server could not understand the request due to invalid syntax.

In this case, a bad request would be appropriated to a request body like:

// invalid JSON syntax
{ "param1": "abc", "param2": 

But, when the request body is well-formed, the server understands the content-type but cannot process the request due to business logic validation, should the default response be sent with a HTTP Status 422 (Unprocessable Entity)?

422 Unprocessable Entity
The request was well-formed but was unable to be followed due to semantic errors.

readme typo

Line 7 of the 2nd example in the Usage section of the readme, I believe it should be celebrate instead of Celebrate
I can make a pull request tomorrow if needed, or you can modify that "online" if you find it easier

Exported API

Change exported API to

{
  celebrate: function() {},
  errors: function() {},
  Joi: Joi
}

This makes importing the different APIs a little cleaner.

Add Joi as a peer dependency

For projects that install Joi as part of there own dependencies, it would be good to get warnings of incompatible versions when npm installing.

Edit: It looks like it used to be a peerDep but was removed at some point?

Integration tests

Now that we are trying to support multiple versions of express, add basic integration tests with a test matrix for express version 3, 4, and 5.

Change Setting Joi result back to req

Remove conditional and just do Object.defineProperty and set the value there. Make this a breaking change in case it has unintended side effects.

Breaking Changes?

Noticed there's a major version change to 3.0.0, are there any breaking changes from 2.2 that could be documented here?

Express 5 heads up

Cannot set property query of #<IncomingMessage> which has only a getter

TypeError: Cannot set property query of #<IncomingMessage> which has only a getter
    at Joi.validate (/home/kevin/wheatt-node/node_modules/celebrate/lib/index.js:37:23)

Commenting out that line seemed to fix the problem, if that helps. Not sure what it does.

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.