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

fods

v2.2.1

Published

Frontend Operational Data Store

Downloads

164

Readme

FODS (Frontend Operational Data Store)

Make frontend data request more controllable.

Install

npm i fods

Usage

import { source, query } from 'fods';
// import { source, query } from 'https://unpkg.com/fods';

// define a source
const UserBooks = source((uid) => {
    // return user' books
});

// query data from source
const userBooks = await query(UserBooks, '123');

// update data in source
renew(UserBooks, '123');

Idea

  1. same source with same params should return same output until the source is renewed
  2. same request should not be send again when the request is runing
  3. multiple relative data should have their lifecycle management

A store is a place to put data in local, when we invoke query emit or take, we find some thing in local store and reuse them, so that we can reduce the real request count, and share data amoung requests.

API

source & query

Define a SOURCE_TYPE store by source and consume it by query.

import { source, query } from 'fods';

// define a source
const UserBooks = source((uid) => {
    // return user' books
});

// query data from source
const userBooks = await query(UserBooks, '123');

// update data in source
renew(UserBooks, '123');

compose

Define a COMPOSE_TYPE store by compose and consume it by query.

import { compose, query } from 'fods';

const MyList = compose(
    (ids: string[]) => {
        // return result list array
    },
    // find value in result list to record cache
    // if undefined, ignored
    (res, id: string) => res.find(item => item.id === id),
);

const lite = await query(MyList, [1, 2]);
const all = await query(MyList, [1, 2, 3, 4]);
// here, we query 1, 2 twice, however, in fact same id will be query only once inside fods

renew(MyList, [2, 3]);

Notice, the first parameter should be an array, and all of items should be same data type. The rest parameters will be passed.

const MyList = compose(
    (ids: string[], ...params: any[]) => {
        return Promise.all(ids.map(id => fetchData(id, ...params)))
    },
    (res, id: string) => res.find(item => item.id === id),
);

const lite = await query(MyList, [1, 2], 'var1', 'var2');

action & take

Define a ACTION_TYPE store by action and consume it by take.

import { action, take } from 'fods';

const AddUserBook = action(async (book) => {
    // send save book request

    // after we add a new book, we should renew the UserBookList in store
    await renew(UserBookList);
});

stream & subscribe

import { stream, subscribe } from 'fods';

const UserBookRepo = stream(({ ondata, onend, onerror }) => (uid) => {
    const stream = requestUserBooksStream(uid);
    stream.on('data', ondata);
    stream.on('end', onend);
    stream.on('error', onerror);
});

const emit = subscribe(UserBookRepo, {
    ondata(chunk) {},
    onend(chunks) {},
    onerror(e) {},
});

emit('123');

renew

Clear store and request again.

const newData = await renew(SomeSource, '123');
const newSubscribe = await renew(SomeStream, '123');

Renew stream will not request again, only clear store.

clear

Clear store.

clear(SomeSource, '123');

read

Read from store without request.

const data = read(SomeSource, 123); // notice, without `await`

request

Send a request with given source or stream outside the store.

const data = await request(SomeSource, 123); // without any affect to the store

Request stream will return a Promise resolved when the end event be triggered.

isTypeOf

Check whether the given object is type of a usable type.

import { isTypeOf, SOURCE_TYPE, STREAM_TYPE, ACTION_TYPE } from 'fods';

if (isTypeOf(obj, SOURCE_TYPE, STREAM_TYPE)) {
    // ...
}

addListener & removeListener

Watch store data change.

const listener = (params, data) => {
    const [uid] = params;
    if (uid === 123) {
        // do some thing with data
    }
};

const unlisten = addListener(SomeSource, 'change', listener);

removeListener(SomeSource, 'change', listener);
// or
unlisten();

Events:

  • Source & Compose: 'change' | 'beforeRenew' | 'afterRenew' | 'beforeClear' | 'afterClear'
  • Stream: 'data' | 'end' | 'error' | 'beforeClear' | 'afterClear'

Quick Use

const queryBook = source((id) => {
    // ...
});
const book = await queryBook(123);
renew(queryBook, 123);
const BookSource = source((id) => {
    // ...
});
const book = await BookSource.query(id);
BookSource.renew(id);
  • source, compose => query { query, request, renew, read, clear }
  • stream => subscribe { subscribe, request, renew, read, clear }
  • action => take { take, request }
const subscribeSomeStream = stream(({ ondata, onend, onerror }) => {
    // ...
});

const emit = subscribeSomeStream({
    ondata: () => {},
    onend: () => {},
    onerror: () => {},
});

emit('arg');