mwitkow / go-proto-validators Goto Github PK
View Code? Open in Web Editor NEWGenerate message validators from .proto annotations.
License: Apache License 2.0
Generate message validators from .proto annotations.
License: Apache License 2.0
We are running into following error when trying to configure.
can't load package: package github.com/protocolbuffers/protobuf: unknown import path "github.com/protocolbuffers/protobuf": cannot find module providing package github.com/protocolbuffers/protobuf
go list -f '{{ .Dir }}' -m github.com/protocolbuffers/protobuf
$GOPATH/pkg/mod/github.com/protocolbuffers/[email protected]+incompatible
Can't generate validator for enum from imported package.
import "package/name/Bar.proto";
message Foo{
package.name.Bar bar = 1 [(validator.field) = { is_in_enum: true }]; // compilation error
// undefined: Bar_name
}
You use function TypeName() but this function not contain the package name.
shell:
go get github.com/mwitkow/go-proto-validators/protoc-gen-govalidators
protobuf file:
syntax = "proto3";
package validatorFromGithub;
import "github.com/mwitkow/go-proto-validators/validator.proto";
message Msg {
string someImportantString = 1 [(validator.field) = {regex: "^[a-z]{2,5}$"}];
int32 age = 2 [(validator.field) = {regex:"int_gt: 0, int_lt: 100"}];
}
shell to gen:
protoc
--proto_path=${GOPATH}/src
--proto_path=${GOPATH}/src/github.com/google/protobuf/src
--proto_path=.
--go_out=.
--govalidators_out=.
*.proto
err:
warning: directory does not exist.
protoc-gen-govalidators: program not found or is not executable
Please specify a program using absolute path or make sure the program is available in your PATH system variable
--govalidators_out: protoc-gen-govalidators: Plugin failed with status code 1.
I feel like "exists" would be more general.
Consider the following message using an enum:
enum Provider {
Post = 0;
Call = 1;
}
message RequestMessage {
Provider provider = 1;
}
and compiling with
protoc -I/usr/local/include -I.
-I$(GOPATH)/src
-I$(GOPATH)/src/github.com/googleapis/googleapis
--descriptor_set_out=../proto/api_descriptor.pb
--go_out=plugins=grpc:../proto
--swagger_out=logtostderr=true:../swagger
--include_imports
--govalidators_out=../proto
*.proto
This works fine.
But after adding
import "github.com/mwitkow/go-proto-validators/validator.proto";
message RequestMessage {
Provider provider = 1 [(validator.field) = {is_in_enum : true}];
}
Now compile the same and the service becomes unaccessible over a grppc gateway:
Error invoking method "con.Service/New": target server does not expose service "con.Service"
I have a something.proto
file, and defined go_package
option on it:
// something.proto
syntax = "proto3";
option go_package="github.com/abc/def/ghi/klm/app/service";
And I generated the validation file using protoc
as below:
protoc -I. \
-I$(CURR_DIR)/../vendor/ \
--doc_out=markdown,proto_clip.md:../docs/proto \
--go_out=plugins=grpc,paths=source_relative:../app/service \
--govalidators_out=$(CURR_DIR)/../app/service \
./*.proto;
Note that I used paths=source_relative:../app/service
option (something.pb.go would be placed in relative path to currrent proto files),
then I got a something.validator.pb.proto
at app/service/github.com/abc/def/ghi/klm/app/service/generate_id.validator.pb.go
=> The generated validation file was placed in whole path joined with relative path.
=> Expect: Only app/service/generate_id.validator.pb.go
This tool support the generated validation files in relative path to as above,
regardless to go_package
option if a relative path is given in command, such as source_relative
, for example.
Hi,
Its been a while now that I'm looking for a suitable solution, something that can validate my requests and return an informative response, something that I'll be able to expose to my gRPC client for farther use.
Suggestion: Make FieldError
expose additional information (Field name / Validation error).
This way, the users of this library would be able to something like this, which will expose additional information back as a gRPC response.
for example:
repeated string pic_url_list = 2 [(validator.field) = {regex: "/^(https?:\/\/)([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w\.-]*)*\/?$/"}];
this will return error:
feeds_protocol.proto:323:83: Invalid escape sequence in string literal.
if i do not use "", everything works fine.
Am I missing a trick, or is there currently no way to enforce that a oneof field must have one of the contained types? Currently the generated validator falls through to return a nil error if none of the union type members are present.
If you use gogoproto's custom types (https://github.com/gogo/protobuf/blob/master/custom_types.md) e.g.:
import "myorg/customtypes/time/time.proto";
...
message Example {
time.CustomTime created = 3 [(gogoproto.customtype) = "myorg/customtypes/time.CustomTime"];
}
mwitkow validators generates a file with unused imports:
19:33:28 generated/xxxx.pb.go:17:2: imported and not used: "myorg/customtypes/time" as myorg_customtypes_time
repeated string name = 1 [(validator.field) = {msg_exists : true}];
when build:
item declared and not used
validator code contains this loop:
for _, item := range this.Name {
}
When one or both of the option go_package
lines in the below 2 files are enabled, the import order changes randomly between:
_ "." // or "github.com/someuser/api_a"
_ "github.com/mwitkow/go-proto-validators"
and vice versa.
syntax = "proto3";
package a;
// option go_package = "github.com/someuser/api_a";
message Thing { string id = 1; }
syntax = "proto3";
import "a.proto";
package b;
// option go_package = "github.com/someuser/api_b";
import "github.com/mwitkow/go-proto-validators/validator.proto";
message SomethingContainingThing { a.Thing thing = 1 [(validator.field) = {msg_exists : true}]; }
default: b.validator.pb.go b.pb.go
%.validator.pb.go: %.proto a.proto
@protoc -I. -Ivendor -Ivendor/github.com/protocolbuffers/protobuf/src --govalidators_out=paths=source_relative:. "$<"
%.pb.go: %.proto a.proto
@protoc -I. -Ivendor -Ivendor/github.com/protocolbuffers/protobuf/src --go_out=paths=source_relative:. "$<"
.PHONY: clean
clean:
@rm -f *.pb.go
F="b.validator.pb.go"
while true ; do
rm -f "$F"
make "$F"
md5="$(md5sum "$F" | awk '{print $1}')"
echo -e "$(date)\t$md5"
mv "$F "$md5-$F"
done
(If F
is changed to b.pb.go
, no flakiness is observed in the output.)
In the vendor
dir we have:
tree -d vendor
vendor/
└── github.com
├── google
│ └── protobuf
│ └── src
│ └── google
│ └── protobuf
│ ├── compiler
│ │ ├── cpp
│ │ └── ruby
│ └── util
│ └── internal
│ └── testdata
└── mwitkow
└── go-proto-validators
├── examples
└── test
Versions:
f425b9f
(12/Feb/2019, or v3.7.0+incompatible
according to go.mod
)I've got a proto file which uses a
google.protobuf.Timestamp date = 1 [(gogoproto.stdtime) = true];
declaration. When compiling this with protoc-gen-govalidators
the resulting file contains an unused import "time".
I could whip up a minimal example for this if desired?
Hey @mwitkow !
Thanks for this great project. Would it be possible to include useful validators such as UUID ? (ie. not in a fork version for this project.. I'll create the PR for it).. At the moment we need to copy and paste it all over the protos.
string user_id = 1 [(validator.field) = {regex: "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-4[a-fA-F0-9]{3}-[8|9|aA|bB][a-fA-F0-9]{3}-[a-fA-F0-9]{12}$"}];
Proposal usage:
string user_id = 1 [(validator.field) = {uuid : true}];
grpc_api_configuration is a sidecar .yml file allowing for specifying varying API configurations outside of the .proto file. It would be awesome if go-proto-validators
could generate validators for a gRPC configuration based on this, so that clients don't have to include go-proto-validators
in a non-Go project.
To take the example on the README.
package validator.examples;
import "github.com/mwitkow/go-proto-validators/validator.proto";
message InnerMessage {
// some_integer can only be in range (1, 100).
int32 some_integer = 1 [(validator.field) = {int_gt: 0, int_lt: 100}];
// some_float can only be in range (0;1).
double some_float = 2 [(validator.field) = {float_gte: 0, float_lte: 1}];
}
Could be specified as:
validators:
- selector: validator.examples.InnerMessage
fields:
- selector: some_integer
field:
int_gt: 0
int_lt: 100
- selector: some_float
field:
int_gt: 0
int_lte: 1
repeated string name = 1 [(validator.field) = {repeated_count_min : 1, human_error: "Name can not be empty"}];
when build:
item declared and not used
validator code contains this loop:
for _, item := range this.Name {
}
I saw https://github.com/mwitkow/go-proto-validators/pull/66/files#diff-daed06840ae2242793f6bca24ba9b8bd
if fieldName != "RepeatedCountMin" && fieldName != "RepeatedCountMax" {
return true
}
I think human_error
break your rule, can you fix it ?
Using the map
type in a proto with string
as the value such as:
map <string, string> my_map = 1;
causes an error due to the comparison of string
to nil
:
invalid operation: item != nil (mismatched types string and nil)
On the second line of this (generated) code block:
for _, item := range this.MyMap {
if item != nil {
if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(item); err != nil {
return err
}
}
}
Hi,
I'm using this project to generate a GRPC server (Go) as well as clients in multiple languages. Unfortunately, I can't seem to generate a Java client that compiles --- there's an validator.Validator that's being generated alongside my Java code.
Here's the command I'm using:
protoc \
-I api/protobuf \
-I /usr/local/include \
-I ${GOPATH}/src \
-I ${GOPATH}/src/github.com/gogo/protobuf/protobuf \
-I ${GOPATH}/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis \
--go_out=plugins=grpc:pkg/my-project \
--java_out=pkg/java/my-project/src/main/java \
--doc_out=docs/ \
--doc_opt=markdown,grpc.md \
--govalidators_out=pkg/my-project \
--grpc-gateway_out=logtostderr=true:pkg/my-project \
api/protobuf/my-project.proto
And a snippet of my proto file
syntax = "proto3";
package myproject;
import "github.com/mwitkow/go-proto-validators/validator.proto";
import "google/api/annotations.proto";
import "google/protobuf/any.proto";
option java_package = "com.myproject";
option optimize_for = SPEED;
I would like to be able to write a function that returns true/false whether the given field passes validation or not.
Every single validation library I can think of supports this.
In order to get this to work with generated code, most likely the user will have to register the function with your package under a include a unique string name. That same name would be used in the proto file.
When Go 1.13 will be supported?
If it's fine, README might be fixed ✨
Using Protobuf validators is currently verified to work with:
Go 1.11 & 1.12
I've got a proto message with a double
variable that I would like to restrict to values between 0 and 0.1. Unfortunately this isn't possible with int_gt and int_lt, for obvious reasons. However, not even restricting it to anything between 0 and 1 exclusive works, e.g.
double my_double = 1 [
(validator.field) = {
int_gt: 0,
int_lt: 1,
}
];
Produces nothing for double fields. Presumably they're explicitly unsupported?
Using the length_* (length_lt, length_gt) validator will print the whole byte[] in its error message, which can get pretty verbose for big arrays. Also the message has weird wording. Example:
invalid field x: value '[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]' must length be less than '257'
In the readme the path to protobuf is
--proto_path=${GOPATH}/src/github.com/google/protobuf/src
the url seems to have moved to https://github.com/protocolbuffers/protobuf
The go_package
option is not declaring a path relative to the $GOPATH/src directory, as is idiomatic. This leads to packages importing it having to use a relative import. It also leads to the unidiomatic file registration.
In my experiments with gRPC reflection, this makes any protofiles using validators completely impossible to use, as reflection forces proto files to be imported in the same fashion as they are registered, which in this case is import "validator.proto"
. A proper go_package path might solve this as well, but I'm not sure.
i add some new cases for integer:
int_gte : equal or greater than
int_lte : equal or smaller than
and another case :
regard enum as interger. 'cause enum in pb files is still an integer, as follow:
type GetTimelineReq_Type int32
const (
GetTimelineReq_ALL GetTimelineReq_Type = 0
GetTimelineReq_USER GetTimelineReq_Type = 1
GetTimelineReq_TOPIC GetTimelineReq_Type = 2
)
this is part of golang pb file
and my pull request is :
https://github.com/mwitkow/go-proto-validators/pull/22/files
protoc \
--go_out=plugins=grpc:./lib/protos/ \
--proto_path=/Users/frontmage/go/src \
--proto_path=/Users/frontmage/go/src/github.com/google/protobuf/src \
--proto_path=./protos/common/ \
--proto_path=./protos/server/ \
--govalidators_out=./lib/protos \
./protos/common/*.proto \
./protos/server/*.proto
I'm using protoc
to generate validators for my proto file, but the validator function is just return nil
.
message LoginReq {
string login_id = 1 [(validator.field) = {msg_exists : true}];
}
func (this *LoginReq) Validate() error {
return nil
}
The protoc
command shows no errors, so how to properly generate validators?
Requesting to add the ability to add a validation rule to an optional field. I am unclear about the right syntax but a possible semantic would be like this:
// Optional. But if the value is present, the length of the value should be greater than 0
string fieldname = 1 [(validator.field) = {optional: true, length_gt: 0, length_lt: 257}];
I ended up having to do a hacky manual registration of the proto extension defined in this package to get a vanilla protobuf environment working that is doing it's own proto file parsing.
I wanted to use go-proto-validators
to validate the field of a message by using regular expressions. This is the regular expression I used: [\p{L}\p{N}]({\p{L}\p{N}_- ]{0,28}[\p{L}\p{N}])?.
And... It didn't work as expected. Why? The regex isn't valid, because you can't use \
in a string "
. Take a look at the generated code:
regexp.MustCompile("[\p{L}\p{N}]({\p{L}\p{N}_- ]{0,28}[\p{L}\p{N}])?.") # Does panic!
You need to escape the backtick with another one: [\\p{L}\\p{N}]({\\p{L}\\p{N}_- ]{0,28}[\\p{L}\\p{N}])?.
. This works, but also produces and ugly error message.
I can't decide if this should be treated like an error or not. But we should at least put a note in the README.
func (this *InnerMessage) Validate() error {
if !(this.SomeInteger > 0) {
return fmt.Errorf("validation error: InnerMessage.SomeInteger must be greater than '0'")
}
if !(this.SomeInteger < 100) {
return fmt.Errorf("validation error: InnerMessage.SomeInteger must be less than '100'")
}
if !(this.SomeFloat >= 0) {
return fmt.Errorf("validation error: InnerMessage.SomeFloat must be greater than or equal to '0'")
}
if !(this.SomeFloat <= 1) {
return fmt.Errorf("validation error: InnerMessage.SomeFloat must be less than or equal to '1'")
I can modify return fmt.Errorf("validation error: InnerMessage.SomeFloat must be less than or equal to '1'")
by change the autogened file. But this is low. Any good way?
Go 1.15 and rules_go are starting to get more strict about conflicts that occur when linking multiple copies of the same package. This happens frequently with Well Known Types since there are two separate targets for each proto: one built from pre-generated sources (for developers not using go_proto_library
) and one built with go_proto_library
.
A conflict is introduced in //:_validators_golang
due to a dependency on @com_github_golang_protobuf//protoc-gen-go/descriptor:go_default_library
. I think the deps
attribute can be dropped from this target. It's compiled with @io_bazel_rules_go//proto:go_proto
, which already has an implicit dependency on @io_bazel_rules_go//proto/wkt:descriptor_go_proto
.
I'm not sure if this also affects the gogo targets, too; I don't know them well enough to suggest a change.
Would it be possible to specify a list of unique integer ids for the type of validation that failed?
This would atleast allow the caller to write code to uniquely handled specific conditions
For instance
err := message.Validate() verr := err.(*validator.Error) if verr.Code == 5 { fmt.Printf("this is a fatal error") } else { fmt.Printf("this is a temporary error") }
Not a big problem by any stretch, but looks a little funny.
I've got a protofile which replaces
google/protobuf/timestamp.proto
with github.com/gogo/protobuf/types
and
google/protobuf/empty.proto
with github.com/gogo/protobuf/types
via the -M
parameter to protoc.
This results in the generated code importing github.com/gogo/protobuf/types
twice, once for each replaced import.
We need to rebase the implementation of the plugin on the new API available in the google.golang.org/protobuf
module.
length_ *
validates the number of bytes.
Would it be possible to include validators such as UTF-8 RuneCount ? When developing services for Japan etc, It is convenient to handle the length of multibyte characters.
A string must always contain UTF-8 encoded or 7-bit ASCII text.
Golang ProtoBuf Validation question here - I'm trying to set validation on a limit field, however I need Limit to be a google.protobuf.Int32Value for validation and tests in our code. This doesn't work with validation however, so I've tried moving the LimitValue out of the Filter message, but this then generates a different name in the swagger docs which we can't use as the api information is already in production.
When I generate the protobuf files using this code:
message Filter {
google.protobuf.Int32Value limit2 = 1;
}
The protobuf.swagger.json generates:
"parameters": [
{
"name": "limit2",
"in": "query",
"required": false,
"type": "integer",
"format": "int32"
},
However if I use this:
message LimitValue {
int32 value = 1 [(validator.field) = {int_gt: 0,int_lt: 101}];
}
message Filter {
LimitValue limit = 1;
}
The generated code produces:
"parameters": [
{
"name": "limit.value",
"in": "query",
"required": false,
"type": "integer",
"format": "int32"
},
Any ideas on how to get around this?
Thanks!
Can I use a external file for the annotations or is it required to include these in the proto file?
Why can't msg_exists
be used for repeated fields? Since other validators can be used on repeated fields, I would expect msg_exists
to work as well.
For example, using regex on a repeated string field loops through the strings and validates each one, but using msg_exists on a repeated message field results in a warning and no validation:
message Test {
repeated string foo = 1 [(validator.field) = {string_not_empty: true}];
repeated Test bar = 2 [(validator.field) = {msg_exists: true}];
}
func (this *Test) Validate() error {
for _, item := range this.Foo {
if item == "" {
return go_proto_validators.FieldError("Foo", fmt.Errorf(`value '%v' must not be an empty string`, item))
}
}
for _, item := range this.Bar {
if item != nil {
if err := go_proto_validators.CallValidatorIfExists(item); err != nil {
return go_proto_validators.FieldError("Bar", err)
}
}
}
return nil
}
WARNING: field Test.Bar is repeated, validator.msg_exists has no effect
As mentioned in #21, it would be useful if the Validate()
method was able to return all violated validation rules on all fields. Either by invoking Validate(true)
with a param, or creating a new method ValidateAll()
for example.
This will help with vendoring.
syntax = "proto3";
import "github.com/mwitkow/go-proto-validators/validator.proto";
message FileObject {
oneof hashes {
string sha256 = 1 [(validator.field) = {regex: "[0-9a-fA-F]{64}"}];
//string md5 = 2 [(validator.field) = {regex: "[0-9a-fA-F]{32}"}];
}
}
$ protoc -I /go/src -I . --gogofast_out=. --govalidators_out=gogoimport=true:. re_test.proto
$ go build re_test.pb.go re_test.validator.pb.go
./re_test.validator.pb.go:31:7: undefined: _regex_FileObject_Sha256
It looks like the generated regex var has the name of the oneof
wrapper instead of the field itself.
var _regex_FileObject_Hashes = regexp.MustCompile("[0-9a-fA-F]{64}")
func (this *FileObject) Validate() error {
if oneOfNester, ok := this.GetHashes().(*FileObject_Sha256); ok {
if !_regex_FileObject_Sha256.MatchString(oneOfNester.Sha256) {
return go_proto_validators.FieldError("Sha256", fmt.Errorf(`value '%v' must be a string conforming to regex "[0-9a-fA-F]{64}"`, oneOfNester.Sha256))
}
}
return nil
}
Simply because Validate
is a function being defined on each struct, it means proto message with a variable called validate
will create invalid go code (it will both have a member Validate
and a function Validate
). I believe this is why gogo/protobuf
chooses functions and variables that look a bit weird (dAtA
is one).
in my message is have
string size = 2;
when i'm try to generate code
this.Size_ undefined (type *XXX has no field or method Size_)
why filed name changed from Size to Size_ ?
Currently when generating code for protofiles with oneof
message types, the code doesn't reflect what type of message it is performing the validation on, instead using the oneof
variable directly, like so:
message Value {
oneof type {
uint64 my_uint = 1 [(validator.field) = {int_gt: 0}];
}
}
func (this *Value) Validate() error {
if !(this.Type > 0) {
return github_com_mwitkow_go_proto_validators.FieldError("Type", fmt.Errorf(`value '%v' must must be greater than '0'`, this.Type))
}
return nil
}
This should instead be checking specific requirements for specific messages or variables within the oneof
struct.
The validator fails for a completely valid UUID 96733dad-7258-716b-22cb-e7963b266675
.
Google parser parses it correctly, the generated validator does not.
The regex makes several incorrect assumptions, like hat the 3rd block must start with 4, which is not the case.
Code Sample:
package main
import (
"fmt"
"regexp"
"github.com/google/uuid"
)
var _regex_GetApiTokenByClientIdRequest_ClientId = regexp.MustCompile(`^([a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[4][a-fA-F0-9]{3}-[8|9|aA|bB][a-fA-F0-9]{3}-[a-fA-F0-9]{12})?$`)
func main() {
guids := []string{"96733dad-7258-716b-22cb-e7963b266675", "89e20584-48b6-4b0b-9ce2-31e3d1125dad"}
for _, g := range guids {
_, err := uuid.Parse(g)
fmt.Printf("v1: %s - %t\n", g, err == nil)
a := _regex_GetApiTokenByClientIdRequest_ClientId.MatchString(g)
fmt.Printf("v2: %s - %t\n", g, a)
}
}
Is there any way to return error metadata (field name, validation rule and params, and actual value) on failed validation?
These metadata helps doing internationalization
Currently, the scenario is such that there is a return statement whenever a validation error occurs for any field. Can we have a feature wherein an array of errors are returned from the validate function in order to accommodate all the field errors while making a request?
If I have the example validation below and would like to remove only the validation part [(validator.field)={repeated_count_max : 100]
in the next release, would that be a breaking change?
repeated string book=1 [(validator.field)={repeated_count_max : 100}];
My guess is no since I'm not changing the field name or number.
This will probably be hilariously complicated to cover all the cases, but I thought a cool idea would be if you could have a message like this:
message MyMessage {
int32 my_int = 1;
int32 my_other_int = 2;
}
I would like to validate that my_other_int
is a certain value relative to the value of my_int
. For example:
message MyMessage {
int32 my_int = 1;
int32 my_other_int = 2 [(validator.field = { int_val: my_int / 2 })];
}
Mostly thinking out loud, and maybe this is way too complicated. Would be interested in hearing thoughts on it.
Hi, I faced next error, when i run protoc
command:
github.com/mwitkow/go-proto-validators/validator.proto: File not found.
Import "github.com/mwitkow/go-proto-validators/validator.proto" was not found or had errors.
protoc version: libprotoc 3.9.1
go version: 1.13
protoc-gen-go installed as it said in instuctions here: https://developers.google.com/protocol-buffers/docs/gotutorial via this command:
go get -u github.com/golang/protobuf/protoc-gen-go
I also installed this:
go get github.com/mwitkow/go-proto-validators/protoc-gen-govalidators
But i think this last is not related to my main problem here that I mentioned on top.
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.