Code Monkey home page Code Monkey logo

cotonic's Introduction

COTONIC

Infrastructure for your web page.

Read the documentation

What is Cotonic?

Cotonic is a JavaScript library.

Infrastructure for communication:

  • Publish and subscribe to a topic tree on your web page
  • Publish and subscribe between tabs in the same browser
  • Publish and subscribe between the page and a MQTT server
  • Subscribe to topics on the page and the server
  • Publish from the server to the page
  • Publish from the page to the server

Infrastructure for using Web Workers:

  • Start and stop Web Workers
  • Communicate with and between Web Workers using the topic tree
  • Use a Service Worker for seamless communication between pages

Building blocks for managing state and html:

  • Update HTML elements with new content, using incremental DOM updates
  • Reflect state in the attributes of html and body tags, use css to change the page according to the state

The great thing is that you can use the parts separately, with frontend libraries, and even with languages like Elm.

Why do you need this?

Today's websites are build by multi-disciplinary teams. A lot of sites also include services from other companies. All these components usually run inside the same global calling context. This can lead to the following problems.

  • Privacy problems. All JavaScript which is loaded on a page has access to all dom-elements on a page. This includes private information like names, date's, financial information and passwords.
  • Isolation problems. All JavaScript code on a page runs in the same execution context. They sometimes unintentionally share resources which can lead to crashes.

This is similar to having a computer without an operating system. In the early days of computing every user had the sole use of the entire machine for a specific time slot. But today's web pages mix the execution of code from different sources in one execution context. In order to let things run reliably we need proper isolation and resource sharing primitives which are usually provided by operating systems.

How are we providing isolation?

By using modern web api's like web-workers we can truly isolate components. By doing this a crash in one component can never affect other component. With this architecture it possible to restart crashed components, and dynamically load new versions. The use of true decoupling with makes it possible run components on the server, another, or IoT device.

How are we providing privacy?

We can encrypt all sensitive payloads between the server and the client. The encryption uses public/private key pairs unique to the client.

What is used for the client/server communication?

The client/server p2p communication uses MQTT v5. Internaly Cotonic uses a topic tree similar to MQTT. All components use this tree for their communication.

There are special bridge topics for the communication with the server or other clients. The origin server is always connected on bridge/origin/. Response topics are mapped when packets pass through the bridge. In this way the server and the client can communicate via topics.

Supported Browsers

Cotonic depends on the Web Worker, so it is supported on IE11 and up.

Dependencies:

The Incremental-DOM library is used for updating the DOM:

https://github.com/google/incremental-DOM

Want to help?

Do you want to help? We are in active development. All help is welcome. Feel free to ask questions or provide feedback.

Development

Cotonic uses Web Workers and a Service Worker. Browsers only support Web Workers served from https or http if you serve from localhost or a 127.x.y.z address. This means that you can't do Web Worker development without a working http server. Luckily most Unix environments have Python installed. In order to start start development you can run the start_dev script.

$ ./start_dev.sh
Serving HTTP on 127.0.0.1 port 6227 ...
127.0.0.1 - - [28/Jan/2018 07:57:27] "GET /test/ HTTP/1.1" 200 -
...

This will start a simple Python webserver which serves the current working directory, and point your browser to the directory with tests.

Software using Cotonic

Cotonic is integrated into the content management system Zotonic.

Thanks

Big thanks to the SIDN Fonds for supporting our development.

TODO

Integration of encryption components and p2p communication using WebRTC.

cotonic's People

Contributors

mmzeeman avatar mworrell avatar rustkas avatar williamthome avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cotonic's Issues

Fix things so cotonic works on IE11

There are a couple of changes needed to make cotonic work on IE11. (Run tests with browserstack)

  • no startsWith available.
  • no codePointAt available.

Maybe other things need to be added to the polyfills.

Or @mworrell, should we remove the polyfills from the base cotonic script and tell people to load it separately when needed (somebody uses IE11)? We could check if the required features exist, when they do not, inject a script with the required polyfills.

Fix broker test suite

There are some failing tests in the broker test suite. It looks like because of small api changes.

Screenshot 2020-01-25 at 23 28 09

Check if the lifecycle model works reliably without using unload event.

The lifecycle model currently uses the unload event event to check if the page is terminated or frozen.

Lighthouse issues a warning against its used because it can influence the back/forward cache of the page.

Screen Shot 2022-11-17 at 15 16 52

It could easily be that it is no longer needed to use the unload event.

Topics for the location model to do back and forward.

It must be possible to have back and forward functionality (with defaults, for when there is no history yet)

  • model/location/post/back A href attribute can serve as default, or the default can be passed in the message.
  • model/location/post/forward A href attribute can serve as default, or the default can be passed in the message.

Example:

<a data-onclick-topic="model/location/post/back" href="/home">Back</a>

Make it possible to have externally managed parts in the dom-tree

It would be handy to make it possible to let parts of the dom-tree be managed by external libraries.

This is required to integrate tinymce in the admin pages.

Or to have externally managed logon buttons in the logon screen. For instance for Sign in with Apple or Sign in with Google, where the contents of a div is managed by another library.

Inserting link tags needs special attention

When link tags are inserted in the dom tree, special attention has to be given to href attributes.

When you insert a link tag, the href attribute has to be the last attribute added.

The reason for this is that the browser will interpret the resource as a css file because it does not know what the rel tag will be. It could easily be another type of resource.

cotonic.broker.match does not work for wildcard matches

cotonic.broker.subscribe("a/test", function(msg) { console.log(msg) })
cotonic.broker.subscribe("b/test", function(msg) { console.log(msg) })
cotonic.broker.match("+/test");
=> []

This should return the two subscriptions. Returning exact matches works.

Improve the DOM selector

Hi!

I'm planning to implement a UI selector using the document.querySelector (returns the first match) and document.querySelectorAll (returns all) instead of just by elems Id.
This adds the possibility to select elements by class, tags and also combined selectors.
Maybe the topic should be model/ui/q-insert/+key and model/ui/qall-insert/+key or something like that.
The selectors are very powerful, but the tradeoff is performance.
See some examples here.
How about?

VueJs and call ?

I'm trying to use cotonic with vuejs, there is a problem with calling the call method, it does not work in mounted, it crashes all the time with a timeout
but if I make a button and load through it, then everything works out well
maybe there is unobvious behavior?
cotonic.broker.call("bridge/origin/model/amiro/post/list", {schema :'glossary', table : 'teducationalorganization'}, { qos: 1 }) .then(data => { this.items = data.payload.result this.totalItems = data.payload.length this.loading = false } ) .catch( error => {// all problem this.loading = false; });
Error: Timeout waiting for response on bridge/origin/model/amiro/post/list

Question about worker page postMessage protocol

@mworrell The postMessage api is asynchronous as well, so you don't get responses directly.

We should probably add some mqtt protocol features like a connect (probably with keep-alive timer from mqtt-sn)/connack/disconnect messages with a will. That way the workers can find out if the page responds.

We probably also need pingreq and pingresp messages from mqtt-sn because there is no way for a worker or the page to find out if the worker is still running.

Publish transport disconnected and connected events.

Rationale

It is sometimes needed to know the pages is connected again. Knowing that makes it possible to query the server for updates.

Proposal

Introduce two session events which are published when a transport has first setup the connection. (Before the CONNECT message is sent).

  • session/+name/event/transport-connected
  • session/+name/event/transport-disconnected

Usage example:

In Zotonic the event could be used to trigger reloads when the page reconnects and important elements have to be updated.

{% live template="_follower_count.tpl" 
        id=id
        topic=id
        topic={subject id=id predicate="is_following"}
        topic="session/origin/event/transport-connected"
%}

Connect to MQTT 5 broker

I try to use cotonic as MQTT client instead of mqtt.js
But currently I can't find how to connect to EMQ X broker.

There is a test EMQ X broker available https://www.emqx.io/mqtt/public-mqtt5-broker

I try to connect to it using

cotonic.mqtt_bridge.newBridge("broker.emqx.io:8083",
                              {protocol: "ws", controller_path:"/mqtt"});

It throws error
Error during WebSocket handshake: Unexpected response code: 400
According to doc: https://docs.emqx.io/en/broker/latest/advanced/http-api.html#response-code
400 - Invalid client request, such as wrong request body or parameters

I've tested broker using http://tools.emqx.io/ and it works, it means that problem is in snippet above, but can't understand what's wrong with that conntection.

Bridge and retained messages

We need to decide how to handle retained messages on bridged topics.

Problem is that they could be retained on the server and the client.
This might give duplication of information and duplication of messages.

Though it is also useful when the client is in offline mode.

  • retain handling of bridge topics
  • retain flags on published messages, should conform to subscription retain_as_published

Remove IE11 Polyfills

IE11 is no longer supported, and its usage is very low.

I think the polyfill code can be removed. What do you thing @mworrell?

tell me how to enable cotonic in vuejs ?

tell me how to enable cotonic in vuejs ?
I am writing an application in vuejs and I have included cotonic in vuex , everything works, but I do not understand how to include the library through vuejs

Cookie topics suggestions

  • Add docs. Release 1.0.5...1.0.6 adds the possibility to get and set cookies, but there is no documentation about that;
  • Cookie delete topic;
  • More payload properties: { secure: boolean, http_only: boolean, same_site: "none" | "strict" | "lax", max_age: integer (seconds), path: string };
  • Change exdays to expires and, instead of days/integer, be a string value. Expires it's a kind of deprecated property, max_age (seconds) is preferred.

FYI

  • Get topic: model/document/get/cookie/+key
  • Set topic: model/document/post/cookie/+key
    • Payload: { value: string, exdays: integer }
function setCookie(cname, cvalue, exdays) {
        var d = new Date();
        d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000));
        var expires = "expires="+d.toUTCString();
        document.cookie = cname + "=" + cvalue + "; " + expires + "; path=/; Secure; SameSite=None";
}

Add navigator model to enable share and other api's

The navigator object has some nice api's attached to it. One of them is the share api. This makes it possible to open the device's native share window. Enabling this makes it possible to use it in a declarative way in templates. Or use it from workers.

Example:

<a href="#" data-onclick-topic="model/navigator/post/share">Share</a>

Make registering and loading the service worker configurable

Cotonic currently automatically starts a service worker when the service worker api is available. It then registers it from /cotonic-service-worker.js.

This is problematic for two reasons:

  • When cotonic is loaded from an external domain. In that case it is not allowed to start service workers.
  • We also want to be able to use zotonic's static file caching mechanism,
  • or be able to use an entirely different service worker implementation.

In order to support this I would like to be able to configure cotonic's service worker behaviour from a set of data-attributes.

  • data-cotonic-service-worker-disabled - Don't register a service worker.
  • data-cotonic-service-worker-src - Use the specified service worker src uri.

Question:

Where do we place the attributes?

  • Do we define a specific location (html, head, body) for the data attributes,
  • or use querySelector("[data-cotonic-service-worker-src]") which allows it to be placed anywhere on the page.
  • or from the script tag from which cotonic is loaded.

The middle option is th e

Examples:

The examples assume the the attributes are placed in the script tag from which cotonic is loaded

Disable the service worker::

<html>
...
<body >
    <script src="cotonic.js" data-cotonic-service-worker-disable></script>
</body>
</html>

Or load a specific service worker in a template.

<html>
    <head>
    </head>
    <body>
        <script src="cotonic.js"
                     data-cotonic-service-worker-src="/lib-min/cotonic-service-worker~1312361.js"></script>
    </body>
</html>

Add lookup table for charref tokenizing

This will speed up tokenizing charrefs considerably. Especially because the same piece of text with the same charref will be tokenized multiple times during its lifetime.

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.