asyncapi / spec Goto Github PK
View Code? Open in Web Editor NEWThe AsyncAPI specification allows you to create machine-readable definitions of your asynchronous APIs.
Home Page: https://www.asyncapi.com
License: Apache License 2.0
The AsyncAPI specification allows you to create machine-readable definitions of your asynchronous APIs.
Home Page: https://www.asyncapi.com
License: Apache License 2.0
My goal is to define a default header (with QoS, retain etc) that I want to specify in detail with more properties:
headers:
$ref: "#/components/schemas/subscribe_header"
properties:
userProperties:
[...]
If I am not wrong this is a new feature of the json schema draft 08, which is not yet released (but I might have missunderstood, so please check!). It should be considered to be used.
json-schema-org/json-schema-spec#628
json-schema-org/json-schema-spec#523
https://github.com/asyncapi/asyncapi#serverVariableObject
I want to specify additional variables for connecting to the MQTT broker: username and password. I want to provide a sample for the username, e.g. "MyUsername". Examples should be always inside an array.
Do you think that is useful? One could work around this by adding additional description text.
Hi, it's not technical question. But I think is related with this repo.
Why if it's an Open protocol project page is on a .com
domain and on .org
. I see other projects using it. Ex.:
Thanks and sorry if it's a dump question
You're doing a great work 👏
The AsyncAPI Specification is licensed under The Apache License, Version 2.0.
This is great as OAS is also under Apache 2.0, but is it correct that package.json
states MIT?
Most standards that evolve quickly, follow innovation and adoption of the developers using those standards and the extensions they add. I realise the AsyncAPI spec does already support extensions in the form x-*
, which is a good common convention.
However, looking specifically at server.scheme
, it states:
"REQUIRED. The scheme this URL supports for connection. The value MUST be one of the following: kafka, kafka-secure, amqp, amqps, mqtt, secure-mqtt, ws, wss, stomp, stomps, jms".
I have seen a lot of other popular protocols being used such as Socket.io (loosely equivalent to ws I suppose), Nats (similar to STOMP/AMQP), Faye etc. and even some proprietary protocols that are popular.
Do you think it would be sensible to change this to:
"REQUIRED. The scheme this URL supports for connection. The value MUST be one of the following: kafka, kafka-secure, amqp, amqps, mqtt, secure-mqtt, ws, wss, stomp, stomps, jms, or may include an unsupported scheme as an extension in the format x-[scheme]
."
I would assume that there is really no need to even specify that x-[scheme]
may not be supported by the consumer, as the spec itself does not require that every scheme is supported anyway by every consumer as that would make it impractical for anyone to implement a client.
WDYT?
Hello, I encountered a possible bug if I try to put multiple parameters/variables in a single topic.
For example creating a topic as event.{streetlightId}.lighting.{banana}.measured
I get .event.:streetlightId}.lighting.{banana.measured
on the rendered page.
I suppose multiple params are not supported yet, right?
I noticed there is no construct for an exchange in AMQP. It would be nice to have that explicitly called out somehow.
I cannot find a way where I can define the description and possible values for parameters/variables in topics, eg:
topics:
v1/sb/{did}/telemetry/{id}:
subscribe:
$ref: "#/components/messages/telemetry"
In this case I would like to specify what are did
and id
.
Is the best practice doing this in the topic description?
Right now, AsyncAPI does not specify how callback messages should be described.
Some ad-hoc approaches can be used. For instance:
Hence, for convenience and clarity reasons, a structural callback-specification approach similar to the one proposed in OpenAPIv3 (cfr. spec + example) might be interesting for AsyncAPI as well?
It could look like this:
topics:
UPDATEARTICLE:
publish:
headers:
type: object
properties:
reply-to:
type: string
description: Callback Destination to be messaged when the Article was updated
correlation-id:
$ref : '#/components/schemas/Correlation-id'
payload:
type: object
properties:
...
callbacks:
reply:
'{$request.header.reply-to}':
publish:
summary: Reply sent through callback
headers:
type: object
properties:
correlation-id:
$ref : '#/components/schemas/Correlation-id'
payload:
type: object
properties:
success:
type: boolean
statusMsg:
type: string
Thanks in advance for considering this feature request!
Right now you can define the host and schemes your API supports the following way:
host: api.company.com
schemes:
- amqp
- mqtt
However, most of the times the schemes are on different ports than the default ones. Or even in different hosts. We should be able to specify how and where to connect with each of the schemes.
Proposal:
schemes:
amqp:
host: api.company.com
port: 1122
mqtt:
host: api.company.com
port: 5676
It will allow us to include more valuable information too, i.e.:
schemes:
mqtt:
host: api.company.com/{app-id}
port: 5676
description: Allows you to connect using the MQTT protocol.
parameters:
app-id:
description: You can find your `app-id` in our control panel, under the auth tab.
required: true
in: path
token:
description: You can find or generate your API `token` in our control panel, under the auth tab. If the token is not specified you'll only have subscribe permissions.
required: false
in: query
What do you think?
https://github.com/asyncapi/asyncapi#specification-extensions
The current pattern is defined as ^x-
But I think it should rather be ^x-.*
?
This is also wrongly defined in the json schema. I am wondering if you evenuse it for validation. If yes, there must be something wrong I guess.
where the necessary streetlightId
parameter is only defined for one topic, but it would be useful to be able to $ref
a re-usable Parameter Object
If approved will target a PR at ... v1.2.0 ?
There are a variety of message brokers that implement an even larger variety of messaging protocols.
The transfer protocols listed does not appear to be complete to me. At first it occurred to me that it was missing 0mq, nanomsg and some others so I searched further.
A quick set of internet searches returned: SMTP, HTTP, JMS, AMQP, STOMP, XMPP, MQTT, and OpenWire
I would be interested in trying to complete this list if there is interest.
There are a variety of message brokers that implement an even larger variety of messaging protocols.
Kafka is well adopted today within the Apache Software Foundation ecosystem of products and is particularly useful in event-driven architecture.
RabbitMQ is designed as a general purpose message broker, employing several variations of point to point, request/reply and pub-sub communication styles patterns. It uses a smart broker / dumb consumer model, focused on consistent delivery of messages to consumers that consume at a roughly similar pace as the broker keeps track of consumer state.
"enum": [
"kafka",
"kafka-secure",
"amqp",
"amqps",
"mqtt",
"mqtts",
"secure-mqtt",
"ws",
"wss",
"stomp",
"stomps"
]
AsyncAPI tries to stay close in approach to OpenAPI in terms of formats and design decisions.
There's already another issue (#1) considering serialization formats other than JSON-schema (or xml extensions). I think the payload format definition should be completely left out. OpenAPI's support for JSON-schema and xml is limiting and JSON-schema in particular is a bit messy.
There are several serialization definition formats quite more popular for message passing than json. See Avro (#1), Google's protocol buffers or thrift (in its varied protocols)
IANA service name for secure MQTT is secure-mqtt
and not mqtts
.
This:
servers:
- url: api.company.com
scheme: mqtts
should become this:
servers:
- url: api.company.com
scheme: secure-mqtt
When I attempt to include anyOf
in Async API editor a schema definition I get the following:
[ { "code": "OBJECT_ADDITIONAL_PROPERTIES", "params": [ [ "anyOf" ] ], "message": "Additional properties not allowed: anyOf", "path": "#/components/schemas/DirectDebit/allOf/1", "schemaId": "http://asyncapi.hitchhq.com/v1/schema.json#", "description": "A deterministic version of a JSON Schema object." } ]
However I can't see anywhere in the documentation that says anyOf
is specifically excluded.
Please can you clarify where anyOf is supported or not? Thanks.
Right now, AsyncAPI is missing a way to document the payloads' media type (e.g., JSON, XML, ...).
Can the specification be enriched to make this possible?
The approach for documenting media types could be similar to the one proposed in the OpenAPI specifications (v2 & v3):
The AsyncAPI Object could be extended with a 'defaultPayloadMediaType' property that allows to specify the default payload media type (e.g., with "application/json" as default value).
The type of the Message.payload property could be changed to "Map[string (media type), Schema Object] | Schema Object", which allows the default payload media type to be overridden at the payload-level.
This would allow API specifications such as:
asyncapi: '1.0.0'
...
defaultPayloadMediaType: text/xml
topics:
X:
publish:
payload:
type: object
properties:
...
J:
publish:
payload:
application/json:
type: object
properties:
...
O:
subscribe:
payload:
application/x-java-serialized-object:
type: object
properties:
...
Thanks in advance for considering this feature request!
Found by mdv, which runs as part of the OAS CI task.
{ source: 'README.md',
missingAnchors:
[ { name: 'componentsObject', defined: 0, seen: 1 },
{ name: 'dataTypeFormat', defined: 0, seen: 1 },
{ name: 'referenceObject', defined: 0, seen: 1 } ] }
Happy to raise a PR to add a CI step. I think all of the above need sections adding to the spec or links created to a version of the OAS spec?
im trying to update my api with http://editor.asyncapi.org/
I get the errormessage:
Your schema contains $ref. You must provide specification in the third parameter.
Can you please clarify the meaning of that message?
I created the spec back at the 16.03.2018 at that time the document was considered valid.
From the site:
asyncapi: '1.0.0'
info:
title: 'Sign up email example'
version: '1.0.0'
baseTopic: 'hitch'
host: 'asyncapi.hitchhq.com'
schemes:
- 'amqp'
- 'mqtt'
topics:
accounts.1.0.event.user.signup:
subscribe:
$ref: '#/components/messages/userSignedUp'
email.1.0.event.email.sent:
publish:
$ref: '#/components/messages/emailSent'
I think this spec can be seen from two points of view:
asyncapi.hitchhq.com
and anyone may freely use them. With this approach, a consumer of the UserService
(a service consuming from a public topic and emitting into a topic only available in the company private network) may need to read the spec of public.asyncapi.hitchhq.com
and also private.asyncapi.hitchhq.com
.host
and schemes
on each topic since a service may accept incoming commands via unencrypted channels (mqtt
) but only emit events via encrypted ones (mqtts
).Sometimes to you want to deprecate a message.
The xml example/test document uses the xml object on a root schema.
From the spec.
This MAY be used only on properties schemas. It has no effect on root schemas. Adds Additional metadata to describe the XML representation format of this property.
It may be worth following the discussion here to see how a similar issue gets resolved in the OAS, or simply clarifying the wording in AsyncAPI to allow this.
Would it be a good idea for AsyncAPI to support built-in correlation ids to enable distributed tracing ?
I would see this as a (optional?) parameter correlationId under #/definitions/operation. The value of this parameter must be the name of one of properties defined in the message schema for the operation.
Automated tracing tools could be implemented with no knowledge of the internal implementation behind the APIs (these tools can listen to publish topics and aggregate on the values of correlationId). Clients of subscribe topics would be aware of the correlation semantics of a particular property in the message they must send to the subscriber of the topic.
As Phil Sturgeon pointed out in his articles (this and this), the divergence between JSON Schema and OpenAPI schema (which AsyncAPI is identical to) is causing some problems.
At this point, given that AsyncAPI is still in its early stages and I'm collecting breaking changes for version 2.0.0, I wonder if it would be a good idea to make AsyncAPI schemas conform to a more recent JSON Schema version (maybe 6 or 7?).
As an addition, we could also implement the alternate-schema
keyword proposed here (without the x-oas-draft
). But, IMHO, that's another issue.
Thoughts? @MikeRalphson @bpedro @philsturgeon @darrelmiller
Right now, a complete topic name is described by both the baseTopic value and a topics.topic value. More specifically, a complete topic name is actually the baseTopic value suffixed by a topics.topic value and separated by a dot.
For instance, in:
baseTopic: my.base.topic
topics:
anEvent
subscribe: ...
the topic my.base.topic.anEvent is described.
This way of composing the baseTopic and topics.topic values is quite rigid and does not allow for a lot of flexibility (i.e., it fixes the order of composition and the separator). Hence, we'd like to propose the introduction of a fixed variable that can be used in the baseTopic value and can be considered to be substituted for the topics.topic value in order to obtain the complete topic name (e.g., a predefined {t} variable).
For instance, in:
baseTopic: my/base/topic/{t}/v1
topics:
anEvent
subscribe: ...
this would allow the topic my/base/topic/anEvent/v1 to be described.
Thanks in advance for considering this feature request!
Is this a new version of the spec, or a 1.1 revision of the 1.0.0 spec?
I.e. is a topic parameter valid in an asyncapi document which uses asyncapi: 1.0.0
?
Howdy!
I was pointed towards AsyncAPI by @darrelmiller.
I'm the developer lead on AutoRest which we write to generate clients for OpenAPI (2.0 right now, 3.0 very soon) in Python, C#, Java, Ruby, Go, JavaScript, Typescript, PHP, (with support for directly generating PowerShell and others on the way)
We're investigating the possibility of generating clients and services for other protocols (ie, AMQP, MTTP, JSON-RPC, etc...) for a variety of purposes. The goal would be to extend AutoRest to be able to generate code for these purposes for all the languages that we support.
At the current point, AutoRest performs a 'modeling' stage in the pipeline where we generate an abstraction of the HTTP REST methods that generators use to spit out code (the
CodeModel
). This enables us to have a common means to 'interpret' the OpenAPI spec and produce like clients on each of the languages (and publish the SDK for each.)
We currently use this to generate 70+ SDKs for Azure services, across 7 or so languages.
The currentCodeModel
is a miserable abstraction that was the result of early developers hacking their way thru the process, with little thought to expansion or reusability.
So, we're looking at the next-generation means of supporting a better abstraction, and our initial thought was to stick to OpenAPI 3 as close as possible, with additional metadata on top of that, which would impact the code generation process.
Of course, we then started thinking about adding support for other protocols, and abstracting the thought a bit further; ideally the basic information about a given call should be reusable as possible, so that the individual generators could do the most with the least amount of effort to process the CodeModel
.
My initial thoughts (before coming to AsyncAPI) with this was to simply use OpenAPI3 and substitute out the HTTP method (POST/PUT/GET/DELETE/etc) for a scheme
:method
representation so I'd end up with things like json-rpc:notification
and json-rpc:request
and substitute out the PATH
for the routing key (aka, the Topic
)
Now, it appears that you're kinda going down a similar route; except that you've created an alternate scheme
and then referred to subscribe
and publish
(which would be just fine for me, and and probably better)
I've done a cursory examination of AsyncAPI and it seems really closely aligned with OpenAPI (duh!)
I was curious about how closely you've modeled things -- ie, could I add in a HTTPS
scheme and additional topic-style methods
for POST/GET/PUT/DELETE
etc and model something that was incredibly close to OpenAPI v3's REST?
It feels like there could be a fairly concrete unified schema that could be then further narrowed for purpose-driven schemas (like OpenAPI).
I saw that you've also talked about supporting other "payload format definitions" and other such things. I'd like to understand what you're thinking of here. Perhaps the concept of a larger unified schema could be useful in collecting the vast array of possibilities, while still retaining the ability to have a narrower 'profile' schema that applies to a given protocol/payload (and has all the necessary restrictions to model an API for just that) (think of it like the relationship that SGML is to HTML, XML and XAML)
Ideally, I'd like to be able to support protocols/payloads/languages as all pluggable. AutoRest's pipeline is entirely configurable to support any range of these types of things. We're probably only three good days work away from stopping it from being 'swagger-focused' and loosening it up to any kind of incremental transformation. The bit that I'm trying to solve only once is the 'unified specification definition'.
It's not even necessary that the 'unified' description be end-user usable (after all, who actually uses SGML itself, right?), but perhaps as a means to drive purpose-driven specification description languages.
AMQP, STOMP, MQTT, and others all have variations in the message structure.
I wanted to suggest that you consider the idea of protocol specific message objects or protocol specific message object properties, that embrace the individuality and uniqueness of each protocol's message specification.
In addition, the variations between AMQP 0.9 and 1.0 are enough to warrant protocol version disambiguation.
Have you previously put any thought into this? As someone who's a fairly invested in AMQP 0.9, I'd love to see more detail in that area than what the spec currently provides.
I my topic tree I always have a variable called "serial":
topics:
event.teltonika.{serial}.mobile.bytes_received:
parameters:
- $ref: "#/x-definitions/serial_parameter"
subscribe:
[...]
x-definitions:
serial_parameter:
name: "serial"
description: "Serial number of the router. Serial number can be taken from the device or via the command: `uci get hwinfo.hwinfo.serial`."
schema:
type: "string"
title: "Serial number"
description: "Serial number, usually 8 digests long."
example: "01234567"
I want to use the parameters defintion of serial more often, so I needed to place it somewhere else. I found out, that I have no chance to put it under any subtype of the components section. So I used a self defined x-definitions
.
Now my question is: Am I missing something, is there a better way to do this task? If not, what about adding a place for such definitions?
Dunno if the spec helps: https://tools.ietf.org/html/rfc7464#section-2.2
I'm thinking about how to beef up the documentation/description of an endpoint that delivers information this way...
The general shape of the endpoint is already described in OpenAPI (Swagger) 2.0, but it doesn't give a good way to describe the several type of JSON objects emitted.
After thoroughly reading the specification I was curious if it was intentional to only allow one message per subscribe or publish on a given topic item.
It seems to dictate a high level of verbosity related to topics that could be simplified in async apis that are primarily used for realtime updates via subscriptions. The specific scenario I am referring to is having a single topic that is used to publish multiple messages to subscribers -- similar to chat rooms.
Clarity in intention or thinking would be greatly appreciated.
It's very useful to have a title and a name in the message object. The name would represent an identification of the object, e.g., User
. The title allows you to have a human-friendly name for the message, e.g., The User
.
In this PR, support for mqtts
was deprecated in favor of secure-mqtt
. In v2 we should totally remove it from the schema file.
Hey folks,
Many public async APIs use "web" protocols like HTTP (streaming, webhooks) and WebSockets. For example: Twitter, Slack, Stripe. I'm not sure, but I think it could make sense for these kinds of APIs to be supported in the AsyncAPI spec.
It looks like AsyncAPI does have some support for WebSockets, although I'm not sure if it would work for Slack's API which establishes listening criteria based on the WebSocket URL (no subsequent subscribe handshake).
In cases like Slack and also Twitter (which uses resource-oriented HTTP streaming), "pubsub" concepts are somewhat diminished even if the APIs are likely powered by pubsub tech behind the scenes. That is, the APIs may not necessarily discuss brokers, topics, subscriptions, etc. I'm not sure if this should necessarily affect AsyncAPI, but worth thinking about.
It looks like webhooks are supported by OpenAPI lately:
https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#callback-object
So maybe nothing needs to be done in AsyncAPI about webhooks. It is a little strange to me how the specs are divided on what async transports to support, so I include it here for completeness.
It is common to have many servers for the same stage (dev, test, acc, ..), the variable substitutions into the server object can help but the substitution can also be problematic when there is some restriction on what can be substituted.
A solution is to create different servers however, there is nothing to group them and to restrict the usage of servers from different stages.
I can be interesting to have a group
attribute in server:
Configuration:
Current:
servers:
- url: dev-master-{node}:1234
variables:
node:
enum:
- '1'
- '2'
- url: dev-slave-{node}:4321
variables:
node:
enum:
- '1'
- '2'
- url: test-master-{node}:1234
variables:
node:
enum:
- '1'
- '2'
- url: test-slave-{node}:4321
variables:
node:
enum:
- '1'
- '2'
Proposal:
servers:
- url: dev-master-{node}:1234
group: dev
variables:
node:
enum:
- '1'
- '2'
- url: dev-slave-{node}:4321
group: dev
variables:
node:
enum:
- '1'
- '2'
- url: test-master-{node}:1234
group: test
variables:
node:
enum:
- '1'
- '2'
- url: test-slave-{node}:4321
group: test
variables:
node:
enum:
- '1'
- '2'
Currently covering our topics with this and it would be great to have some official SNS support
edit: incorrectly used sqs
instead of sns
The base topic are defined as strings:
https://github.com/asyncapi/asyncapi#baseTopicString
Normal topics are not allowed to start with a dot:
https://github.com/asyncapi/asyncapi#topicsObject
Now a few things are unclear that should be added to the documentation (explanation) or specification:
company/users/{userid}/{commands}
or company/device/{serialnumber}/{commands}
. That is a valid usecase I need.HTTP and HTTPS schemes are missing in human-readable documentation, i.e., in the README.
After a some researches about "how to document message-driven communication", I found your framework which looks very good but There is something that I don't understand...
I am beginner in the "message driven" way of communication but today I have an app using websockets and I didn't sucess to write the spec using asyncapi.
A simple example to display a list of filtered users:
Every call is asynchrone. So I tried to specify that using the asyncapi format:
asyncapi: '1.0.0'
info:
title: 'User Api'
version: '1.0.0'
topics:
company.user.1.0.event.getall:
publish:
$ref: '#/components/messages/requestAllUsers'
company.user.1.0.event.getall.succeed:
publish:
$ref: '#/components/messages/responseAllUsers'
components:
messages:
requestAllUsers:
summary: 'Request the list of Users'
payload:
type: 'object'
properties:
status:
type: 'string'
responseAllUsers:
summary: 'Return the list of Users'
payload:
type: 'array'
items:
$ref: '#/components/schemas/user'
schemas:
id:
title: 'id'
description: 'Resource identifier'
type: 'string'
name:
title: 'name'
description: 'Resource name'
type: 'string'
user:
type: 'object'
required:
- 'id'
- 'name'
properties:
id:
$ref: '#/components/schemas/id'
name:
$ref: '#/components/schemas/name'
What I misunderstand is the link between request message and response message. In your singup example, I am mixing the role of the "accounts.1.0.event.user.signup" message. It look like the reponse message but it's a topic that we should subscribe....
After all steps in your tutorial (www.asyncapi.com/v1/tutorial/), after running 'npm start' it throws an error like '
const adapter = hermesMQTT({
^
TypeError: Class constructor MqttAdapter cannot be invoked without 'new'
'. What is missed from my side?..
Hi,
We would like to use AsyncAPI to describe asynchronous messaging services that are exposed over JMS
and would therefor like to be able to specify 'jms' as a value for server.scheme.
Protocol-specific message details, as proposed in #42 , are initially not required. Mapping from an AsyncAPI description to JMS constructs by convention already brings us pretty far.
Thanks in advance for considering this feature!
Many async APIs out there have proved to support different protocols for the same API. For instance, they might support using WebSockets and MQTT, HTTP streaming and WebSockets, etc.
The way you authenticate to these APIs depend very much on the protocol, so I think it would make sense to attach the security requirement to the server you're connecting to.
Example:
servers:
# This server supports connecting using user-password or X509 certificate
- url: async.api.com:1883
scheme: mqtt
securityRequirements:
- X509Certificate
- userPass
# This server only supports connecting using user-password
- url: async.api.com
scheme: amqp
securityRequirements:
- userPass
components:
securitySchemes:
userPass:
type: userPassword
X509Certificate:
type: X509
Right now the security requirements are at the root level, making it impossible to guess which server supports which security scheme.
So the idea is to have an attribute that can identify what attribute to call when a message is pulled from the queue.
components:
messages:
HelloWorld:
summary: Hello World
payload:
type: object
properties:
arga:
type: string
argb:
type: string
x-operation-id: "helloworld.say"
Where Helloworld is a python file and say is a method in it
A sample function for calling the operation would look like this
def callmethod(self, message, **kwargs):
try:
if 'x-osperation-id' in self._config['components']['messages'][message].keys():
methodlookup = self._config['components']['messages'][message]['x-operation-id']
library, func = methodlookup.rsplit('.', 1)
i = importlib.import_module(library)
method_to_call = getattr(i, func)
return method_to_call(**kwargs)
except Exception as e:
raise e
return None
Kafka uses its own protocol and it should be pretty easy to support it.
https://github.com/asyncapi/asyncapi/blob/develop/test/docs/sample.yml#L9
You can specify the terms of service here. It supports Markdown as well.
Should be
A URL to the Terms of Service for the API.
OpenAPI 3.0.0 adds to the field description:
MUST be in the format of a URL.
The specs seem to focus on events emitted. Will there be support to document commands, too?
For instance, AQMP 0-9-1 differs a lot from AMQP 1.0. It's actually a totally new protocol.
Example:
servers:
- url: api.company.com
scheme: amqp
schemeVersion: '1.0'
Another example:
servers:
- url: api.company.com
scheme: kafka
schemeVersion: '0.10.0'
I'd async editor open source component?
If yes where can I get source code of it ?
Is it allowed to embed the async editor in any other application ?
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.