@slangy/react
Advanced tools
| import { CrudStore } from '../stores/createCrudStore.js'; | ||
| /** | ||
| * A function that removes an item from a collection based on its ID. | ||
| * | ||
| * @template Item The type of the collection item. | ||
| * @template ItemId The type of the item's identifier. | ||
| */ | ||
| type CrudRemover<Item, ItemId extends keyof Item> = (itemId: Item[ItemId]) => Promise<void>; | ||
| /** | ||
| * Parameters required to create a custom CRUD hook. | ||
| * | ||
| * @template ReaderArgs The types of arguments accepted by the read function. | ||
| * @template CreateItemType The type of item being created. | ||
| * @template UpdateItemType The type of item being updated. | ||
| * @template ReaderReturnType The type of data returned from the read function. | ||
| * @template Extra Any extra properties or methods the resulting hook should have. | ||
| * @template TransformedType The type of data returned after optional transformation. | ||
| * @template ItemId The type of the item's identifier in the transformed data. | ||
| * @template Remover The type for the remove function. | ||
| */ | ||
| type CreateCrudHookParams<ReaderArgs extends unknown[], CreateItemType, UpdateItemType, ReaderReturnType, Extra, TransformedType, ItemId extends keyof TransformedType, Remover extends CrudRemover<TransformedType, ItemId>> = { | ||
| store: () => CrudStore<TransformedType, ItemId>; | ||
| create: (item: CreateItemType) => Promise<TransformedType>; | ||
| read: (...args: ReaderArgs) => Promise<ReaderReturnType>; | ||
| update: (item: UpdateItemType) => Promise<TransformedType>; | ||
| remove: Remover; | ||
| transform?: (data?: ReaderReturnType) => TransformedType[]; | ||
| extra?: (data: TransformedType[]) => Extra; | ||
| }; | ||
| /** | ||
| * A utility hook to create a custom CRUD hook with optional data transformation. | ||
| * | ||
| * @template ReaderArgs The types of arguments accepted by the read function. | ||
| * @template CreateItemType The type of item being created. | ||
| * @template UpdateItemType The type of item being updated. | ||
| * @template ReaderReturnType The type of data returned from the read function. | ||
| * @template Extra Any extra properties or methods the resulting hook should have. | ||
| * @template TransformedType The type of data returned after optional transformation. | ||
| * @template ItemId The type of the item's identifier in the transformed data. | ||
| * @template Remove The type for the remove function. | ||
| */ | ||
| declare const createCrudHook: <ReaderArgs extends unknown[], CreateItemType, UpdateItemType, ReaderReturnType, Extra, TransformedType = ReaderReturnType, ItemId extends keyof TransformedType = "id" extends keyof TransformedType ? "id" : never, Remove extends CrudRemover<TransformedType, ItemId> = CrudRemover<TransformedType, ItemId>>({ store, create, read, update, remove, transform, extra, }: CreateCrudHookParams<ReaderArgs, CreateItemType, UpdateItemType, ReaderReturnType, Extra, TransformedType, ItemId, Remove>) => (...args: ReaderArgs) => { | ||
| data: TransformedType[]; | ||
| error: Error | undefined; | ||
| isLoading: boolean; | ||
| create(item: CreateItemType): Promise<void>; | ||
| remove(itemId: TransformedType[ItemId]): Promise<void>; | ||
| update(item: UpdateItemType): Promise<void>; | ||
| } & Extra; | ||
| export default createCrudHook; | ||
| //# sourceMappingURL=createCrudHook.d.ts.map |
| {"version":3,"file":"createCrudHook.d.ts","sourceRoot":"","sources":["../../src/hooks/createCrudHook.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AAEzD;;;;;GAKG;AACH,KAAK,WAAW,CAAC,IAAI,EAAE,MAAM,SAAS,MAAM,IAAI,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAE5F;;;;;;;;;;;GAWG;AACH,KAAK,oBAAoB,CACvB,UAAU,SAAS,OAAO,EAAE,EAC5B,cAAc,EACd,cAAc,EACd,gBAAgB,EAChB,KAAK,EACL,eAAe,EACf,MAAM,SAAS,MAAM,eAAe,EACpC,OAAO,SAAS,WAAW,CAAC,eAAe,EAAE,MAAM,CAAC,IAClD;IACF,KAAK,EAAE,MAAM,SAAS,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC;IAChD,MAAM,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,OAAO,CAAC,eAAe,CAAC,CAAC;IAC3D,IAAI,EAAE,CAAC,GAAG,IAAI,EAAE,UAAU,KAAK,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACzD,MAAM,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,OAAO,CAAC,eAAe,CAAC,CAAC;IAC3D,MAAM,EAAE,OAAO,CAAC;IAChB,SAAS,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,gBAAgB,KAAK,eAAe,EAAE,CAAC;IAC3D,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,eAAe,EAAE,KAAK,KAAK,CAAC;CAC5C,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,QAAA,MAAM,cAAc;;;;;;;SA0FnB,CAAC;AAEF,eAAe,cAAc,CAAC"} |
| import { useEffect, useState } from 'react'; | ||
| /** | ||
| * A utility hook to create a custom CRUD hook with optional data transformation. | ||
| * | ||
| * @template ReaderArgs The types of arguments accepted by the read function. | ||
| * @template CreateItemType The type of item being created. | ||
| * @template UpdateItemType The type of item being updated. | ||
| * @template ReaderReturnType The type of data returned from the read function. | ||
| * @template Extra Any extra properties or methods the resulting hook should have. | ||
| * @template TransformedType The type of data returned after optional transformation. | ||
| * @template ItemId The type of the item's identifier in the transformed data. | ||
| * @template Remove The type for the remove function. | ||
| */ | ||
| const createCrudHook = ({ store, create, read, update, remove, transform = (data) => data, extra, }) => { | ||
| /** | ||
| * Hook that provides CRUD operations and manages data state. | ||
| * | ||
| * @param args The arguments required for the read operation. | ||
| * @returns object An object containing data, loading error and CRUD operations (and fields from extra factory). | ||
| */ | ||
| return function useData(...args) { | ||
| const [isLoading, setIsLoading] = useState(true); | ||
| const [error, setError] = useState(undefined); | ||
| const { data, set, create: createInStore, update: updateInStore, remove: removeFromStore, } = store(); | ||
| useEffect(() => { | ||
| const fetchData = async () => { | ||
| setIsLoading(true); | ||
| setError(undefined); | ||
| try { | ||
| const result = await read(...args); | ||
| set(transform(result)); | ||
| } | ||
| catch (err) { | ||
| setError(err); | ||
| } | ||
| finally { | ||
| setIsLoading(false); | ||
| } | ||
| }; | ||
| if (data.length === 0) { | ||
| fetchData(); | ||
| } | ||
| // eslint-disable-next-line react-hooks/exhaustive-deps | ||
| }, [...args, set, data.length]); | ||
| const extraProperties = extra ? extra(data) : undefined; | ||
| const hook = { | ||
| data: data, | ||
| error: error, | ||
| isLoading: isLoading, | ||
| async create(item) { | ||
| const newItem = await create(item); | ||
| createInStore(newItem); | ||
| }, | ||
| async remove(itemId) { | ||
| await remove(itemId); | ||
| removeFromStore(itemId); | ||
| }, | ||
| async update(item) { | ||
| const updatedItem = await update(item); | ||
| updateInStore(updatedItem); | ||
| }, | ||
| }; | ||
| return { | ||
| ...hook, | ||
| ...extraProperties, | ||
| }; | ||
| }; | ||
| }; | ||
| export default createCrudHook; | ||
| //# sourceMappingURL=createCrudHook.js.map |
| {"version":3,"file":"createCrudHook.js","sourceRoot":"","sources":["../../src/hooks/createCrudHook.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AA2C5C;;;;;;;;;;;GAWG;AACH,MAAM,cAAc,GAAG,CASrB,EACA,KAAK,EACL,MAAM,EACN,IAAI,EACJ,MAAM,EACN,MAAM,EACN,SAAS,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC,IAAyB,EAC/C,KAAK,GAUN,EAAE,EAAE;IACH;;;;;OAKG;IACH,OAAO,SAAS,OAAO,CAAC,GAAG,IAAgB;QACzC,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;QACjD,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAoB,SAAS,CAAC,CAAC;QAEjE,MAAM,EACJ,IAAI,EACJ,GAAG,EACH,MAAM,EAAE,aAAa,EACrB,MAAM,EAAE,aAAa,EACrB,MAAM,EAAE,eAAe,GACxB,GAAG,KAAK,EAAE,CAAC;QAEZ,SAAS,CAAC,GAAG,EAAE;YACb,MAAM,SAAS,GAAG,KAAK,IAAI,EAAE;gBAC3B,YAAY,CAAC,IAAI,CAAC,CAAC;gBACnB,QAAQ,CAAC,SAAS,CAAC,CAAC;gBACpB,IAAI;oBACF,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;oBACnC,GAAG,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;iBACxB;gBAAC,OAAO,GAAG,EAAE;oBACZ,QAAQ,CAAC,GAAY,CAAC,CAAC;iBACxB;wBAAS;oBACR,YAAY,CAAC,KAAK,CAAC,CAAC;iBACrB;YACH,CAAC,CAAC;YAEF,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE;gBACrB,SAAS,EAAE,CAAC;aACb;YACD,uDAAuD;QACzD,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;QAEhC,MAAM,eAAe,GAAG,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAExD,MAAM,IAAI,GAAG;YACX,IAAI,EAAE,IAAI;YACV,KAAK,EAAE,KAAK;YACZ,SAAS,EAAE,SAAS;YACpB,KAAK,CAAC,MAAM,CAAC,IAAoB;gBAC/B,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,CAAC;gBACnC,aAAa,CAAC,OAAO,CAAC,CAAC;YACzB,CAAC;YACD,KAAK,CAAC,MAAM,CAAC,MAA+B;gBAC1C,MAAM,MAAM,CAAC,MAAM,CAAC,CAAC;gBACrB,eAAe,CAAC,MAAM,CAAC,CAAC;YAC1B,CAAC;YACD,KAAK,CAAC,MAAM,CAAC,IAAoB;gBAC/B,MAAM,WAAW,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,CAAC;gBACvC,aAAa,CAAC,WAAW,CAAC,CAAC;YAC7B,CAAC;SACF,CAAC;QAEF,OAAO;YACL,GAAG,IAAI;YACP,GAAI,eAAyB;SAC9B,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC,CAAC;AAEF,eAAe,cAAc,CAAC"} |
| /** | ||
| * Return type of crudStoreFactory. | ||
| * | ||
| * @template ItemType The types of element the store holds. | ||
| * @template ItemId The id of ItemType. | ||
| */ | ||
| export type CrudStore<ItemType, ItemId extends keyof ItemType> = { | ||
| data: ItemType[]; | ||
| set: (items: ItemType[]) => void; | ||
| create: (...items: ItemType[]) => void; | ||
| remove: (idToRemove: ItemType[ItemId]) => void; | ||
| update: (updatedItem: ItemType) => void; | ||
| }; | ||
| /** | ||
| * Parameters required to create a custom crud store. | ||
| * | ||
| * @template ItemType The types of element the store holds. | ||
| * @template ItemId The id of ItemType. | ||
| */ | ||
| type CrudStoreFactoryParams<ItemType, ItemId extends keyof ItemType> = { | ||
| idKey?: ItemId; | ||
| }; | ||
| /** | ||
| * A utility hook to create a custom zustand based crud store. | ||
| * @param idKey | ||
| */ | ||
| declare const createCrudStore: <ItemType, ItemId extends keyof ItemType = "id" extends keyof ItemType ? "id" : never>({ idKey }?: CrudStoreFactoryParams<ItemType, ItemId>) => import("zustand").UseBoundStore<import("zustand").StoreApi<CrudStore<ItemType, ItemId>>>; | ||
| export default createCrudStore; | ||
| //# sourceMappingURL=createCrudStore.d.ts.map |
| {"version":3,"file":"createCrudStore.d.ts","sourceRoot":"","sources":["../../src/stores/createCrudStore.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,MAAM,MAAM,SAAS,CAAC,QAAQ,EAAE,MAAM,SAAS,MAAM,QAAQ,IAAI;IAC/D,IAAI,EAAE,QAAQ,EAAE,CAAC;IACjB,GAAG,EAAE,CAAC,KAAK,EAAE,QAAQ,EAAE,KAAK,IAAI,CAAC;IACjC,MAAM,EAAE,CAAC,GAAG,KAAK,EAAE,QAAQ,EAAE,KAAK,IAAI,CAAC;IACvC,MAAM,EAAE,CAAC,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC;IAC/C,MAAM,EAAE,CAAC,WAAW,EAAE,QAAQ,KAAK,IAAI,CAAC;CACzC,CAAC;AAEF;;;;;GAKG;AACH,KAAK,sBAAsB,CAAC,QAAQ,EAAE,MAAM,SAAS,MAAM,QAAQ,IAAI;IACrE,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF;;;GAGG;AACH,QAAA,MAAM,eAAe,0OAsBhB,CAAC;AAEN,eAAe,eAAe,CAAC"} |
| import { create } from 'zustand'; | ||
| /** | ||
| * A utility hook to create a custom zustand based crud store. | ||
| * @param idKey | ||
| */ | ||
| const createCrudStore = ({ idKey = 'id' } = {}) => create((setStore) => ({ | ||
| data: [], | ||
| set: (items) => { | ||
| setStore(() => ({ data: [...items] })); | ||
| }, | ||
| create: (...items) => { | ||
| setStore((state) => ({ data: [...state.data, ...items] })); | ||
| }, | ||
| update: (updatedItem) => { | ||
| setStore((state) => ({ | ||
| data: state.data.map((item) => (item[idKey] === updatedItem[idKey] ? updatedItem : item)), | ||
| })); | ||
| }, | ||
| remove: (idToRemove) => { | ||
| setStore((state) => ({ | ||
| data: state.data.filter((item) => item[idKey] !== idToRemove), | ||
| })); | ||
| }, | ||
| })); | ||
| export default createCrudStore; | ||
| //# sourceMappingURL=createCrudStore.js.map |
| {"version":3,"file":"createCrudStore.js","sourceRoot":"","sources":["../../src/stores/createCrudStore.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AA0BjC;;;GAGG;AACH,MAAM,eAAe,GAAG,CAGtB,EAAE,KAAK,GAAG,IAAc,KAA+C,EAAE,EAAE,EAAE,CAC7E,MAAM,CAA8B,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;IACjD,IAAI,EAAE,EAAE;IACR,GAAG,EAAE,CAAC,KAAiB,EAAE,EAAE;QACzB,QAAQ,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,GAAG,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;IACzC,CAAC;IACD,MAAM,EAAE,CAAC,GAAG,KAAiB,EAAE,EAAE;QAC/B,QAAQ,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,GAAG,KAAK,CAAC,IAAI,EAAE,GAAG,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;IAC7D,CAAC;IACD,MAAM,EAAE,CAAC,WAAqB,EAAE,EAAE;QAChC,QAAQ,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YACnB,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;SAC1F,CAAC,CAAC,CAAC;IACN,CAAC;IACD,MAAM,EAAE,CAAC,UAA4B,EAAE,EAAE;QACvC,QAAQ,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YACnB,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,UAAU,CAAC;SAC9D,CAAC,CAAC,CAAC;IACN,CAAC;CACF,CAAC,CAAC,CAAC;AAEN,eAAe,eAAe,CAAC"} |
| import { useEffect, useState } from 'react'; | ||
| import { CrudStore } from '../stores/createCrudStore.js'; | ||
| /** | ||
| * A function that removes an item from a collection based on its ID. | ||
| * | ||
| * @template Item The type of the collection item. | ||
| * @template ItemId The type of the item's identifier. | ||
| */ | ||
| type CrudRemover<Item, ItemId extends keyof Item> = (itemId: Item[ItemId]) => Promise<void>; | ||
| /** | ||
| * Parameters required to create a custom CRUD hook. | ||
| * | ||
| * @template ReaderArgs The types of arguments accepted by the read function. | ||
| * @template CreateItemType The type of item being created. | ||
| * @template UpdateItemType The type of item being updated. | ||
| * @template ReaderReturnType The type of data returned from the read function. | ||
| * @template Extra Any extra properties or methods the resulting hook should have. | ||
| * @template TransformedType The type of data returned after optional transformation. | ||
| * @template ItemId The type of the item's identifier in the transformed data. | ||
| * @template Remover The type for the remove function. | ||
| */ | ||
| type CreateCrudHookParams< | ||
| ReaderArgs extends unknown[], | ||
| CreateItemType, | ||
| UpdateItemType, | ||
| ReaderReturnType, | ||
| Extra, | ||
| TransformedType, | ||
| ItemId extends keyof TransformedType, | ||
| Remover extends CrudRemover<TransformedType, ItemId>, | ||
| > = { | ||
| store: () => CrudStore<TransformedType, ItemId>; | ||
| create: (item: CreateItemType) => Promise<TransformedType>; | ||
| read: (...args: ReaderArgs) => Promise<ReaderReturnType>; | ||
| update: (item: UpdateItemType) => Promise<TransformedType>; | ||
| remove: Remover; | ||
| transform?: (data?: ReaderReturnType) => TransformedType[]; | ||
| extra?: (data: TransformedType[]) => Extra; | ||
| }; | ||
| /** | ||
| * A utility hook to create a custom CRUD hook with optional data transformation. | ||
| * | ||
| * @template ReaderArgs The types of arguments accepted by the read function. | ||
| * @template CreateItemType The type of item being created. | ||
| * @template UpdateItemType The type of item being updated. | ||
| * @template ReaderReturnType The type of data returned from the read function. | ||
| * @template Extra Any extra properties or methods the resulting hook should have. | ||
| * @template TransformedType The type of data returned after optional transformation. | ||
| * @template ItemId The type of the item's identifier in the transformed data. | ||
| * @template Remove The type for the remove function. | ||
| */ | ||
| const createCrudHook = < | ||
| ReaderArgs extends unknown[], | ||
| CreateItemType, | ||
| UpdateItemType, | ||
| ReaderReturnType, | ||
| Extra, | ||
| TransformedType = ReaderReturnType, | ||
| ItemId extends keyof TransformedType = 'id' extends keyof TransformedType ? 'id' : never, | ||
| Remove extends CrudRemover<TransformedType, ItemId> = CrudRemover<TransformedType, ItemId>, | ||
| >({ | ||
| store, | ||
| create, | ||
| read, | ||
| update, | ||
| remove, | ||
| transform = (data) => data as TransformedType[], | ||
| extra, | ||
| }: CreateCrudHookParams< | ||
| ReaderArgs, | ||
| CreateItemType, | ||
| UpdateItemType, | ||
| ReaderReturnType, | ||
| Extra, | ||
| TransformedType, | ||
| ItemId, | ||
| Remove | ||
| >) => { | ||
| /** | ||
| * Hook that provides CRUD operations and manages data state. | ||
| * | ||
| * @param args The arguments required for the read operation. | ||
| * @returns object An object containing data, loading error and CRUD operations (and fields from extra factory). | ||
| */ | ||
| return function useData(...args: ReaderArgs) { | ||
| const [isLoading, setIsLoading] = useState(true); | ||
| const [error, setError] = useState<Error | undefined>(undefined); | ||
| const { | ||
| data, | ||
| set, | ||
| create: createInStore, | ||
| update: updateInStore, | ||
| remove: removeFromStore, | ||
| } = store(); | ||
| useEffect(() => { | ||
| const fetchData = async () => { | ||
| setIsLoading(true); | ||
| setError(undefined); | ||
| try { | ||
| const result = await read(...args); | ||
| set(transform(result)); | ||
| } catch (err) { | ||
| setError(err as Error); | ||
| } finally { | ||
| setIsLoading(false); | ||
| } | ||
| }; | ||
| if (data.length === 0) { | ||
| fetchData(); | ||
| } | ||
| // eslint-disable-next-line react-hooks/exhaustive-deps | ||
| }, [...args, set, data.length]); | ||
| const extraProperties = extra ? extra(data) : undefined; | ||
| const hook = { | ||
| data: data, | ||
| error: error, | ||
| isLoading: isLoading, | ||
| async create(item: CreateItemType) { | ||
| const newItem = await create(item); | ||
| createInStore(newItem); | ||
| }, | ||
| async remove(itemId: TransformedType[ItemId]) { | ||
| await remove(itemId); | ||
| removeFromStore(itemId); | ||
| }, | ||
| async update(item: UpdateItemType) { | ||
| const updatedItem = await update(item); | ||
| updateInStore(updatedItem); | ||
| }, | ||
| }; | ||
| return { | ||
| ...hook, | ||
| ...(extraProperties as Extra), | ||
| }; | ||
| }; | ||
| }; | ||
| export default createCrudHook; |
| import { create } from 'zustand'; | ||
| /** | ||
| * Return type of crudStoreFactory. | ||
| * | ||
| * @template ItemType The types of element the store holds. | ||
| * @template ItemId The id of ItemType. | ||
| */ | ||
| export type CrudStore<ItemType, ItemId extends keyof ItemType> = { | ||
| data: ItemType[]; | ||
| set: (items: ItemType[]) => void; | ||
| create: (...items: ItemType[]) => void; | ||
| remove: (idToRemove: ItemType[ItemId]) => void; | ||
| update: (updatedItem: ItemType) => void; | ||
| }; | ||
| /** | ||
| * Parameters required to create a custom crud store. | ||
| * | ||
| * @template ItemType The types of element the store holds. | ||
| * @template ItemId The id of ItemType. | ||
| */ | ||
| type CrudStoreFactoryParams<ItemType, ItemId extends keyof ItemType> = { | ||
| idKey?: ItemId; | ||
| }; | ||
| /** | ||
| * A utility hook to create a custom zustand based crud store. | ||
| * @param idKey | ||
| */ | ||
| const createCrudStore = < | ||
| ItemType, | ||
| ItemId extends keyof ItemType = 'id' extends keyof ItemType ? 'id' : never, | ||
| >({ idKey = 'id' as ItemId }: CrudStoreFactoryParams<ItemType, ItemId> = {}) => | ||
| create<CrudStore<ItemType, ItemId>>((setStore) => ({ | ||
| data: [], | ||
| set: (items: ItemType[]) => { | ||
| setStore(() => ({ data: [...items] })); | ||
| }, | ||
| create: (...items: ItemType[]) => { | ||
| setStore((state) => ({ data: [...state.data, ...items] })); | ||
| }, | ||
| update: (updatedItem: ItemType) => { | ||
| setStore((state) => ({ | ||
| data: state.data.map((item) => (item[idKey] === updatedItem[idKey] ? updatedItem : item)), | ||
| })); | ||
| }, | ||
| remove: (idToRemove: ItemType[ItemId]) => { | ||
| setStore((state) => ({ | ||
| data: state.data.filter((item) => item[idKey] !== idToRemove), | ||
| })); | ||
| }, | ||
| })); | ||
| export default createCrudStore; |
+27
-21
| { | ||
| "root": true, | ||
| "env": { | ||
| "node": true, | ||
| "es6": true | ||
| "browser": true, | ||
| "es2020": true | ||
| }, | ||
| "extends": [ | ||
| "eslint:recommended", | ||
| "plugin:@typescript-eslint/recommended", | ||
| "plugin:jest/recommended", | ||
| "plugin:jest/style", | ||
| // "plugin:@typescript-eslint/recommended", | ||
| "plugin:eslint-comments/recommended", | ||
| "plugin:import/errors", | ||
| "plugin:import/warnings", | ||
| "plugin:import/recommended", | ||
| "plugin:import/typescript", | ||
| // "plugin:n/recommended-module", currently not working properly with typescript, review in the future | ||
| "plugin:react/recommended", | ||
| "react-app", | ||
| "react-app/jest", | ||
| "plugin:react-hooks/recommended", | ||
| "plugin:react/jsx-runtime", | ||
| "prettier" | ||
| ], | ||
| "globals": { | ||
| "Atomics": "readonly", | ||
| "SharedArrayBuffer": "readonly" | ||
| }, | ||
| "settings": { | ||
@@ -31,14 +27,24 @@ "import/resolver": { | ||
| } | ||
| }, | ||
| "react": { | ||
| "version": "detect" | ||
| } | ||
| }, | ||
| "ignorePatterns": ["dist", ".eslintrc.cjs"], | ||
| "parser": "@typescript-eslint/parser", | ||
| "parserOptions": { | ||
| "ecmaVersion": 2020, | ||
| "sourceType": "module" | ||
| }, | ||
| "plugins": ["@typescript-eslint"], | ||
| "plugins": ["react-refresh"], | ||
| "rules": { | ||
| "node/no-missing-import": "off", | ||
| "@typescript-eslint/no-unused-vars": ["error", { "ignoreRestSiblings": true }], | ||
| "import/order": ["error", { "newlines-between": "always", "alphabetize": { "order": "asc" } }], | ||
| "react-refresh/only-export-components": "warn", | ||
| "react/react-in-jsx-scope": "off", | ||
| "@typescript-eslint/explicit-module-boundary-types": "off", | ||
| "eslint-comments/disable-enable-pair": ["error", { "allowWholeFile": true }], | ||
| "import/no-unresolved": ["error", {}], | ||
| "import/order": [ | ||
| "error", | ||
| { | ||
| "newlines-between": "always", | ||
| "alphabetize": { "order": "asc" }, | ||
| "warnOnUnassignedImports": true | ||
| } | ||
| ], | ||
| "sort-imports": [ | ||
@@ -45,0 +51,0 @@ "error", |
| import { SWRResponse } from 'swr'; | ||
| /** | ||
| * Describes the parameters required to create a custom fetch hook. | ||
| * Parameters required to create a custom fetch hook. | ||
| * | ||
| * @template FetcherArgs - The types of arguments accepted by the fetcher function. | ||
| * @template FetcherReturnType - The type of data returned from the fetcher function. | ||
| * @template TransformedType - The type of data returned from the transform function. | ||
| * @template FetcherArgs The types of arguments accepted by the fetcher function. | ||
| * @template FetcherReturnType The type of data returned from the fetcher function. | ||
| * @template TransformedType The type of data returned from the transform function. | ||
| */ | ||
@@ -15,5 +15,5 @@ type CreateFetchHookParams<FetcherArgs extends unknown[], FetcherReturnType, TransformedType> = { | ||
| /** | ||
| * The shape of the response from the custom hook. | ||
| * Return type of createFetchHook. | ||
| */ | ||
| type HookResponse<T> = { | ||
| type FetchHook<T> = { | ||
| data: T | undefined; | ||
@@ -24,9 +24,9 @@ } & Omit<SWRResponse, 'data'>; | ||
| * | ||
| * @param fetcher - The function used to fetch data. | ||
| * @param swrKey - The caching key used by SWR. | ||
| * @param transform - An optional function to transform or enrich the fetched data. | ||
| * @param fetcher The function used to fetch data. | ||
| * @param swrKey The caching key used by SWR. | ||
| * @param transform An optional function to transform or enrich the fetched data. | ||
| * @returns HookResponse A custom hook tailored to the given configuration. | ||
| */ | ||
| declare const createFetchHook: <FetcherArgs extends unknown[], FetcherReturnType, TransformedType = FetcherReturnType>({ fetcher, swrKey, transform, }: CreateFetchHookParams<FetcherArgs, FetcherReturnType, TransformedType>) => (...args: FetcherArgs) => HookResponse<TransformedType>; | ||
| declare const createFetchHook: <FetcherArgs extends unknown[], FetcherReturnType, TransformedType = FetcherReturnType>({ fetcher, swrKey, transform, }: CreateFetchHookParams<FetcherArgs, FetcherReturnType, TransformedType>) => (...args: FetcherArgs) => FetchHook<TransformedType>; | ||
| export default createFetchHook; | ||
| //# sourceMappingURL=createFetchHook.d.ts.map |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"createFetchHook.d.ts","sourceRoot":"","sources":["../../src/hooks/createFetchHook.ts"],"names":[],"mappings":"AAAA,OAAe,EAAE,WAAW,EAAE,MAAM,KAAK,CAAC;AAE1C;;;;;;GAMG;AACH,KAAK,qBAAqB,CACxB,WAAW,SAAS,OAAO,EAAE,EAC7B,iBAAiB,EACjB,eAAe,IACb;IACF,OAAO,EAAE,CAAC,GAAG,IAAI,EAAE,WAAW,KAAK,OAAO,CAAC,iBAAiB,CAAC,CAAC;IAC9D,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,iBAAiB,KAAK,eAAe,CAAC;CAC3D,CAAC;AAEF;;GAEG;AACH,KAAK,YAAY,CAAC,CAAC,IAAI;IACrB,IAAI,EAAE,CAAC,GAAG,SAAS,CAAC;CACrB,GAAG,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;AAE9B;;;;;;;GAOG;AACH,QAAA,MAAM,eAAe,6PAelB,CAAC;AAEJ,eAAe,eAAe,CAAC"} | ||
| {"version":3,"file":"createFetchHook.d.ts","sourceRoot":"","sources":["../../src/hooks/createFetchHook.ts"],"names":[],"mappings":"AAAA,OAAe,EAAE,WAAW,EAAE,MAAM,KAAK,CAAC;AAE1C;;;;;;GAMG;AACH,KAAK,qBAAqB,CAAC,WAAW,SAAS,OAAO,EAAE,EAAE,iBAAiB,EAAE,eAAe,IAAI;IAC9F,OAAO,EAAE,CAAC,GAAG,IAAI,EAAE,WAAW,KAAK,OAAO,CAAC,iBAAiB,CAAC,CAAC;IAC9D,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,iBAAiB,KAAK,eAAe,CAAC;CAC3D,CAAC;AAEF;;GAEG;AACH,KAAK,SAAS,CAAC,CAAC,IAAI;IAClB,IAAI,EAAE,CAAC,GAAG,SAAS,CAAC;CACrB,GAAG,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;AAE9B;;;;;;;GAOG;AACH,QAAA,MAAM,eAAe,0PAelB,CAAC;AAEJ,eAAe,eAAe,CAAC"} |
@@ -5,5 +5,5 @@ import useSWR from 'swr'; | ||
| * | ||
| * @param fetcher - The function used to fetch data. | ||
| * @param swrKey - The caching key used by SWR. | ||
| * @param transform - An optional function to transform or enrich the fetched data. | ||
| * @param fetcher The function used to fetch data. | ||
| * @param swrKey The caching key used by SWR. | ||
| * @param transform An optional function to transform or enrich the fetched data. | ||
| * @returns HookResponse A custom hook tailored to the given configuration. | ||
@@ -10,0 +10,0 @@ */ |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"createFetchHook.js","sourceRoot":"","sources":["../../src/hooks/createFetchHook.ts"],"names":[],"mappings":"AAAA,OAAO,MAAuB,MAAM,KAAK,CAAC;AA0B1C;;;;;;;GAOG;AACH,MAAM,eAAe,GACnB,CAAwF,EACtF,OAAO,EACP,MAAM,EACN,SAAS,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC,IAAuB,GAC0B,EAAE,EAAE,CAC7E,CAAC,GAAG,IAAiB,EAAiC,EAAE;IACtD,MAAM,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,MAAM,CAAC,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC,EAAE,WAAW,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC;IAE/F,MAAM,eAAe,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IAExC,OAAO;QACL,GAAG,IAAI;QACP,IAAI,EAAE,eAAe;KACtB,CAAC;AACJ,CAAC,CAAC;AAEJ,eAAe,eAAe,CAAC"} | ||
| {"version":3,"file":"createFetchHook.js","sourceRoot":"","sources":["../../src/hooks/createFetchHook.ts"],"names":[],"mappings":"AAAA,OAAO,MAAuB,MAAM,KAAK,CAAC;AAsB1C;;;;;;;GAOG;AACH,MAAM,eAAe,GACnB,CAAwF,EACtF,OAAO,EACP,MAAM,EACN,SAAS,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC,IAAuB,GAC0B,EAAE,EAAE,CAC7E,CAAC,GAAG,IAAiB,EAA8B,EAAE;IACnD,MAAM,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,MAAM,CAAC,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC,EAAE,WAAW,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC;IAE/F,MAAM,eAAe,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IAExC,OAAO;QACL,GAAG,IAAI;QACP,IAAI,EAAE,eAAe;KACtB,CAAC;AACJ,CAAC,CAAC;AAEJ,eAAe,eAAe,CAAC"} |
+11
-4
| { | ||
| "name": "@slangy/react", | ||
| "version": "2.1.0", | ||
| "version": "2.2.0", | ||
| "author": { | ||
@@ -33,7 +33,8 @@ "name": "Dani Lupión", | ||
| "react": "^18.2.0", | ||
| "swr": "^2.2.4" | ||
| "swr": "^2.2.4", | ||
| "zustand": "^4.4.3" | ||
| }, | ||
| "devDependencies": { | ||
| "@types/jest": "^29.5.5", | ||
| "@types/node": "^20.8.2", | ||
| "@types/node": "^20.8.5", | ||
| "@types/react": "^18.2.28", | ||
@@ -44,2 +45,3 @@ "@typescript-eslint/eslint-plugin": "^6.7.5", | ||
| "eslint-config-prettier": "^9.0.0", | ||
| "eslint-config-react-app": "^7.0.1", | ||
| "eslint-import-resolver-typescript": "^3.6.1", | ||
@@ -49,2 +51,5 @@ "eslint-plugin-eslint-comments": "^3.2.0", | ||
| "eslint-plugin-jest": "^27.4.2", | ||
| "eslint-plugin-react": "^7.33.2", | ||
| "eslint-plugin-react-hooks": "^4.6.0", | ||
| "eslint-plugin-react-refresh": "^0.4.3", | ||
| "jest": "^29.7.0", | ||
@@ -54,4 +59,6 @@ "lint-staged": "^14.0.1", | ||
| "prettier": "^3.0.3", | ||
| "react": "^18.2.0", | ||
| "swr": "^2.2.4", | ||
| "typescript": "^5.2.2" | ||
| "typescript": "^5.2.2", | ||
| "zustand": "^4.4.3" | ||
| }, | ||
@@ -58,0 +65,0 @@ "lint-staged": { |
| import useSWR, { SWRResponse } from 'swr'; | ||
| /** | ||
| * Describes the parameters required to create a custom fetch hook. | ||
| * Parameters required to create a custom fetch hook. | ||
| * | ||
| * @template FetcherArgs - The types of arguments accepted by the fetcher function. | ||
| * @template FetcherReturnType - The type of data returned from the fetcher function. | ||
| * @template TransformedType - The type of data returned from the transform function. | ||
| * @template FetcherArgs The types of arguments accepted by the fetcher function. | ||
| * @template FetcherReturnType The type of data returned from the fetcher function. | ||
| * @template TransformedType The type of data returned from the transform function. | ||
| */ | ||
| type CreateFetchHookParams< | ||
| FetcherArgs extends unknown[], | ||
| FetcherReturnType, | ||
| TransformedType, // This is a new type for the transformed data | ||
| > = { | ||
| type CreateFetchHookParams<FetcherArgs extends unknown[], FetcherReturnType, TransformedType> = { | ||
| fetcher: (...args: FetcherArgs) => Promise<FetcherReturnType>; | ||
@@ -21,5 +17,5 @@ swrKey: string; | ||
| /** | ||
| * The shape of the response from the custom hook. | ||
| * Return type of createFetchHook. | ||
| */ | ||
| type HookResponse<T> = { | ||
| type FetchHook<T> = { | ||
| data: T | undefined; | ||
@@ -31,5 +27,5 @@ } & Omit<SWRResponse, 'data'>; | ||
| * | ||
| * @param fetcher - The function used to fetch data. | ||
| * @param swrKey - The caching key used by SWR. | ||
| * @param transform - An optional function to transform or enrich the fetched data. | ||
| * @param fetcher The function used to fetch data. | ||
| * @param swrKey The caching key used by SWR. | ||
| * @param transform An optional function to transform or enrich the fetched data. | ||
| * @returns HookResponse A custom hook tailored to the given configuration. | ||
@@ -43,3 +39,3 @@ */ | ||
| }: CreateFetchHookParams<FetcherArgs, FetcherReturnType, TransformedType>) => | ||
| (...args: FetcherArgs): HookResponse<TransformedType> => { | ||
| (...args: FetcherArgs): FetchHook<TransformedType> => { | ||
| const { data, ...rest } = useSWR([swrKey, args], ([, fetcherArgs]) => fetcher(...fetcherArgs)); | ||
@@ -46,0 +42,0 @@ |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
38621
96.42%19
111.11%611
146.37%3
50%23
35.29%1
Infinity%