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

compressed-json-collection

v1.1.0

Published

A compressed JSON collection used to manage and cache large sets of similar JSON objects for sending over HTTP(S), WebSockets or similar.

Downloads

7

Readme

compressed-json-collection

A compressed collection used to manage and cache large sets of similar JSON objects.

What this is

  • A collection with basic query abilities
  • A collection that generates and maintains a compressed state of the collection for passing over http or similar as JSON.
  • A basic cache for large amounts of similar data objects that should be exposed as JSON.

What this is not

  • A collection that has a smaller memory footprint than a normal javascript array

Usage (typescript example)

// So you have some data:
interface IData { id: number: name: string; status: 'ACTIVE' | 'PASSIVE' | 'ARCHIVED'; joined: Date }
var data: IData = [
	{ id: 1234, name: 'John Doe', status: 'ACTIVE', joined: new Date() },
	{ id: 4321, name: 'Jane Doe', status: 'ACTIVE', joined: new Date() },
				.
				.
				.
	{ id: 9999, name: 'Last Name', status: 'PASSIVE', joined: new Date() },
];

// Provide a definition for the properties on the data items that should be included
// in the compressed collection. Here you define how and if each property should be 
// compressed.
const definition: ICompressedJsonCollectionDefinition<IData> = { 
	properties: { 
		id: { encoding: EncodingType.DIFF },
		name: { encoding: EncodingType.RAW },
		status: {encoding: EncodingType.RUNLENGTH },
		joined: { encoding: EncodingType.DIFF, type: 'date' }
	} 
};

// Create a compressed collection with some (optional) initial data and the definition
const collection = new CompressedCollection<IData>(definition, data);

// Possibly add some data
collection.add({ id: 3232, name: 'Some Guy', status: 'ARCHIVED', joined: new Date() });
collection.add([
	{ id: 2323, name: 'Some Girl', status: 'ACTIVE', joined: new Date() },
	{ id: 4141, name: 'Some other Guy', status: 'PASSIVE', joined: new Date() }
]);

// Possibly remove some data... 
collection.remove(data[1]);      // ...by reference
collection.removeByIndex(3);     // ...by index
collection.removeByIndex(6, 10); // ...from index to index

// Retrieve the whole compressed collection...
var compressed data = collection.compressedJson;

// ...or query for a compressed subset of the data:
var compressedSubset: collection.query((item: IData) => item.status === 'ACTIVE');

// Decompress compressed data ()
var decompressedData = CompressedCollection.decompress<IData>(compressedSubset);

The definition explained

How the collection works is defined with the ICompressedJsonCollectionDefinition<T> passed to the constructor of the CompressedCollection.

The definition interface:

export interface ICompressedJsonCollectionDefinition<T> {
	insertionHandler?: ((item: T) => boolean) | ICompressedJsonCollectionHandler<T>;
	sort?: (itemA: T, itemB: T) => -1 | 0 | 1;
	properties: { [key: string]: EncodingDefinition };
}

insertionHandler

The insertion handler is an optional function or object (e.g. class) that is used to evaluate each item that is added to the collection.

The insertionHandler function option: (item: T) => boolean

The function form of the insertion handler will receive the item being evaluated for insertion and is expected to return true if the item should be inserted or false if it should be rejected.

Example:

// Only allow items with a non null date property 'time' with a date succeeding 'timeThreshold'
const timeThreshold = new Date('1995-12-17T03:24:00');
const myInsertionHandler = (item:  {time: Date }) => item.time != null && item.time > timeThreshold;   

The insertionHandler object/class option: ICompressedJsonCollectionHandler<T>

The object/class insertionHandler is an advanced option that comes with great freedom. It can be used to create advanced collection that processes the data on insertion in more advanced ways, like having a buffer, performing advanced preprocessing or dynamically re-encode parts of the collection on input.

Unlike the function version of the insertion handler the class/object version returns objects that should be inserted in to the collection. The handler get passed all items being inserted to the collection and should return items that should be added. If multiple items are added att the same time all of them will be sent to the handler in one array, unlike the function version that will be passed one at a time.

Example:

interface DataType { timeStamp: Date; position: { x: number, y: number }; };
class myAdvancedInsertionHandler implements ICompressedJsonCollectionHandler<DataType> {

	insert(items: DataType[], collection: CompressedJsonCollection<DataType>): DataType[] {
		// Performe some processing, store things in a buffer, filter or alter the data... 
		const result = this.processData(items);

		// you can even remove some items from the collection if needed
		collection.removeByIndex(42);

		// ...and return items that should be added to the collection.  
		return result;
	}

	private processData(items: DataType[]): DataType[] { /* ... */ }
}

sort

The definition sort function is an optional way of turning the collection in to an ordered collection, each item added to the collection will be sorted in to place on insertion.

Example:

const sort = (a, b): -1 | 0 | 1 => a.val < b.val ? -1 : a.val > b.val 

NOTE: Ordering can have a huge impact when performing diff based compression. When encrypting series of GPS positions for example, better compression is achieved if sorting the positions in a useful way (e.g. based on time or distance).

properties

The properties of the definitions define the properties to be included in the resulting compressed collection. The types available are defined by the interfaces:

export interface RunLengthEncodingDefinition extends EncodingDefinition {
	encoding: EncodingType.RUNLENGTH;
	values?: string[]; // possible values
}

export interface KeyFrameDiffEncodingDefinition extends EncodingDefinition {
	encoding: EncodingType.DIFF;
	decimalDigits?: number;
	factor?: number;
	type?: 'number' | 'date' // defaults to number if not set
}

export interface RawEncodingDefinition extends EncodingDefinition {
	encoding: EncodingType.RAW;
}

RunLengthEncodingDefinition

The run length encoding type is useful for properties that has a limited set of possible values, like string constants or enums converted to strings or integers for example.

KeyFrameDiffEncodingDefinition

The key frame encoding type is useful for dates or numeric parameters. It achieves high compression rates when used with a fixed number of decimal digits (all numbers will be converted to decimalDigits number of decimal digits), and is especially good for parameters with a limited numeric range. If the target parameter is a data set the type to 'date', the type 'number' is default.

RawEncodingDefinition

The raw type is useful for including parameters that should not be compressed in the resulting collection. The parameter will not be compresed or alered in anny way.