
Security News
Another Round of TEA Protocol Spam Floods npm, But It’s Not a Worm
Recent coverage mislabels the latest TEA protocol spam as a worm. Here’s what’s actually happening.
comp-select
Advanced tools
A re-select enhancer designed to work along-side your existing selectors. It allows document linking and composable transformations written in a declarative manner giving you part of the power of an ORM without all the work.
type State = {
fooHash: {
[Foo.id]: Foo,
},
selectedFooIds: Array<Foo.id>,
barHash: {
[Bar.id]: Bar,
};
}
type Foo = {
id: FooId,
links: {
bars: Array<Bar.id>,
}
};
type BarHash = {
[BarId]: Bar,
};
type Bar = {
id: BarId,
name: string,
};
const getSelectedFooIds = (state) => state.selectedFooIds
const getFooHash = (state) => state.fooHash
const getBarHash = (state) => state.barHash
const getBarNamesFromFooIds = composableSelector(getSelectedFooIds)
.populate(getFooHash);
.populate({
'links.bars': getBarHash,
})
.flatten('links.bars')
.getEach('name')
.create();
const getBarNamesFromFooIds = createSelector(getSelectedFooIds, getFooHash, getBarHash,
(selectedFooIds, fooHash, barHash) => {
const selectedFoos = selectedFooIds.map((id) => fooHash[id]);
const selectedFooWithBars = [...selectedFoos]((foo) => {
foo.links.bars = foo.links.bars.map((barId) => barHash[barId]);
});
const selectedBars = [].concat(
...selectedFooWithBars.map((foo) => get(foo, 'links.bars')));
return selectedBars.map((bar) => bar.name);
});
There are three main categories of Transformers
Takes static values as arguments such as path.
For example, in order to get target value
obj = { outer: { inner: { superInner: 'target value' } } };
You can use get
.get('outer.inner.superInner')
The path used, outer.inner.superInner never changes.
.get(Path): *.getEach(Path): Array<*>.flatten(Path): Array<*>.keys()Object.keys().values()Object.values().slice(index, length): Array<*>Array.prototype.sliceSelector based transformers work like re-select selectors.
Each takes a list of selectors, ending with a resultFunc Function. resultFunc will receive the results of each selector in order, the final argument will be the previous output.
.select(selectorA, selectorB, (a, b, previousOutput) => {
// Do something
})
Selector Transformers don't require selectors as arguments. For example:
composableSelector(getItems)
.filter((item) => item.isValid)
Only the resultFunc is provided, no selectors.
.select(...inputSelectors, resultFunc): *inputSelectorsresultFunc as the last argument
resultFunc receives selector outputs as arguments, in orderresultFunc receives previous output as the last argument.filter(...inputSelectors, resultFunc): Array<*>inputSelectorsresultFunc as the last argument
resultFunc receives selector outputs as arguments, in orderresultFunc gets called for each item in the previous outputresultFunc is expected to return true or false.map(...inputSelectors, resultFunc): *inputSelectorsresultFunc as the last argument
resultFunc receives selector outputs as arguments, in orderresultFunc gets called for each item in the previous outputresultFunc is expected to return true or falsepopulate is used to populate id fields with records from a hash selector.
.populate(SELECTOR)
SELECTOR result for each idconst getSelectedFoos = composableSelector(getSelectedFooIds)
.populate(getFooHash);
.populate(PATH, SELECTOR)
SELECTOR result for each id at PATH on each passed recordconst getSelectedFoosWithBars = composableSelector(getSelectedFoos)
.populate('links.bars', getBarHash);
.populate({ [PATH]: SELECTOR })
SELECTOR result for each id at PATH on each passed recordconst getSelectedFoosWithBarsAndBaz = composableSelector(getSelectedFoos)
.populate({
'links.bars': getBarHash,
'links.baz': getBazHash,
});
It is easy to add new, or custom transformers. As transformers become universal, they may be added to the standard transformers. Otherwise, they'll
registerTransformers({
filter: {
type: SELECTOR,
fn: (task) => (args) => {
const { deps, last } = splitDepsLast(args);
return last.filter((item) => task.resultFunc(...deps, item));
}
}
});
getConversationsByThreadexport const getConversationsByThread = composableSelector(getSelectedThreads)
.populate('links.conversations', getConversations)
.flatten('links.conversations')
.create();
export const getConversationsByThread = createSelector(
getConversations,
getThreadIdsSelected,
(conversations = {}, threadIds = []) => {
const values = Object.keys(conversations)
.map((key) => conversations[key]);
const initialValue = [];
return threadIds.reduce((prev, id) =>
[...prev, ...deepFilter(values, 'links.shared_thread', id)],
initialValue
);
}
);
getMessagesByThreadIdsNote how filter is formatted like a selector. Transformers which take functions have the option of including additional selector dependencies which will be used only in that function.
const getMessagesByThreadIds = composableSelector(getMessages)
.values()
.filter(
(_, props) => props.threadIds,
(ids, message) => ids.some((id) => id === get(message, 'links.thread'))
)
.create();
export const getMessagesByThreadIds = createSelector(
getMessages,
(_, props) => props.threadIds,
(messages, threadIds) => filterMessagesByThreadIds(messages, threadIds)
);
export function filterMessagesByThreadIds(messages: MessagesHash, threadIds: ThreadIds) {
if (!threadIds) return [];
return Object
.values(messages)
.filter((message) => {
if (!message.links || !message.links.thread) return false;
const linkedThreadId = message.links.thread;
return threadIds.some((threadId) => threadId === linkedThreadId);
});
}
getMessagesByThreadSelectedexport const getMessagesByThreadSelected = composableSelector(getThreadIdsSelected)
.slice(0, 1)
.populate(getThreadsHash)
.populate('links.messages', getMessages)
.flatten('links.messages')
.fallback([])
.create();
export const getMessagesByThreadSelected = createSelector(
getThreadIdsSelected,
getMessages,
getThreadsHash,
(threadIds = [], messagesHash = {}, threadsHash = {}) => {
if (threadIds.length === 0 || threadIds.length > 1) return [];
const selectedThread = threadsHash[threadIds[0]];
if (!selectedThread) return [];
const threadMessages = get(selectedThread, 'links.messages', []);
const messages = threadMessages.map((id) => messagesHash[id]);
return messages.filter((message) => message !== undefined);
}
);
The original api concept which led to comp-select
const getThreadMessages = createStrictSelector({
transformer: flattenLinks,
sources: getSelectedThreads,
dependencies: {
'links.messages': getMessageHash,
},
fallbackValue: [],
});
FAQs
Create transform functions.
The npm package comp-select receives a total of 0 weekly downloads. As such, comp-select popularity was classified as not popular.
We found that comp-select 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
Recent coverage mislabels the latest TEA protocol spam as a worm. Here’s what’s actually happening.

Security News
PyPI adds Trusted Publishing support for GitLab Self-Managed as adoption reaches 25% of uploads

Research
/Security News
A malicious Chrome extension posing as an Ethereum wallet steals seed phrases by encoding them into Sui transactions, enabling full wallet takeover.