diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 00000000..d6a64753 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,75 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, gender identity and expression, level of experience, +nationality, personal appearance, race, religion, or sexual identity and +orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or +advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an appointed +representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project team at or +. All +complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project team is +obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at [http://contributor-covenant.org/version/1/4][version] + +[homepage]: http://contributor-covenant.org +[version]: http://contributor-covenant.org/version/1/4/ diff --git a/README.md b/README.md index 47e3feb1..b7638147 100644 --- a/README.md +++ b/README.md @@ -1,91 +1,159 @@ -[![Travis CI](https://travis-ci.org/metarhia/JSTP.svg?branch=master)](https://travis-ci.org/metarhia/JSTP) -[![bitHound Dependencies](https://www.bithound.io/github/metarhia/JSTP/badges/dependencies.svg)](https://www.bithound.io/github/metarhia/JSTP/master/dependencies/npm) -[![bitHound Score](https://www.bithound.io/github/metarhia/JSTP/badges/score.svg)](https://www.bithound.io/github/metarhia/JSTP) -[![NPM Version](https://badge.fury.io/js/metarhia-jstp.svg)](https://badge.fury.io/js/metarhia-jstp) -[![NPM Downloads/Month](https://img.shields.io/npm/dm/metarhia-jstp.svg)](https://www.npmjs.com/package/metarhia-jstp) -[![NPM Downloads](https://img.shields.io/npm/dt/metarhia-jstp.svg)](https://www.npmjs.com/package/metarhia-jstp) - -# JSTP / JavaScript Transfer Protocol - -## Concept - -JSTP is a family of data formats and corresponding libraries for their -processing that are based on some simple assumptions: - -* it is possible to trasfer data as plain JavaScript code easier and - more efficient than using JSON: - - in its simplest implementation it doesn't even require a specialized - parser since it is already built into transferer and receiver systems; - - a human-readable format can be almost as minimalist as a binary one, - losing coding efficiency very slightly yet winning from the simplicity - of packet inspection; - - serialization format and data modeling must be maximally univocal and - must answer a question about why someone has done something this way; - - there should be possibility to apply different formatting and use - comments; - -* it is redundant to send a structure along with data each time, the - serialization format and the protocol must be optimized to exempt - metamodel and send it only when the receiver hasn't got it yet; - -* the protocol of interaction between two JavaScript applications must - have the following features: - - two-way asynchronous data transfer with support of plentiful parallel - non-blocking interactions and packet indentifiers allowing, for example, - to find the correspondence between a request and a response; - - support of RPC and multiple APIs must be so transparent that application - shouldn't event know whether a function call is inside the address space - of the application or it is a remote call sent to another system for - execution; - - direct call and response via callback support; - - support of translation of named events with bound data and named channels - for event grouping; - - support of automatic synchronization of objects in applications memory - if they are registered for synchronization; - - only one of sides can initiate a connection but both sides can send data - over open channel; - - the transport layer must guarantee reliable data transfer with connection - establishment and guaranteed delivery (TCP is the basic transport and we - also support WebSocket but anything can be used, even RS232 or USB); - - all packet types (call, response, callback, event, data etc.) may be split - into several parts if their body is too large; - - there should be a possibility to stop data transfer if the data transmitted - in parts is too large and the last part hasn't been received yet; - -* it is required to minimize the transformation of data while tranferring them - between different systems, storing and processing, minimize putting them from - one structures to other, to save memory and connection channel; - -* amount of data structures needed for most systems is in fact finite and the - structures themselves must be standardized as a result of specialists - agreement, and there should be possibility of their versioning; - -* non-standard data structures can be sent between systems along with metadata - that will allow to interprete them and provide universal processing to the - possible extent if the remote sides trust each other and formalization of - data doesn't make sense. - -## Getting Started - -JSTP works in Node.js and web browsers. To install it, simply run: +
+ + Metarhia Logo + +
+
+ + Travis CI + + + bitHound Dependencies + + + bitHound Score + + + NPM Version + + + NPM Downloads/Month + + + NPM Downloads + +

JSTP / JavaScript Transfer Protocol

+
+ +JSTP is an RPC protocol and framework which provides two-way asynchronous data +transfer with support of plentiful parallel non-blocking interactions that is so +transparent that an app may not even distinguish between local async functions +and remote procedures. + +And, as a nice bonus, there's a blazing fast [JSON5](https://github.com/json5) +implementation bundled in! + +**This project is bound by a [Code of Conduct](CODE_OF_CONDUCT.md).** + +## Installation + +JSTP works in Node.js and web browsers: ```sh $ npm install --save-dev metarhia-jstp ``` -Or, alternatively, if you are developing a client-side application for browser -environment and don't use a module bundler like Webpack, +Or, alternatively, there are [jstp.min.js](https://metarhia.github.io/JSTP/dist/jstp.min.js) and -[jstp.min.js.map](https://metarhia.github.io/JSTP/dist/jstp.min.js.map) are -also available. +[jstp.min.js.map](https://metarhia.github.io/JSTP/dist/jstp.min.js.map) +available for those browser-based applications that aren't built using a module +bundler like [webpack](https://webpack.js.org/). + +We also have official client-side implementations for +[Swift](https://github.com/JSTPMobile/iOS) and +[Java](https://github.com/JSTPMobile/Java) that work effortlessly on iOS and +Android 🎉 -Then proceed to the documentation at . +## Getting Started + +Server: + +```js +'use strict'; + +const jstp = require('metarhia-jstp'); + +// Application is the core high-level abstraction of the framework. An app +// consists of a number of interfaces, and each interface has its methods. +const app = new jstp.Application('testApp', { + someService: { + sayHi(connection, name, callback) { + callback(null, `Hi, ${name}!`); + } + } +}); + +// Let's create a TCP server for this app. Other available transports are +// WebSocket and Unix domain sockets. One might notice that an array of +// applications is passed the `createServer()`. That's because it can serve +// any number of applications. +const server = jstp.tcp.createServer(3000, [app]); +server.listen(() => { + console.log('TCP server listening on port 3000 🚀'); +}); +``` -## Implementations +Client: + +```js +'use strict'; + +const jstp = require('metarhia-jstp'); + +// Create a TCP client. Clients can have applications too for full-duplex RPC, +// but we don't need that in this example. +const client = jstp.tcp.createClient({ host: 'localhost', port: 3000 }); + +// Connect to the `testApp` application. Username and password are both `null` +// here — that is, the protocol-level authentication is not leveraged in this +// example. The next argument is an array of interfaces to inspect and build +// remote proxy objects for. +client.connectAndInspect('testApp', null, null, ['someService'], handleConnect); + +function handleConnect(error, connection, app) { + if (error) { + console.error(`Could not connect to the server: ${error}`); + return; + } + + // The `app` object contains remote proxy objects for each interface that has + // been requested which allow to use remote APIs as regular async functions. + // Remote proxies are also `EventEmitter`s: they can be used to `.emit()` + // events to another side of a connection and listen to them using `.on()`. + app.someService.sayHi('JSTP', (error, message) => { + if (error) { + console.error(`Oops, something went wrong: ${error}`); + return; + } + console.log(`Server said "${message}" 😲`); + }); +} +``` -| Implementation | Parser | TCP Client | TCP Server | WebSocket Client | WebSocket Server | -| --- | :---: | :---: | :---: | :---: | :---: | -| JavaScript
[metarhia/JSTP](https://github.com/metarhia/JSTP) | ✓ | ✓ | ✓ | ✓ | ✓ | -| Swift
[JSTPMobile/iOS](https://github.com/JSTPMobile/iOS) | ✓ | ✓ | ✗ | ✗ | ✗ | -| Java
[JSTPMobile/Java](https://github.com/JSTPMobile/Java) | ✓ | ✓ | ✗ | ✗ | ✗ | -| Haskell
[DzyubSpirit/JSTPHaskell](https://github.com/DzyubSpirit/JSTPHaskell) | ✓ | ✓ | ✓ | ✗ | ✗ | +## Project Maintainers + +Kudos to [@tshemsedinov](https://github.com/tshemsedinov) for the initial idea +and proof-of-concept implementation. Current project team is: + +* [@aqrln](https://github.com/aqrln) — + **Alexey Orlenko** <eaglexrlnk@gmail.com> +* [@belochub](https://github.com/belochub) — + **Mykola Bilochub** <nbelochub@gmail.com> +* [@lundibundi](https://github.com/lundibundi) — + **Denys Otrishko** <shishugi@gmail.com> +* [@nechaido](https://github.com/nechaido) — + **Dmytro Nechai** <nechaido@gmail.com> +* [@tshemsedinov](https://github.com/tshemsedinov) — + **Timur Shemsedinov** <timur.shemsedinov@gmail.com> diff --git a/examples/readme-example/client.js b/examples/readme-example/client.js new file mode 100644 index 00000000..c7ba6e6c --- /dev/null +++ b/examples/readme-example/client.js @@ -0,0 +1,32 @@ +'use strict'; + +const jstp = require('../..'); + +// Create a TCP client. Clients can have applications too for full-duplex RPC, +// but we don't need that in this example. +const client = jstp.tcp.createClient({ host: 'localhost', port: 3000 }); + +// Connect to the `testApp` application. Username and password are both `null` +// here — that is, the protocol-level authentication is not leveraged in this +// example. The next argument is an array of interfaces to inspect and build +// remote proxy objects for. +client.connectAndInspect('testApp', null, null, ['someService'], handleConnect); + +function handleConnect(error, connection, app) { + if (error) { + console.error(`Could not connect to the server: ${error}`); + return; + } + + // The `app` object contains remote proxy objects for each interface that has + // been requested which allow to use remote APIs as regular async functions. + // Remote proxies are also `EventEmitter`s: they can be used to `.emit()` + // events to another side of a connection and listen to them using `.on()`. + app.someService.sayHi('JSTP', (error, message) => { + if (error) { + console.error(`Oops, something went wrong: ${error}`); + return; + } + console.log(`Server said "${message}" 😲`); + }); +} diff --git a/examples/readme-example/server.js b/examples/readme-example/server.js new file mode 100644 index 00000000..57eb6da9 --- /dev/null +++ b/examples/readme-example/server.js @@ -0,0 +1,22 @@ +'use strict'; + +const jstp = require('../..'); + +// Application is the core high-level abstraction of the framework. An app +// consists of a number of interfaces, and each interface has its methods. +const app = new jstp.Application('testApp', { + someService: { + sayHi(connection, name, callback) { + callback(null, `Hi, ${name}!`); + } + } +}); + +// Let's create a TCP server for this app. Other available transports are +// WebSocket and Unix domain sockets. One might notice that an array of +// applications is passed the `createServer()`. That's because it can serve +// any number of applications. +const server = jstp.tcp.createServer(3000, [app]); +server.listen(() => { + console.log('TCP server listening on port 3000 🚀'); +});