Code Monkey home page Code Monkey logo

letmegrpc's People

Contributors

awalterschulze avatar d-alex avatar gpaul avatar ivucica avatar jmarais avatar scbizu avatar tgulacsi avatar yinxulai 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

letmegrpc's Issues

suggestion for a better form preview/generation, build an awesome golang admin boilerplate

Hi guys,

Hope you are all well !

Would be awesome and a game changer for the golang community to have an administration panel being able to create forms through admin-rest boilerplates like admin-on-rest (https://github.com/marmelab/admin-on-rest-demo) or better with vue.js like (vue-admin).

Why ? because there is no boilerplate allowing to deal with custom forms (settings, multi-database connection or api gateways, eg krakend or qor an e-commerce framework, and to make it easy to setup or edit more flexible admin uis.

Flow:
1- export models, structs or interfaces
2- generate proto files from go source code (eg, link) or from gorm models
3- add/update the yaml based schema (eg, redis-orm) some form properties (eg. textarea, mandatory)

I found some interesting entity based apis, like entity-rest-api, to integrate another admin skeleton from marmelab, ng-admin, in golang but the painful side is that you have to bundle the api manually.

Would be awesome to get things more easier to setup by exporting the schema of gorm model, or struct, and to use letmegrpc to generate the GRPC form and save the form content...

My question is much more about how do u see letmegrpc helping such purpose guys ? Did I miss-understood the aim of letmegrpc ?

It is really something missing in the go community, a dynamic/flexible admin boilerplate.

Have an awesome day ! Waiting for any feedbacks :-) ^^

Cheers,
Richard

no buildable Go source files error

$ letmegrpc --addr=localhost:12345 --port=10000 --proto_path=./:../ ./protobuf/proxygroup.proto
2015/07/25 21:33:37 main.go:3:8: no buildable Go source files in /var/folders/_n/hr82ybg110jbm8ytkqygh6zw0000gn/T/letmegrpc_c25416e49fd6e592/src/tmpprotos
exit status 1

running the above command with options results in the above error. Any suggestions? Anything you need for me to diagnose further?

nested enums not generating a dropdown menu

I have a Protobuf message with an enum defined within it, e.g.

    enum TestEnum {
        SOME_OPTION = 1;
        SOME_OTHER_OPTION = 2;
    }
    required TestEnum test_enum = 1;
    ...
}

However, the GUI generated fails to provide a dropdown menu. Instead, it shows up as text, e.g.:
screen shot 2018-06-04 at 4 39 00 pm
Is there a fix?

protoc-gen-gofast generates different names

db_dealer.zip
protoc-gen-gofast generates DbDealer_UtolsoMod from the proto name db_dealer__utolso_mod.

The protoc-gen-letmegrpc plugin uses the names from the proto unchanged. I've tried to replicate what gofast does (vanity and vanity/command) but seems a little bit magic, and when it worked, it did not compile, missed the "Serve" function from the html plugin.

Please help me sort this out!

package main

import (
    "strings"

    "github.com/gogo/letmegrpc/html"
    "github.com/gogo/protobuf/proto"
    "github.com/gogo/protobuf/protoc-gen-gogo/generator"
    "github.com/gogo/protobuf/vanity/command"
)

func main() {
    req := command.Read()
    //files := req.GetProtoFile()
    //files = vanity.FilterFiles(files, vanity.NotGoogleProtobufDescriptorProto)
    //vanity.ForEachFile(files, vanity.TurnOnMarshalerAll)
    //vanity.ForEachFile(files, vanity.TurnOnSizerAll)
    //vanity.ForEachFile(files, vanity.TurnOnUnmarshalerAll)

    //resp := command.Generate(req)
    //command.Write(resp)

    gen := generator.New()
    gen.Request = req
    gen.CommandLineParameters(gen.Request.GetParameter())
    gen.WrapTypes()
    gen.SetPackageNames()
    gen.BuildTypeNameMap()
    gen.GeneratePlugin(html.New())
        gen.Response = resp

    for i := 0; i < len(gen.Response.File); i++ {
        gen.Response.File[i].Name = proto.String(strings.Replace(*gen.Response.File[i].Name, ".pb.go", ".letmegrpc.go", -1))
    }

    // Send back the results.
    command.Write(gen.Response)
}

Error whilst testing serve.proto

$ letmegrpc --addr=localhost:12345 --port=8080 serve.proto
2018/08/18 12:21:51 protoc-gen-gogo: program not found or is not executable
--gogo_out: protoc-gen-gogo: Plugin failed with status code 1.

Docker image does not work

I tried to setup a container running letmegrpc, with the following Dockerfile

FROM golang:latest

# install protobuf
RUN apt-get update && apt-get install curl unzip -y 
RUN curl -OL https://github.com/google/protobuf/releases/download/v3.0.0/protoc-3.0.0-linux-x86_64.zip \
  && unzip protoc-3.0.0-linux-x86_64.zip -d protoc3 \
  && mv protoc3/bin/protoc /usr/bin/protoc

# install letmegrpc
RUN cd $GOPATH \
  && mkdir -p ./src/github.com/gogo/letmegrpc \
  && git clone https://github.com/gogo/letmegrpc ./src/github.com/gogo/letmegrpc \
  && git clone https://github.com/gogo/protobuf ./src/github.com/gogo/protobuf \
  && go get google.golang.org/grpc \
  && go get golang.org/x/net/context \
  && (cd ./src/github.com/gogo/letmegrpc && make install)

# install protoc-gen-gogo
RUN go get github.com/gogo/protobuf/protoc-gen-gofast \
  && go get github.com/gogo/protobuf/proto \
  && go get github.com/gogo/protobuf/jsonpb \
  && go get github.com/gogo/protobuf/protoc-gen-gogo \
  && go get github.com/gogo/protobuf/gogoproto

COPY protos /etc/protos


EXPOSE 5000

CMD letmegrpc --addr=localhost:3002 --port=5000 --proto_path=/etc/protos /etc/protos/auth.proto

I tried to run it using docker run -it -p 5000:5000 letmegrpc:auth, The process run without any errors, but http://localhost:5000/MyService/MyMethod still cannot be reached, any idea where the issues are? Thanks in advance!

Why submit form values via GET instead of POST?

This is a great project! But why does the generated UI submit form values as URL parameters instead in a GET request, instead of as form POST parameters? Is there a configuration option to make the UI use POST?

RPC method name staring with lowercase character fails

../../1.letmegrpc.go:8248: this.client.setVehicleModel undefined (type OneWayTicketClient has no field or method setVehicleModel, but does have SetVehicleModel)

if change setVehicleModel to SetVehicleModel, it works.

letmegrpc doesn't support Google's Message Types

I get the following error when I try to generate a GUI with letmegrpc:

2019/11/16 14:14:37 google/protobuf/any.proto: File not found.
google/protobuf/descriptor.proto: File not found.
google/protobuf/timestamp.proto: File not found.
todo_list.proto: Import "google/protobuf/any.proto" was not found or had errors.
todo_list.proto: Import "google/protobuf/descriptor.proto" was not found or had errors.
todo_list.proto: Import "google/protobuf/timestamp.proto" was not found or had errors.
todo_list.proto:58:5: "google.protobuf.Timestamp" is not defined.
todo_list.proto:59:5: "google.protobuf.Timestamp" is not defined.
todo_list.proto:60:5: "google.protobuf.Timestamp" is not defined.
todo_list.proto:72:5: "google.protobuf.Timestamp" is not defined.
todo_list.proto:73:5: "google.protobuf.Timestamp" is not defined.
todo_list.proto:74:5: "google.protobuf.Timestamp" is not defined.
todo_list.proto:87:5: "google.protobuf.Timestamp" is not defined.
todo_list.proto:88:5: "google.protobuf.Timestamp" is not defined.
todo_list.proto:89:5: "google.protobuf.Timestamp" is not defined.
todo_list.proto:104:5: "google.protobuf.Timestamp" is not defined.
todo_list.proto:105:5: "google.protobuf.Timestamp" is not defined.
todo_list.proto:106:5: "google.protobuf.Timestamp" is not defined.
todo_list.proto:150:5: "google.protobuf.FileDescriptorSet" is not defined.
todo_list.proto:153:5: "google.protobuf.Any" is not defined.
 exit status 1

Check the original proto schema below for more details about the message types.

Original Proto Document:

syntax = "proto3";

import "google/protobuf/any.proto";
import "google/protobuf/descriptor.proto";
import "google/protobuf/timestamp.proto";

/*
 * Services
 */
service TodoList {
    // Gets a todo item by id
    rpc GetItem (GetItemReq) returns (GetItemResp) {}

    // Adds a new item to the todo list
    rpc AddItem (AddItemReq) returns (AddItemResp) {}

    // Updates a todo items task
    rpc UpdateItem (UpdateItemReq) returns (UpdateItemResp) {}

    // Deletes a todo item by id
    rpc DeleteItem (DeleteItemReq) returns (DeleteItemResp) {}

    // Marks a todo item as DONE
    rpc MarkItemAsDone (MarkItemDoneReq) returns (MarkItemDoneResp) {}

    // Marks a todo item as ONGOING
    rpc MarkItemAsOnGoing (MarkItemOnGoingReq) returns (MarkItemOnGoingResp) {}

    // Streams a list of todo items from the server to the client
    rpc GetItemsStream (GetItemsStreamReq) returns (stream GetItemResp) {}

    // Bidirectional streaming RPC where the client streams AddTodoItemRequest
    // messages and the server streams TodoItem responses
    rpc AddItemsSteam (stream AddItemReq) returns (stream AddItemResp) {}
}

/**
 * Messages
 */
enum Priority {
    PRIORITY_UNSPECIFIED = 0;
    PRIORITY_LOW = 1;
    PRIORITY_MEDIUM = 2;
    PRIORITY_HIGH = 3;
}

enum Status {
    STATUS_UNSPECIFIED = 0;
    STATUS_ONGOING = 1;
    STATUS_DONE = 2;
}

message TodoItem {
    string id = 1;
    string task = 2;
    Priority priority = 3;
    Status status = 4;
    google.protobuf.Timestamp created_at = 5;
    google.protobuf.Timestamp updated_at = 6;
    google.protobuf.Timestamp completed_at = 7;
}

message GetItemReq {
    string id = 1;
}

message GetItemResp {
    string id = 1;
    string task = 2;
    Priority priority = 3;
    Status status = 4;
    google.protobuf.Timestamp created_at = 5;
    google.protobuf.Timestamp updated_at = 6;
    google.protobuf.Timestamp completed_at = 7;
}

message AddItemReq {
    string task = 1;
    Priority priority = 2;
}

message AddItemResp {
    string id = 1;
    string task = 2;
    Priority priority = 3;
    Status status = 4;
    google.protobuf.Timestamp created_at = 5;
    google.protobuf.Timestamp updated_at = 6;
    google.protobuf.Timestamp completed_at = 7;
}

message UpdateItemReq {
    string id = 1;
    string task = 2;
    Priority priority = 3;
    Status status = 4;
}

message UpdateItemResp {
    string id = 1;
    string task = 2;
    Priority priority = 3;
    Status status = 4;
    google.protobuf.Timestamp created_at = 5;
    google.protobuf.Timestamp updated_at = 6;
    google.protobuf.Timestamp completed_at = 7;
}

message DeleteItemReq {
    string id = 1;
}

message DeleteItemResp {
    string id = 1;
    bool success = 2;
    string message = 3;
}

message MarkItemDoneReq {
    string id = 1;
}

message MarkItemDoneResp {
    string id = 1;
    bool success = 2;
    string message = 3;
}

message MarkItemOnGoingReq {
    string id = 1;
}

message MarkItemOnGoingResp {
    string id = 1;
    bool success = 2;
    string message = 3;
}

message GetItemsStreamReq {
    int32 limit = 1;
}

message GetItemsStreamResp {
    repeated TodoItem items = 1;
    uint32 cursor = 2;
}

message SelfDescribingMessage {
    // Set of FileDescriptorProtos which describe the type and its dependencies.
    google.protobuf.FileDescriptorSet descriptor_set = 1;

    // The message and its type, encoded as an Any message.
    google.protobuf.Any message = 2;
}

Can't run example as per readme

I'm just trying to run the example in the readme but when I run the final line in the example:

letmegrpc --addr=localhost:12345 --port=8080 serve.proto

I get This parser only recognizes "proto2". exit status 1

How do I fix this?

running curl localhost:8080 fails

I'm trying to run the example as
letmetestserver --port=8080 && letmegrpc --addr=localhost:3149 --port=8080 serve.proto

However, running curl localhost:8080 returns curl: (56) Recv failure: Connection reset by peer

For reference, I'm running this server and attempting to curl on the same machine. curl localhost:3149 simply says Connection refused

Any solutions?

Package name with dots in it causes failure

» letmegrpc --addr=localhost:65021 --port=8080 -proto_path ~/go/src/content_api/domains/border/category ~/go/src/content_api/domains/border/category/category.proto

2016/09/05 19:03:53 panic: runtime error: index out of range

goroutine 1 [running]:
panic(0x55e280, 0xc42000a180)
        /usr/lib/go/src/runtime/panic.go:500 +0x1a1
github.com/gogo/letmegrpc/html.(*html).generateFormFunc(0xc4200f3570, 0xc4200efd82, 0xe, 0xc4200134a0)
        /home/u/go/src/github.com/gogo/letmegrpc/html/html.go:93 +0x4e1
github.com/gogo/letmegrpc/html.(*html).Generate(0xc4200f3570, 0xc4200da1b0)
        /home/u/go/src/github.com/gogo/letmegrpc/html/html.go:169 +0x2dce
github.com/gogo/protobuf/protoc-gen-gogo/generator.(*Generator).generatePlugin(0xc42009e000, 0xc4200da1b0, 0x63c7e0, 0xc4200f3570)
        /home/u/go/src/github.com/gogo/protobuf/protoc-gen-gogo/generator/helper.go:330 +0x142
github.com/gogo/protobuf/protoc-gen-gogo/generator.(*Generator).GeneratePlugin(0xc42009e000, 0x63c7e0, 0xc4200f3570)
        /home/u/go/src/github.com/gogo/protobuf/protoc-gen-gogo/generator/helper.go:309 +0x22d
main.main()
        /home/u/go/src/github.com/gogo/letmegrpc/protoc-gen-letmegrpc/main.go:59 +0x32e
--letmegrpc_out: protoc-gen-letmegrpc: Plugin failed with status code 2.
 exit status 1

Not working with Windows

The directory list for GOPATH is concatenated using envs[i] + ":" + tmpDir. But Windows needs it to be envs[i] + ";" + tmpDir since the list separator is a semicolon.

Call a HTTP server (which uses grpcServer.ServeHTTP through a ServeMux)

That would be very nice, to be able to call one of several grpc servers listening on the same HTTPS port, but under different paths. grpc.Server.ServeHTTP allows us to create such a server, but I don't know yet how to call it with letmegrpc.
I need to use grpc.Invoke(..., "/prefixpath/package.service/method", ...)
(instead of "/package/service.method").

I don't see an easy solution, as all the client code is generated, with constants as paths.

Add tooltips to describe fields

It would be great if it was possible to annotate protobuf fields and have those fields appear as tooltips in the generated web form. This could be used to provide instructions and act as living documentation.

invalid code is generated: conn declared and not used

I am trying to run letmegrpc but the generated code is incorrect:

letmegrpc --addr=localhost:3149 --port=8080 listdates.proto 
2017/03/10 11:00:35 # tmpprotos
../../listdates.letmegrpc.go:54: conn declared and not used

Unfortunately there is a lot of implicit stuff going on. I found the generated file is in some /tmp/letmegrpc_ directory, and the code is indeed incorrect:

func NewHandler(grpcAddr string, stringer func(req, resp interface{}) ([]byte, error), opts ...google_golang_org_grpc.DialOption) (net_http.Handler, error) {
        conn, err := google_golang_org_grpc.Dial(grpcAddr, opts...)
        if err != nil {
                return nil, err
        }
        mux := net_http.NewServeMux()
        return mux, nil
}

Indeed this is not correct go code.
It is generated with this code

What can we do about it?

Related question: I see the code generator uses gogo/protobuf code generator, with .In(), .Out(), etc. Is there a reason to do it like this? Would it not be much simpler to generate the code with a template, and format it with gofmt afterwards?

support oneof values

It looks like oneof is not supported. The JSON doesn't seem to be marshalled onto the oneof structure correctly. The oneof is ofcourse defined as interface field using the is_ type.

Maybe there's a custom unmarshal function required, or a different work arround (sending the oneof type and value as seperate json?

escaping of reserved characters

If you use '%' in any string field, the character will not be correctly escaped when passed via the json GET querystring parameter.

This is the diff I used to narrow down the bug:

diff --git a/myservice-letmegrpc/myservice.letmegrpc.go b/myservice-letmegrpc/myservice.letmegrpc.go
index 389156e..9f8b747 100644
--- a/myservice-letmegrpc/myservice.letmegrpc.go
+++ b/myservice-letmegrpc/myservice.letmegrpc.go
@@ -35,7 +35,10 @@ It has these top-level messages:
 */
 package myservice

-import net_http "net/http"
+import (
+       net_http "net/http"
+       "net/url"
+)
 import encoding_json "encoding/json"
 import io "io"
 import golang_org_x_net_context "golang.org/x/net/context"
@@ -2437,7 +2440,17 @@ s += '<div class="children" type="Something_something">' + buildSomething_som

 func (this *htmlmyservice) CreateSomething(w net_http.ResponseWriter, req *net_http.Request) {
        w.Write([]byte(Header(`myservice`, `CreateSomething`)))
-       jsonString := req.FormValue("json")
+
+       rawQuery := req.URL.RawQuery[len("json="):]
+       fmt.Println("raw query =", rawQuery)
+
+       //      jsonString := req.FormValue("json")
+       jsonString, err := url.QueryUnescape(rawQuery)
+       if err != nil {
+               w.Write([]byte("<div class=\"alert alert-danger\" role=\"alert\">" + err.Error() + "</div>"))
+               return
+       }
+
        someValue := false
        msg := &CreateSomethingRequest{}
        if len(jsonString) > 0 {
@@ -2450,6 +2463,8 @@ func (this *htmlmyservice) CreateSomething(w net_http.ResponseWriter, req
                        w.Write([]byte("<div class=\"alert alert-danger\" role=\"alert\">" + err.Error() + "</div>"))
                }
                someValue = true
+       } else {
+               w.Write([]byte("<div class=\"alert alert-info\" role=\"alert\">" + `No JSON sent` + "</div>"))
        }
        w.Write([]byte(Formmyservice_CreateSomething))
        if someValue {

Issues generating multiple files from same package

Hi,
Conflicts happen after generating separate files that are a part of the same package.
Such generated files have functions and variables with the same name which causes issues.

Example:
Lets say I have 2 files in "package example" named ex1.proto and ex2.proto.
When I run protoc --letmegrpc (...) I get var Header, var Footer, and function func NewHandler defined in both ex1.letmegrpc.go and ex2.letmegrpc.go which causes issues.

I may have a workaround for this issue.

letmegrpc binary doesn't generate code that can listen at arbitrary IP

When working remotely, one may want to specify an IP in local network's range (or for some unfathomable reason, listen on all interfaces or on a public IP).

A trivial fix would be to replace httpPort flag with httpAddr, and to use that in the generated code. If port flag is specified, the program could keep the current behavior.

protoc-gen-letmegrpc does not support subtypes as repeated

I just tried to use the default addressbook.proto example. The function buildRepeatedKeyword_PhoneNumber_phones is generated, but where it's used, it want's to call buildRepeatedKeyword__phones. I just started looking into the problem, but I assume the getMessage in form.go seems to have a problem with subtypes. I will check if I can fix it in little time. If not, I will have to just drop my tests of letmegrpc, since this is already the second problem I found in less than an hour and I don't want to get from one problem into the next.

main.go:3:8: cannot find package "tmpprotos"

This happens if GOPATH is not set. On Mac OS the default behavior is to use ~/go if GOPATH is not set. I am not sure this is the case for all go installations.

Workaround:
set GOPATH

install failed

on OSX, go 1.5.1

i used the deps.sh to install. The git-anchor technique looks cool solution. But i think i hit some snaffu's


(cd ./src/github.com/gogo/letmegrpc && make install)
go install -v ./...
github.com/gogo/protobuf/proto
golang.org/x/net/context
golang.org/x/net/internal/timeseries
google.golang.org/grpc/codes
google.golang.org/grpc/grpclog
github.com/bradfitz/http2/hpack
google.golang.org/grpc/credentials
golang.org/x/net/trace
google.golang.org/grpc/metadata
github.com/bradfitz/http2
github.com/gogo/letmegrpc/testcmd
google.golang.org/grpc/transport
github.com/gogo/protobuf/protoc-gen-gogo/descriptor
google.golang.org/grpc
github.com/gogo/protobuf/gogoproto
github.com/gogo/protobuf/protoc-gen-gogo/plugin
github.com/gogo/letmegrpc/letmetestserver/serve
github.com/gogo/letmegrpc/test
github.com/gogo/letmegrpc/testproto2
github.com/gogo/protobuf/protoc-gen-gogo/generator
# github.com/gogo/letmegrpc/letmetestserver/serve
letmetestserver/serve/serve.pb.go:269: cannot use _Label_Produce_Handler (type func(interface {}, context.Context, func(interface {}) error) (interface {}, error)) as type grpc.methodHandler in field value
letmetestserver/serve/serve.pb.go:273: cannot use _Label_Loop_Handler (type func(interface {}, context.Context, func(interface {}) error) (interface {}, error)) as type grpc.methodHandler in field value
# github.com/gogo/letmegrpc/test
test/grpc.pb.go:303: cannot use _MyTest_UnaryCall_Handler (type func(interface {}, context.Context, func(interface {}) error) (interface {}, error)) as type grpc.methodHandler in field value
# github.com/gogo/letmegrpc/testproto2
testproto2/proto2.pb.go:355: cannot use _Proto2_Produce_Handler (type func(interface {}, context.Context, func(interface {}) error) (interface {}, error)) as type grpc.methodHandler in field value
github.com/gogo/letmegrpc/form
github.com/gogo/letmegrpc/html
github.com/gogo/letmegrpc/protoc-gen-letmegrpc
make: *** [install] Error 2


Generate from file descriptor

With support for reflection in Go, it would be great if letmegrpc could supports rendering from a proto file descriptor.

letmegrpc does not generate tooltips for imported proto objects

Given a.proto and b.proto, if b.proto imports a.proto and uses an object, say c, any comments within c from a.proto will not be generated.

a.proto:

message C {
    // This comment doesn't get turned into a tooltip
    required int64 something = 1;
}

b.proto:

message WrapperMsg {
    // This message does
    required a.C nested = 1;
}

Is it possible for the parser to process imported .proto files and their comments?

Special chars in comments are breaking the output

If protobuf fields' comments contain any quote-like symbols then something usually breaks.
i.e. ` breaks go code and ' breaks javascript.

I'll fix it later if nobody else picks the issue up first,

How to display help text?

As I've investigated, the comments before the field (in the .proto file) are read and provided to Builder.
But I don't see this appear anywhere.
There's a "setLink" in the js code, but nowhere called.

What do I miss?

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.