
Security News
/Research
Wallet-Draining npm Package Impersonates Nodemailer to Hijack Crypto Transactions
Malicious npm package impersonates Nodemailer and drains wallets by hijacking crypto transactions across multiple blockchains.
generator-tfountain-redux-reducer
Advanced tools
A Yeoman generator for @doches' opinionated redux reducers
A strongly-opinionated Yeoman generator for scaffolding out a redux reducer (and associated state slice & api calls) based on the way that @doches likes to set things up. Probably not useful for you, but tremendously useful for him.
Install Yeoman via yarn, or npm, or whatever JS package manager is hot this week:
$ yarn global add yo
Once you've got Yeoman set up, install this generator:
$ yarn global add generator-tfountain-redux-reducer
Move into the directory in your project where you want to create the new redux slice, and invoke Yeoman:
$ cd awesome-project/src/state
$ yo tfountain-redux-reducer
Tell Yeoman about your type name for this reducer, then sit back and bask in the glory of a lovely autogenerated piece of boilerplate that you didn't have to write. Finish your application. Move on with your life. Maybe write that novel you've always been dreaming about, or start learning the drums.
Go on. Live a little.
By way of example, the generator will ask you for singluar (e.g. "item") and plural (e.g. "items") type names, then produce a file like this:
import { Dispatch } from "redux";
import { baseURL, headers } from "./api";
export interface IItemsState {
fetchPending: boolean;
fetched: boolean;
updatePending: boolean;
items: IItem[];
}
export const DEFAULT_ITEMS_STATE: IItemsState = {
fetchPending: false,
fetched: false,
updatePending: false,
items: [],
}
export const SET_FETCH_PENDING = "@@items/SET_FETCH_PENDING";
export const SET_UPDATE_PENDING = "@@items/SET_UPDATE_PENDING";
export const SET_ITEMS = "@@items/SET_ITEMS";
export const ADD_ITEM = "@@items/ADD_ITEM";
export const REMOVE_ITEM = "@@items/REMOVE_ITEM";
export const UPDATE_ITEM = "@@items/UPDATE_ITEM";
export function setFetchPending(pending: boolean) {
return {
type: SET_FETCH_PENDING,
pending,
};
}
export function setUpdatePending(pending: boolean) {
return {
type: SET_UPDATE_PENDING,
pending,
};
}
export function setItems(items: IItem[]) {
return {
type: SET_ITEMS,
items,
};
}
export function addItem(item: IItem) {
return {
type: ADD_ITEM,
item,
};
}
export function removeItem(itemId: number) {
return {
type: REMOVE_ITEM,
id: itemId,
};
}
function replaceItem(item: IItem) {
return {
type: UPDATE_ITEM,
item,
};
}
export function createItem(item: IItem) {
return (dispatch: Dispatch<any>) => {
dispatch(setUpdatePending(true));
return fetch(`${baseURL}items/create`, {
headers,
method: "POST",
body: JSON.stringify(item),
})
.then((response: Response) => {
if (!response.ok) {
throw new Error();
}
return response.json();
})
.then((created: IItem) => {
dispatch(addItem(created));
})
.catch((error: any) => {
console.error(error);
})
.finally(() => {
dispatch(setUpdatePending(false));
});
}
}
export function listItems() {
return (dispatch: Dispatch<any>) => {
dispatch(setFetchPending(true));
return fetch(`${baseURL}items/list`, {
headers,
method: "GET",
})
.then((response: Response) => {
if (!response.ok) {
throw new Error();
}
return response.json();
})
.then((items: IItem[]) => {
dispatch(setItems(items));
})
.catch((error: any) => {
console.error(error);
})
.finally(() => {
dispatch(setFetchPending(false));
});
}
}
export function updateItem(item: IItem) {
return (dispatch: Dispatch<any>) => {
dispatch(setUpdatePending(true));
return fetch(`${baseURL}items/update`, {
headers,
method: "POST",
body: JSON.stringify(item),
})
.then((response: Response) => {
if (!response.ok) {
throw new Error();
}
dispatch(replaceItem(item));
})
.catch((error: any) => {
console.error(error);
})
.finally(() => {
dispatch(setUpdatePending(false));
});
}
}
export function deleteItem(itemId: number) {
return (dispatch: Dispatch<any>) => {
dispatch(setUpdatePending(true));
return fetch(`${baseURL}items/${itemId}/delete`, {
headers,
method: "POST",
})
.then((response: Response) => {
if (!response.ok) {
throw new Error();
}
dispatch(removeItem(itemId));
})
.catch((error: any) => {
console.error(error);
})
.finally(() => {
dispatch(setUpdatePending(false));
});
}
}
export function items(state: IItemsState, action: any) {
if (!state) {
state = DEFAULT_ITEMS_STATE;
}
switch (action.type) {
default:
return state;
case SET_FETCH_PENDING:
return {
...state,
fetchPending: action.pending,
};
case SET_UPDATE_PENDING:
return {
...state,
updatePending: action.pending,
};
case SET_ITEMS:
return {
...state,
fetchPending: false,
fetched: true,
items: action.items,
};
case ADD_ITEM:
return {
...state,
updatePending: false,
items: [
...state.items,
action.item,
],
};
case REMOVE_ITEM:
return {
...state,
updatePending: false,
items: state.items.filter((item: IItem) => item.id != action.item.id),
};
case UPDATE_ITEM:
return {
...state,
updatePending: false,
items: state.items.map((item: IItem) => item.id === action.item.id ? action.item : item),
};
}
}
FAQs
A Yeoman generator for @doches' opinionated redux reducers
We found that generator-tfountain-redux-reducer 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
/Research
Malicious npm package impersonates Nodemailer and drains wallets by hijacking crypto transactions across multiple blockchains.
Security News
This episode explores the hard problem of reachability analysis, from static analysis limits to handling dynamic languages and massive dependency trees.
Security News
/Research
Malicious Nx npm versions stole secrets and wallet info using AI CLI tools; Socket’s AI scanner detected the supply chain attack and flagged the malware.