npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@hitchy/plugin-odem-socket.io

v0.3.0

Published

exposing Hitchy's document-oriented database via websocket

Downloads

75

Readme

@hitchy/plugin-odem-socket.io

exposing Hitchy's document-oriented database via websocket

License

MIT

Installation

npm i @hitchy/plugin-odem-socket.io

This plugin relies on additional plugins to be installed as well:

npm i @hitchy/plugin-odem @hitchy/plugin-socket.io

Breaking changes

v0.2

  • The parameter uuidsOnly of actions <modelName>:list and <modelName>:find has been replaced by loadRecords to match the semantics of server-side Odem API. You have to negate its value to adapt.

v0.3

  • This version is recognizing an existing authentication plugin and checks a user's authorization for accessing models and their properties based on authorization rules set on server.
  • Previously, actions of control API required the provision of a session ID to read a requesting user from as first argument. This approach has been abandoned. All actions are automatically associated with the user which has been authenticated when the websocket connection has been established.
  • Clients should drop and re-connect over websocket whenever authentication of a requesting user has changed.

Usage

Basics

This plugin is exposing an API via websocket for controlling and monitoring models of server-side document-oriented database. Relying on particular features of socket.io, this API is exposed in namespace /hitchy/odem.

For every server-side model, request listeners and/or notification broadcasters are set up. Either model's name is converted into its kebab-case variant and used as colon-separated prefix in event names emitted either by the server or by a client.

In the following sections, the placeholder <modelName> is used instead of that kebab-case variant of a model's name.

Control API

Attention!

As of v0.1.0, the control API is disabled by default due to the lack of having authorization checks implemented on server-side. You have to enable it explicitly by setting runtime configuration parameter config.socket.odem.crud which defaults to false.

All action events listed in this section are to be sent by a client. The server is setting up listeners and directly responds to either received event. Thus, the common pattern on client side looks like this:

const socket = io( "/hitchy/odem" );

socket.on( "connect", () => {
    socket.emit( actionName, arg1, arg2, arg3, response => {
        // process the response here
    } );
} );

socket.io requires all arguments to be provided no matter what. Thus, you can't omit any of the arguments given in examples below but have to provide values assumed to be default, at least.

The following code excerpts are focusing on the inner part of emitting an action event and processing the response.

<modelName>:list

This request is the websocket variant of Model.list(). Supported arguments are

  • query-related options as supported by Model.list() and

  • a boolean controlling loadRecords of result-related options supported by Model.list().

    This boolean must be true to actually get the properties of retrieved items. Otherwise, listed items are represented by their UUIDs, only.

socket.emit( "<modelName>:list", { limit: 10 }, false, response => {
    // - check for `response.success` or `response.error`
    // - process total count of items in `response.count`
    // - process requested excerpt of items in `response.items`
} );

Last argument is a callback to be invoked with the resulting response from server-side. response is an object consisting of truthy property success on success or error message in case of a failure. On success, property count is providing total count of matches and items is the list of matching items' properties.

<modelName>:find

This request is searching for instances of selected model matching some query. It is invoking Model.find(). Arguments are

  • the query describing items to find,

  • query-related options as supported by Model.find() and

  • a boolean controlling loadRecords of result-related options supported by Model.find().

    This boolean must be true to actually get the properties of retrieved items. Otherwise, listed items are represented by their UUIDs, only.

socket.emit( "<modelName>:find", {}, { limit: 10 }, true, response => {
    // - check for `response.success` or `response.error`
    // - process total count of items in `response.count`
    // - process requested excerpt of items in `response.items`
} );

Last argument is a callback to be invoked with the resulting response from server-side. response is an object consisting of truthy property success on success or error message in case of a failure. On success, property count is providing total count of matches and items is the selected excerpt from that list of matching items' each given by its properties including its UUID.

<modelName>:create

This request is creating another instance of selected model assigning provided properties as initial values. Those properties are provided as serializable object.

socket.emit( "<modelName>:create", { title: "important things" }, response => {
    // - check for `response.success` or `response.error`
    // - process properties of eventually created instance in `response.properties`
    // - created instance's UUID is available as `response.properties.uuid`
} );

Last argument is a callback to be invoked with the resulting response from server-side. response is an object consisting of truthy property success on success or error message in case of a failure. On success, properties of created instance are returned. These may be different from provided ones due to server-side constraints. The created item's UUID is added to that set of properties as uuid.

<modelName>:read

This request is fetching a single instance's properties.

socket.emit( "<modelName>:read", "12345678-1234-1234-1234-123456789012", response => {
    // - check for `response.success` or `response.error`
    // - process properties of fetched instance in `response.properties`
} );

Last argument is a callback to be invoked with the resulting response from server-side. response is an object consisting of truthy property success on success or error message in case of a failure. On success, properties of selected instance are returned.

<modelName>:update

This request is updating an existing instance of model. The UUID of item to update and the values per property to assign are provided as arguments.

socket.emit( "<modelName>:update", "12345678-1234-1234-1234-123456789012", { prio: 1 }, response => {
    // - check for `response.success` or `response.error`
    // - properties of updated instance are provided in `response.properties`
} );

Last argument is a callback to be invoked with the resulting response from server-side. response is an object consisting of truthy property success on success or error message in case of a failure. On success, properties of updated instance are returned. These may be different from provided ones due to server-side constraints.

<modelName>:delete

This request is eventually completing the CRUD-support of this API by deleting an existing instance of model selected by its UUID in first argument.

socket.emit( "<modelName>:delete", "12345678-1234-1234-1234-123456789012", response => {
    // - check for `response.success` or `response.error`
    // - deleted instance's UUID is available as `response.properties.uuid`
} );

Last argument is a callback to be invoked with the resulting response from server-side. response is an object consisting of truthy property success on success or error message in case of a failure. On success, properties of updated instance are returned.

Notifications

notifications of the document-oriented database are forwarded as broadcast events named <modelName>:changed. Either event consists of

  • a type of change and
  • the changed item's properties (limited to its UUID on deletion).

The type of change is

  • created on notifications about having created another instance of model,
  • updated on notifications about having adjusted one or more properties of an existing instance of model and
  • deleted on notifications about having removed an existing instance of model.

In last case the provided set of properties is limited to the instance's UUID. The common pattern on client-side for listening to server-side notifications looks like this:

const socket = io( "/hitchy/odem" );

socket.on( "<modelName>:changed", info => {
    // type of change is in `info.change`, e.g. "updated"
    // process properties of changed instance in `info.properties`
} );

There may be server-side restriction applying per event or per instance of model, thus some or all notifications might be omitted.