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

@type-r/endpoints

v4.0.2

Published

I/O endpoint for Type-R models

Downloads

145

Readme

I/O endpoints

Overview

Type-R uses IO abstraction represented by IOEndpoint interface, with JSON serialization handled by Model and Collection classes.

IOEndpoint defines the set of CRUD + list methods operating on raw JSON. Attachment of an endpoint to the model or collection enables I/O API. There are few endpoints bundled with Type-R, for instance memoryIO() which can be used for mock testing.

@define class User extends Model {
    static endpoint = memoryIO();

    static attributes = {
        name : '',
        email : ''
    }
}

const users = new User.Collection();
users
    .add({ name : 'John' })
    .save()
    .then( () => console.log( user.id );

I/O endpoints

restfulIO( url, options? )

HTTP REST client endpoint. Requires window.fetch available natively or through the polyfill. Implements standard BackboneJS REST semantic.

All I/O methods append an optional options.params object to the URL parameters translating them to string with JSON.stringify().

  • model.save() makes:
    • POST url, if the model has no id. Expects to receive { id : recordId }.
    • PUT url/:id, if the model has an id.
  • collection.fetch() makes GET url.
  • model.destroy() makes DELETE url.

Supports URI relative to owner (./relative/url resolves as /owner/:id/relative/url/:id ).

import { restfulIO } from 'type-r/endpoints/restful'

@define class Role extends Model {
    static endpoint = restfulIO( '/api/roles' );
    ...
}

@define class User extends Model {
    static endpoint = restfulIO( '/api/users' );
    
    static attributes = {
        // Roles collection here has relative url /api/users/:user_id/roles/
        roles : type( Role.Collection ).endpoint( restfulIO( './roles' ) ), 
        ...
    }
}

memoryIO( mockData?, delay? )

Endpoint for mock testing. Takes optional array with mock data, and optional delay parameter which is the simulated I/O delay in milliseconds.

import { memoryIO } from 'type-r/endpoints/memory'

@define class User extends Model {
    static endpoint = memoryIO();
    ...
}

localStorageIO( key )

Endpoint for localStorage. Takes key parameter which must be unique for the persistent model's collection.

import { localStorageIO } from 'type-r/endpoints/localStorage'

@define class User extends Model {
    static endpoint = localStorageIO( '/users' );
    ...
}

attributesIO()

Endpoint for I/O composition. Redirects model's fetch() request to its attributes and returns the combined abortable promise. Does not enable any other I/O methods and can be used with model.fetch() only.

It's common pattern to use attributesIO endpoint in conjunction with Store to fetch all the data required by SPA page.

import { localStorageIO } from 'type-r/endpoints/attributes'

@define class PageStore extends Store {
    static endpoint = attributesIO();
    static attributes = {
        users : User.Collection,
        roles : UserRole.Collection,
    }
}
...
const store = new PageStore();
store.fetch().then( () => renderUI() );

proxyIO( RecordCtor )

Create IO endpoint from the Model class. This endpoint is designed for use on the server side with a data layer managed by Type-R.

Assuming that you have Type-R models with endpoints working with the database, you can create an endpoint which will use an existing Model subclass as a transport. This endpoint can be connected to the RESTful endpoint API on the server side which will serve JSON to the restfulIO endpoint on the client.

An advantage of this approach is that JSON schema will be transparently validated on the server side by the Type-R.

    import { proxyIO } from 'type-r/endpoint/proxy'
    
    ...

    const usersIO = proxyIO( User );

IOEndpoint Interface

An IO endpoint is an "plug-in" abstraction representing the persistent collection of JSON objects, which is required to enable models and collections I/O API. There are several pre-defined endpoints included in Type-R package which can be used for HTTP REST I/O, mock testing, working with localStorage, and IO composition.

You will need to define custom endpoint if you would like to implement or customize serialization transport for Type-R objects. Use built-in endpoints as an example and the starting boilerplate.

All IOEndpoint methods might return standard Promises or abortable promises (created with createIOPromise()). An IOEndpoint instance is shared by all of the class instances it's attached to and therefore it's normally must be stateless.

endpoint.read( id, options, model )

Reads an object with a given id. Used by model.fetch() method. Must return JSON wrapped in abortable promise.

endpoint.update( id, json, options, model )

Updates or creates an object with a given id. Used by model.save() method when model already has an id. Must return abortable promise.

endpoint.create( json, options, model )

Creates an object. Used by model.save() method when model does not have an id. Must return abortable promise.

endpoint.destroy( id, options, model )

Destroys the object with the given id. Used by model.destroy() method. Must return abortable promise.

endpoint.list( options, collection )

Fetch an array of objects. Used by collection.fetch() method. Must returns abortable promise.

endpoint.subscribe( callbacks, collection )

Optional method to enable the live updates subscription. Used by collection.liveUpdates( true ) method. Must returns abortable promise.

Method callbacks argument is an object of the following shape:

{
    // Endpoint must call it when an object is created or updated.
    updated( json ){}

    // Endpoint must call it when an object is removed.
    removed( json ){}
}

endpoint.unsubscribe( callbacks, collection )

Unsubscribe from the live updates. Used by collection.liveUpdates( false ) method. Takes the same callbacks object as subscribe().

createIOPromise( init )

Service function to create an abortable version of ES6 promise (with promise.abort() which meant to stop pending I/O and reject the promise).

init function takes the third onAbort argument to register an optional abort handler. If no handler is registered, the default implementation of promise.abort() will just reject the promise.

import { createIOPromise } from 'type-r'

const abortablePromise = createIOPromise( ( resolve, reject, onAbort ) =>{
    ...
    onAbort( () => {
        reject( 'I/O Aborted' );
    });
});