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

apeiron

v1.0.5

Published

reactive data layer library

Downloads

2

Readme

###APEIRON.JS - reactive bindings for IO-actions and more. Apeiron is a tiny library written in ES6 with RxJS to provide concise and robust infrastructure for driving data layer abstractions: HTTP, SSE, WS, other IO-actions as multidirectional reactive streams (ie. binding IO and Observable/Observer with Rx.Subject and vice versa).

Build Status Code Climate Latest Stable Version Dependency Status devDependency Status

####Motivation What is the difference between Apeiron and RxJS-DOM?

Apeiron is not just a syntactic sugar to avoid boilerplate code. It is flexible and semantically clean abstraction for M(model) layer.

  • Apeiron provides unified and simple API for IO of any origin.
  • Apeiron is accurate in terms of app architecture semantics: any IO is implied to be treated with Apeiron, which encourages best FP practices (side effect denotation with data type).
  • Hence Apeiron implies good architecture: Model layer isolation, Model immutability, flattened dataStream and errorStream, and on the other hand allows high composability and decomposition.
  • The barrier for entry into Apeiron is low: you may have no reactive or Haskell experience to operate IO a binding to Stream a quasi-impertively as usual chained methods.
  • Apeiron has richer API both on HTTP and WS/SSE written in more functional style.
  • Apeiron plays great with RxJS - dataStream and errorStream are merely RxJS Observables.

HTTP features:

  • Apeiron HTTP relies on Axios library, which has richer API than RxJS-DOM.
  • Apeiron HTTP endpoints config is declarative - you may think of it as dual to View framework router.
  • On the other hand Apeiron HTTP is dynamic - you can create new Apeiron HTTP instances base on subsets of config. Check GroupBy API.

WS/SSE features:

  • Apeiron WS automatically tries to reconnect.
  • Apeiron WS handles WS life cycle for open, close, and error consistently - bound to dataStream/errorStream Observables and send/sendMany API.
  • Apeiron WS send close command to the server when completed is called.
  • Apeiron WS enforces a single instance of a socket regardless of the number of subscriptions.
  • Apeiron WS gracefully buffers messages until underlying socket isn't open and then sends them asynchronously when it does open.

ALSO:

  • Apeiron's end mission is isomorphic development: similar API for client and node.js (currently in development).

####Install

NPM:

npm i apeiron -S

then hook up APEIRON.js into project:

ES6:

import { StreamAPI } from 'apeiron'

Node / Browserify:

const StreamAPI = require('apeiron').StreamAPI

UMD:

<script src="apeiron/dist/apeiron.min.js"></script>

####Class API Import Apeiron:

import { StreamAPI } from 'apeiron'

Create streamer instance with following data structures:

StreamAPI :: TYPE -> OPTIONS -> Streamer

-- JS: const Streamer = new StreamAPI(TYPE, OPTIONS);
-- notice that args are not curried.

data TYPE = "HTTP" | "WS" | "SSE"

data OPTIONS = 
	HTTPOptions {
		config :: Maybe AxiosConfig, 
		endpoints :: ApeironEndopints
	} | 
	WSOptions {
		endpoint :: Url,
		protocol :: Protocol | [Protocol]
	} |
	SSEOptions {
		endpoint :: Url,
		withCredentials: Bool
	}

####Streams API

-- common interface
-- JS: Streamer.dataStream
dataStream :: Observable a
-- JS: Streamer.errorStream
errorStream :: Observable a

-- for SSE and WS only
-- JS: Streamer.metaStream
metaStream :: Observable a

####Send API

Send API is for HTTP and WS only. It tunnels data to IO () and returns dataStream reference.

-- Notice, that Data type differs for HTTP and WS (see examples below)

-- JS: Streamer.send(Data)
send :: Data -> Streamer.dataStream

-- JS: Streamer.send([Data1, Data2.. DataN], 1000) or Streamer.send([Data1, Data2.. DataN])
sendMany :: [Data] -> Maybe Delay -> Streamer.dataStream

-- for SSE and WS
-- JS: Streamer.close()
close :: IO ()

As send / sendMany returns Streamer.dataStream, it is easy to nest operations like:

DL.send('getPosts')
	.filter(x => x.isActive)
	.subscribe(x => console.log('Data Stream:', x));

####Group API - HTTP only

Creates new Streamer instance with the endpoints matched by name (multiple args) / url (single arg) / method (single arg)

-- JS: Streamer.groupByName('ep1','ep2',...'epN')
groupByName :: Args EP -> Streamer

-- JS: Streamer.groupByUrl('posts')
groupByUrl :: Url -> Streamer

-- JS: Streamer.groupByMethod('put')
groupByMethod :: Method -> Streamer

####Headers API - HTTP only Add and remove headers for all HTTP requests

-- JS: Streamer.setHeader('common', 'AUTH', token)
setHeader :: HMethod -> Header -> Value -> ()

-- JS: Streamer.removeHeader('common', 'AUTH')
removeHeader :: HMethod -> Header -> ()

####Type reference

data Method = "post" | "put" | "patch" | "get" | "delete" | "head"
data HMethod = Method | "common"
type Url = String
type EP = String
type Header = String
type Value = String
type Delay = Int

data Data = HTTPData {
	endpoint :: EP,
	payload :: {
		data :: Maybe a,
		config :: Maybe AxiosConfig
	}} | 
	WSData {
		endpoint: EP,
		data: a
	}

####Examples HTTP Prepare config (for config details check AXIOS API):

const config = {
  baseURL: 'http://localhost:3000'
};

Add endpoints declaratively:

const endpoints = {
  removePost: {
    url: '/posts/:id',
    method: 'delete'
  },
  addPost: {
    url: '/posts',
    method: 'post'
  },
  getPosts: {
    url: '/posts',
    method: 'get'
  },
  getPost: {
    url: '/posts/:id',
    method: 'get'
  },
  editPost: {
    url: '/posts/:id',
    method: 'put'
  }
}

Create Apeiron instance:

const StreamAPI = require('apeiron').StreamAPI;
const DL = new StreamAPI('HTTP', { endpoints, config });

Run REST API server and add subscription:

DL.dataStream.subscribe(res => {
  console.log('Data Stream:');
  console.log(res.data);
});

DL.dataStream.subscribe(insertDataInDOM);

DL.errorStream.subscribe(err => {
  console.log('Error Stream:');
  console.error(err);
});

DL.errorStream.subscribe(err => {
  if (err.statusText) {
    $('#notifications').text(err.statusText);
  } else {
    $('#notifications').text(err);
  }
});

DL.errorStream.subscribe(err => {
  console.log('SSE Error Stream:');
  console.error(err);
});

Senders example:

DL.send('getPosts'); // possible no config for GET 

DL.send('getPost', {
    config: { id : 1 } // GET id denoted in config for url/:id	
});

DL.send('getPost', {
	config: { // GET url/:id with query params ?ID=123
		id : 1,
		params : { ID : 123 } 
	}
});

DL.send('addPost', {
	data: { a: '12345' }, // data is required for POST, PUT, PATCH
	config: {
		params: { ID: 123 }, // optional
		withCredentials: true, // optional
		headers: {'X-Requested-With': 'XMLHttpRequest'} // optional
	}
})

DL.send('removePost', {
	// data - ignored for GET, DELETE, HEAD
	config: {
		id: 12345, // required for DELETE, HEAD, optional for GET
		params: { ID: 12345 }, // optional
		withCredentials: true, // optional
		headers: {'X-Requested-With': 'XMLHttpRequest'} // optional
	}
})

// sendMany argument is the list of tuples :: [[endpoint, payload]]
// i.e. [[endpoint1, {data, config}], [endpoint2, {data, config}]]

DL.sendMany([
	['getPost', {config: {id: 1} }],
	['getPost', {config: {id: 9774} }]
]);

For config details check AXIOS API

####Examples WS/SSE Create Apeiron instance:

const StreamAPI = require('apeiron').StreamAPI;
const DLWS = new StreamAPI('WS', 'ws://localhost:3001');

Run server and add subscription:

DLWS.dataStream
	.take(10)
	.do(() => void 0, () => void 0, () => {
		DLWS.close();
		console.log('DLWS stopped');
	})
	.subscribe((res) => {
		console.log('WS Data Stream:');
		res.type === 'message' ?
		  console.log(res.data) :
		  console.log(res.type);
	});

DLWS.errorStream
	.subscribe(err => {
	  console.log('SSE Error Stream:');
	  console.error(err);
	});

Senders example:

DLWS.sendMany([{data:'1'},{data:'2'},{data:'3'}]);

setTimeout(() => {
  DLWS.send({data:'x'});
}, 3000)

Same way works for SSE.

Check more examples in /examples folder

####License ISC

####TODO (Beta-3 release)

CLIENT (ClientAPI)

1. StreamAPI -> ClientAPI
2. bower package
3. browser support
4. WS reconnect
5. HTTP.poll
6. HTTP.pollUntil
7. Notification API
8. unit tests

####TODO (Beta-4 release)

SERVER (ServerAPI)

1. SSE custom
2. WS ws
3. Regis redis
4. Mongo mongodb
5. unit tests

####Future examples

  1. DL -> Controller -> Stateless Components (React)
  2. DL -> Stateless Services -> VM (Angular 1.5)
  3. Architecture guide: async MVC (DL -> Controller -> View)