Git Product home page Git Product logo

generator's Introduction

open-rpc logo

open-rpc.org

This repository contains the open-rpc.org website & tooling to deploy the website.

Need help or have a question? Join us on Discord!

Goals

  1. Knowledge Base for the community.
  2. Purpose-built to introduce new and existing users to OpenRPC.
  3. Great native-content, and minimal curated content.

Contributing

How to contribute, build and release are outlined in CONTRIBUTING.md, BUILDING.md and RELEASING.md respectively. Commits in this repository follow the CONVENTIONAL_COMMITS.md specification.

Resources

generator's People

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

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

generator's Issues

Root CLI should support multi languages

Describe the bug
Currently there is no simple way for someone to write a new client template

  • read language options from folder structure
  • provide language options in cli
  • provide configurable post template step
  • provide documentation on how to create a new generator

The code that does the templating is specific to javascript. Need to abstract in order to make it work for n many languages in the repo.

add .nojekyll to generated docs folders

Is your feature request related to a problem? Please describe.
I'm trying to serve up the docs folder for js on github and I have to add a .nojekyll empty file to the /docs folder every time for it to work on github pages

Describe the solution you'd like
Add .nojekyll to docs folders

README.md is missing from the generated client

Describe the bug
When I generate a new client. The folder containing the client should contain a README

To Reproduce
Steps to reproduce the behavior:

  1. open-rpc-generator-client -s https://raw.githubusercontent.com/etclabscore/multi-geth/0718d25e92e568f486be17123e9384ce15d8b48c/openrpc.json EthClient
  2. cd EthClient
  3. See no README.md

Expected behavior
I should see at least a generic README.md for a generated RPC client

Screenshots
image

Generate Language specific docs (TS to start)

Is your feature request related to a problem? Please describe.
If we have the typings, we can generate language specific docs now.

MVP of this issue should just use basic defaults of typedoc

.gitignore not getting copied

Describe the bug
for js client:
the .gitignore folder is not getting copied to the newly generated client

To Reproduce
Steps to reproduce the behavior:

  1. open-rpc-generator-client -s https://raw.githubusercontent.com/etclabscore/multi-geth/0718d25e92e568f486be17123e9384ce15d8b48c/openrpc.json EthClient
  2. check contents of EthClient/ folder for .gitignore
  3. See that its missing

Expected behavior
I expect it to be there since its in the static folder for the js client.

allOf for interfaceTypes is broken

Describe the bug
interfaceTypes is what sets T or I based on if we think it's an alias type or interface. When hitting an allOf in JSON-Schema, our code is not handling it properly.

To Reproduce
Steps to reproduce the behavior:

  1. open-rpc-generator-client -s https://raw.githubusercontent.com/open-rpc/examples/1b55c8c7c1a9aefc07a430ed52e2c2654eafba21/service-descriptions/petstore-openrpc.json PetStore
  2. check Petstore/index.ts
  3. See TPet is an interface but named TPet
  4. See screenshot

Expected behavior
should support allOf and show it as an Interface

Screenshots
image

Mock Mode

Is your feature request related to a problem? Please describe.
I would like to pass an option to the constructor, indicating that I want the client to run in 'mock' mode.

In mock mode, requests will not be executed against a backend. Instead, the params will be validated, looked up in examplePairings, and if not matching an example, use something like json schema faker to generate a result similar to mock server.

ts client doesnt pass rpc params properly

Describe the bug
when using the client I get argument length mismatch errors

To Reproduce
Steps to reproduce the behavior:

  1. generate a new client
  2. use client
  3. see params mismatch errors
err="too many arguments, want at most 0"

image

// => rpcParams [ 'eth_blockNumber', [] ]

additional notes

Its using Array.from(arguments) instead of using the params from the arguments

Validations dont really work

Describe the bug
Djv is not working for us. We should switch to use the more heavy handed Ajv

To Reproduce
Steps to reproduce the behavior:

  1. Go to '...'
  2. Click on '....'
  3. Scroll down to '....'
  4. See error

Expected behavior
A clear and concise description of what you expected to happen.

Screenshots
If applicable, add screenshots to help explain your problem.

Desktop (please complete the following information):

  • OS: [e.g. iOS]
  • Browser [e.g. chrome, safari]
  • Version [e.g. 22]

Smartphone (please complete the following information):

  • Device: [e.g. iPhone6]
  • OS: [e.g. iOS8.1]
  • Browser [e.g. stock browser, safari]
  • Version [e.g. 22]

Additional context
Add any other context about the problem here.

Mark files as generated

Is your feature request related to a problem? Please describe.
The lifecycle of code is unclear after generation. It should be clear that the files are generated and that you should find the source openrpc.json and edit that instead. or make a custom extension, or fork this repo and make your own generator. anything but edit the generated file directly.

Describe the solution you'd like
Golang has a convention around this:
golang/go#13560 (comment)

Also, the golang vscode extension looks for these files and pops a warning notification up saying something like: Looks like these files are generated! Do not edit

Its regex looks like this:
^// Code generated .* DO NOT EDIT\.$

I propose this (which matches the regex):

// Code generated by @open-rpc/client-generator DO NOT EDIT.

Describe alternatives you've considered
We've considered update-in-place and other management techniques, but this seems like the most universal option.

Dockerfile is broken

Describe the bug

COPY failed: stat /var/lib/docker/tmp/docker-builder846238464/client-static: no such file or directory

including the wrong directory, it should be templates

To Reproduce
Steps to reproduce the behavior:

  1. clone repository
  2. docker build .
  3. See error

Expected behavior
The docker build . should successfull execute and be able to run it

Screenshots
image

Desktop (please complete the following information):

  • OS: OSX

Some thoughts on current unresolved but defs thoughtabout issues

  1. whats the cli interface and why that and what does it produce
    • after you 'produce it', do you:
      • re-do it when you updated your schema file
      • or is there a diff command for updating the one you have
  2. when you generate, does it also creates builds of each one, or just generate the code and then you go in and compile + deploy each one
  3. does it provide a script to do this shit on aggregate for the diff languages it supports
  4. does it generate each language into the same project
  5. how do you specify what languages you want to generate clients for
    • should u just always generate them all?
  6. how do u specify the configs for each language

Create JS implementation of client generators

This will be used as the reference implementation for other languages, so it should not use complex language features that make the API impossible to implement in other languages.

cannot find module "ajv"

Describe the bug

To Reproduce
Steps to reproduce the behavior:

  1. npm -g update @open-rpc/generator-client
  2. pen-rpc-generator-client --version 1.0.28
open-rpc-generator-client \
  -s https://raw.githubusercontent.com/open-rpc/examples/master/service-descriptions/petstore-openrpc.json \
  PetStore
Error: added 67 packages from 417 contributors and audited 101 packages in 2.583s
found 0 vulnerabilities


> [email protected] build /Users/stev/PetStore
> tsc && typedoc --out docs

index.ts(3,17): error TS2307: Cannot find module 'ajv'.

    at exec (/Users/stev/.nodenv/versions/10.15.0/lib/node_modules/@open-rpc/generator-client/src/bootstrapGeneratedPackage.js:10:14)
    at ChildProcess.exithandler (child_process.js:301:5)
    at ChildProcess.emit (events.js:182:13)
    at maybeClose (internal/child_process.js:962:16)
    at Socket.stream.socket.on (internal/child_process.js:381:11)
    at Socket.emit (events.js:182:13)
    at Pipe._handle.close (net.js:610:12)

Expected behavior
I expected it to generator an open-rpc client.

Client name (& package.json name) should be derived from .info.title

Is your feature request related to a problem? Please describe.
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

Describe the solution you'd like
A clear and concise description of what you want to happen.

Describe alternatives you've considered
A clear and concise description of any alternative solutions or features you've considered.

Additional context
Add any other context or screenshots about the feature request here.

Kill old named package on npm

The package still exists on npm, and this could be confusing.

Doesnt seem like we can delete it, but we can push a new version that has a preinstall step that throws, giving a link to the properly named one.

Apache 2.0 License or a License of some kind.

Is your feature request related to a problem? Please describe.
Currently this repo does not have license. I'd like to recommend Apache 2.0 License. This idea came about when writing readme, usually license is the footer of such documentation and knowing the license status is better than not. If no License than License should be UnLicensed.

Describe the solution you'd like
When I land on the repo, I want to understand what the License is by discovering the License document in the code or reference in the Readme.

Describe alternatives you've considered
If no License than repo should state Unlicensed.

add a binary to build artifacts

Is your feature request related to a problem? Please describe.
i’d like binary build for generator-client so that i can brew or apt-get or maybe even chocolatey install the generator client as an alternative to nodejs installed.

return value for methods are wrapped in JSON-RPC response

Describe the bug
When calling a method, its return value does not match why is defined in typescript. Its wrapping its value in

{
"jsonrpc: "2.0",
"result": ...,
"id": ...
}

To Reproduce
Steps to reproduce the behavior:

  1. Generate Client
  2. call method promise
  3. try to use result according to typescript

Expected behavior
should not wrap the result in the JSON-RPC response

Make the pattern easier and more repeatable for other language generators.

Is your feature request related to a problem? Please describe.
The goal is to have generators for many languages. To make it easier for people to contribute, we need to evaluate the current architecture, and try to find one that makes more sense for the average joe looking to spend an hour and contribute.

Describe the solution you'd like
move the cli and scripts from JS folder into the root. Make a new folder for each languages template files. Document generic 'flow' or 'steps' that are taken, and how one might write a compliant generator in a different language.

Describe alternatives you've considered

  • each language free for all - the only interface is the cli, but you implement it urself in each language

Additional context
Add any other context or screenshots about the feature request here.

readme has incorrect generate client path

Describe the bug
Readme specifies incorrect path.

open-rpc-generator-client \
  -s https://raw.githubusercontent.com/open-rpc/examples/master/service-descriptions/petstore.json \
  PetStore

should be:

open-rpc-generator-client \
  -s https://raw.githubusercontent.com/open-rpc/examples/master/service-descriptions/petstore-openrpc.json \
  PetStore

Can't run with `tsc --init` defaults

Describe the bug
Using the client-generator in a new project via tsc --init. fails to import with type errors.

Expected behavior
Allow user to import generated client library in their tsc --init'd projects

Possible Solution
add noImplicitAny: true and strict: true to js/static/tsconfig.json

Automated tests to ensure build is working

Problem

We should have a more clear distinction between testing contexts. Further, the tests should catch issues that would otherwise result in a build that is horrifically broken being published. The goal is not to have perfect test coverage so that we never ship a single bug, cause we would be at this for a life time. The goal is to never ship a version of this tool that doesn't work at all.

Solution

I propose a list of testing steps, going in order of "Fail Fast As Possible" - The time it takes for each group of test to pass must be increasing.

Linting

Linting will catch syntax errors and various small issues. It's the fastest type of test, and so we run this first.

We should not give warnings - only errors. If it's not worth being an error, then don't use the rule.

Unit Tests

Unit tests mock out any type of IO, as well as dependent modules. Unit tests test individual exported methods to ensure that their interfaces are upheld, and that any logic that the function is implementing is documented via a use case formatted unit test.

Ex of good unit test case:

it("returns null if you try to divide by zero", () => { ... })

Ex of bad unit test case

("it doesn't divide by zero", () => { ... });

Integration Tests

Integration tests are the most intensive test, and will generally take much longer than the others. They should test this tool from end to end, using the filesystem and everything just as a user would.

Integration tests should accomplish the following main points.

Make a build

The integration tests should use the built code, and should not run via ts-jest, but rather as nodejs targeted javascript.

Generating clients from examples

Using build/bin/cli.js, run the generator against each of the examples found in @open-rpc/examples. Write each generated client to the test/ directory.

Integration Testing the generated clients in each language

For each generated example client, we must ensure that each language's client is functioning as intended. To do this, we must start a mock server, and run the language-specific integration test script.

  1. node_modules/.bin/open-rpc-mock-server -s { "openrpc": "1.0.0-rc1", ... } -p 6969
  2. ./test/${exampleName}/${language}/bin/test.integration.sh.

To make this work, we obviously need to add a file to each templates/{language}/static/bin/ a test.sh script that would run tests in the particular language-specific way.

Language Specific Integration Tests

The generated client for each language should have a tests suite that is generated alongside it. This means that the language specific client implementation MUST make provisions to generate these tests. Since each language has its own tools for testing, each language implementation must have an integration test script that follows the naming convention:

./test/${exampleName}/${language}/bin/test.integration.sh.

Once the script is run, the language specific tests should test the following:

Changes to generator-client's package.json

  1. This will add the following "scripts" to the root package.json:
{
  "test": "jest --coverage",
  "test:unit": "jest ./src",
  "test:integration": "jest ./integration-tests"
}
  1. Requires generating a 'test application' alongside each client, which will template the calls to each method, asserting the result is correct.

IBROKEN and TBROKEN should not exist or error

Describe the bug
When using the generator it is possible to generate IBROKEN and TBROKEN interfaces and type aliases.

To Reproduce
Steps to reproduce the behavior:

  1. open-rpc-generator-client -s https://raw.githubusercontent.com/etclabscore/multi-geth/0718d25e92e568f486be17123e9384ce15d8b48c/openrpc.json EthClient
  2. check out the index.ts
  3. See IBROKEN and TBROKEN for some types and interfaces

Expected behavior
I should not see anything that says BROKEN

rust generator-client fails on multi-geth openrpc.json

Describe the bug
When I try to generate a client with mutli-geth's openrpc.json I get errors

To Reproduce
Steps to reproduce the behavior:

  1. open-rpc-generator-client -s https://raw.githubusercontent.com/etclabscore/multi-geth/feat/openrpc/openrpc.json MultiGethRpc
  2. See error output below

Expected behavior
I expect no errors and get a client output in the specified directory

Additional context

➜  MultiGethRpc git:(master) ✗ npm run generateclient

> [email protected] generateclient /Users/shanejonas/scratch/test-eth-rpc
> open-rpc-generator-client MultiGethRpc

Error:     Updating crates.io index
   Compiling proc-macro2 v0.4.27
   Compiling unicode-xid v0.1.0
   Compiling syn v0.15.30
   Compiling autocfg v0.1.2
   Compiling libc v0.2.51
   Compiling serde v1.0.90
   Compiling ryu v0.2.7
   Compiling cfg-if v0.1.7
   Compiling itoa v0.4.3
   Compiling rustc-demangle v0.1.13
   Compiling futures v0.1.26
   Compiling log v0.4.6
   Compiling backtrace v0.3.15
   Compiling log v0.3.9
   Compiling quote v0.6.12
   Compiling error-chain v0.12.0
   Compiling serde_derive v1.0.90
   Compiling serde_json v1.0.39
   Compiling jsonrpc-core v8.0.1
   Compiling jsonrpc-client-core v0.5.0
   Compiling template-client v1.0.0 (/Users/shanejonas/scratch/test-eth-rpc/MultiGethRpc/rs)
error[E0252]: the name `HashMap` is defined multiple times
  --> src/lib.rs:79:5
   |
27 | use std::collections::HashMap;
   |     ------------------------- previous import of the type `HashMap` here
...
79 | use std::collections::HashMap;
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^ `HashMap` reimported here
   |
   = note: `HashMap` must be defined only once in the type namespace of this module
help: you can use `as` to change the binding name of the import
   |
79 | use std::collections::HashMap as OtherHashMap;
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0252]: the name `HashMap` is defined multiple times
  --> src/lib.rs:96:5
   |
27 | use std::collections::HashMap;
   |     ------------------------- previous import of the type `HashMap` here
...
96 | use std::collections::HashMap;
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^ `HashMap` reimported here
   |
   = note: `HashMap` must be defined only once in the type namespace of this module
help: you can use `as` to change the binding name of the import
   |
96 | use std::collections::HashMap as OtherHashMap;
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0428]: the name `Address` is defined multiple times
   --> src/lib.rs:198:1
    |
114 | pub type Address = String;
    | -------------------------- previous definition of the type `Address` here
...
198 | pub enum Address {
    | ^^^^^^^^^^^^^^^^ `Address` redefined here
    |
    = note: `Address` must be defined only once in the type namespace of this module

error[E0428]: the name `TransactionElement` is defined multiple times
   --> src/lib.rs:234:1
    |
220 | pub enum TransactionElement {
    | --------------------------- previous definition of the type `TransactionElement` here
...
234 | pub enum TransactionElement {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `TransactionElement` redefined here
    |
    = note: `TransactionElement` must be defined only once in the type namespace of this module

error[E0428]: the name `_IMPL_DESERIALIZE_FOR_TransactionElement` is defined multiple times
   --> src/lib.rs:232:21
    |
218 | #[derive(Serialize, Deserialize)]
    |                     ----------- previous definition of the value `_IMPL_DESERIALIZE_FOR_TransactionElement` here
...
232 | #[derive(Serialize, Deserialize)]
    |                     ^^^^^^^^^^^ `_IMPL_DESERIALIZE_FOR_TransactionElement` redefined here
    |
    = note: `_IMPL_DESERIALIZE_FOR_TransactionElement` must be defined only once in the value namespace of this module

error[E0428]: the name `_IMPL_SERIALIZE_FOR_TransactionElement` is defined multiple times
   --> src/lib.rs:232:10
    |
218 | #[derive(Serialize, Deserialize)]
    |          --------- previous definition of the value `_IMPL_SERIALIZE_FOR_TransactionElement` here
...
232 | #[derive(Serialize, Deserialize)]
    |          ^^^^^^^^^ `_IMPL_SERIALIZE_FOR_TransactionElement` redefined here
    |
    = note: `_IMPL_SERIALIZE_FOR_TransactionElement` must be defined only once in the value namespace of this module

error: no rules expected the token `>`
   --> src/lib.rs:857:78
    |
857 |     pub fn eth_getFilterChanges(&mut self, filterId: FilterId) -> RpcRequest<>;
    |                                                                              ^ no rules expected this token in macro call

warning: unused import: `std::collections::HashMap`
  --> src/lib.rs:79:5
   |
79 | use std::collections::HashMap;
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
   |
   = note: #[warn(unused_imports)] on by default

warning: unused import: `std::collections::HashMap`
  --> src/lib.rs:96:5
   |
96 | use std::collections::HashMap;
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0119]: conflicting implementations of trait `serde::Deserialize<'_>` for type `std::string::String`:
   --> src/lib.rs:196:21
    |
196 | #[derive(Serialize, Deserialize)]
    |                     ^^^^^^^^^^^
    |
    = note: conflicting implementation in crate `serde`:
            - impl<'de> serde::Deserialize<'de> for std::string::String;

error[E0119]: conflicting implementations of trait `serde::Deserialize<'_>` for type `TransactionElement`:
   --> src/lib.rs:232:21
    |
218 | #[derive(Serialize, Deserialize)]
    |                     ----------- first implementation here
...
232 | #[derive(Serialize, Deserialize)]
    |                     ^^^^^^^^^^^ conflicting implementation for `TransactionElement`

error[E0119]: conflicting implementations of trait `serde::Serialize` for type `std::string::String`:
   --> src/lib.rs:196:10
    |
196 | #[derive(Serialize, Deserialize)]
    |          ^^^^^^^^^
    |
    = note: conflicting implementation in crate `serde`:
            - impl serde::Serialize for std::string::String;

error[E0119]: conflicting implementations of trait `serde::Serialize` for type `TransactionElement`:
   --> src/lib.rs:232:10
    |
218 | #[derive(Serialize, Deserialize)]
    |          --------- first implementation here
...
232 | #[derive(Serialize, Deserialize)]
    |          ^^^^^^^^^ conflicting implementation for `TransactionElement`

error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
   --> src/lib.rs:196:21
    |
196 | #[derive(Serialize, Deserialize)]
    |                     ^^^^^^^^^^^ impl doesn't use types inside crate
    |
    = note: the impl does not reference only types defined in this crate
    = note: define and implement a trait or new type instead

error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
   --> src/lib.rs:196:10
    |
196 | #[derive(Serialize, Deserialize)]
    |          ^^^^^^^^^ impl doesn't use types inside crate
    |
    = note: the impl does not reference only types defined in this crate
    = note: define and implement a trait or new type instead

error: aborting due to 13 previous errors

Some errors occurred: E0117, E0119, E0252, E0428.
For more information about an error, try `rustc --explain E0117`.
error: Could not compile `template-client`.

To learn more, run the command again with --verbose.

    at /Users/shanejonas/scratch/test-eth-rpc/node_modules/@open-rpc/generator-client/build/src/bootstrapGeneratedPackage.js:19:20
    at ChildProcess.exithandler (child_process.js:283:5)
    at emitTwo (events.js:126:13)
    at ChildProcess.emit (events.js:214:7)
    at maybeClose (internal/child_process.js:915:16)
    at Socket.stream.socket.on (internal/child_process.js:336:11)
    at emitOne (events.js:116:13)
    at Socket.emit (events.js:211:7)
    at Pipe._handle.close [as _onclose] (net.js:561:12)
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] generateclient: `open-rpc-generator-client MultiGethRpc`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] generateclient script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     /Users/shanejonas/.npm/_logs/2019-04-12T05_35_23_030Z-debug.log

Transports for js client: no browser support, no websocket support

Describe the bug
There is no browser support for jayson out of the box, and also no websocket support.

To Reproduce
Steps to reproduce the behavior:
1.build a client
2. try to use it in browser
3. errors on jayson.Client node-fetch

Expected behavior
I would expect it to work out of the box in the browser

content descriptors with same name but diff schema

Describe the bug
We need a way of dealing with the case where 2 content descriptors share the same name, but have different schemas. This is for obvious reasons quite an anti pattern for api design, but none-the-less we should handle it more gracefully than just having linting fail.

Error: Cannot find module '../templates/js/templated/exported-class.template.js'

Describe the bug
Error: Cannot find module '../templates/js/templated/exported-class.template.js'

To Reproduce
Steps to reproduce the behavior:

  1. npm install -g @open-rpc/generator-client
  2. open-rpc-generator-client -s https://raw.githubusercontent.com/etclabscore/multi-geth/0718d25e92e568f486be17123e9384ce15d8b48c/openrpc.json EthClient
  3. See error screenshot

Expected behavior
Should build a client no errors

Screenshots
image

Desktop (please complete the following information):

  • OS: OSX
  • Browser [e.g. chrome, safari]
  • Version 1.0.25

Remove Jayson

Describe the bug
Jayson is a complete piece of shit, and it's downright embarrassing that it's the current 'best' json-rpc lib on NPM. The maintainer is incompetent, and has demonstrated his inability to maintain the project. tedeh/jayson#131

We need to build a new one so we can provide proper support for JSON-RPC.

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.