
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
Make frontend data request more controllable.
npm i fods
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');
A store is a place to put data in local, when we invoke
queryemitortake, we find some thing in local store and reuse them, so that we can reduce the real request count, and share data amoung requests.
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:
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);
const subscribeSomeStream = stream(({ ondata, onend, onerror }) => {
// ...
});
const emit = subscribeSomeStream({
ondata: () => {},
onend: () => {},
onerror: () => {},
});
emit('arg');
FAQs
Frontend Operational Data Store
We found that fods demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.