Security News
PyPI’s New Archival Feature Closes a Major Security Gap
PyPI now allows maintainers to archive projects, improving security and helping users make informed decisions about their dependencies.
@dwarvesf/redux-bundler-async-resources
Advanced tools
redux-bundler bundle that manages a collection of async resources
A bundle factory for redux-bundler that clearly manages remote resources.
It is questionable that createAsyncResourceBundle
should be a native part of redux-bundler in the first place. Either way, it's missing some features that are usually needed and usually re-implemented as extensions.
This package:
createAsyncResourceBundle
with a bit clearer semantics and few additional missing featurescreateAsyncResourcesBundle
(note plural form). Instead of a single resource instance, it manages a collection of async resource instances referenced by ID. Each managed instance has it's own lifecycle in terms of loading, expiration etc.npm install --save redux-bundler-async-resources
If you use React, take a look at redux-bundler-async-resources-hooks
import { createSelector } from 'redux-bundler'
import { createAsyncResourceBundle } from 'redux-bundler-async-resources'
export default {
...createAsyncResourceBundle({
name: 'hotCarDeals',
staleAfter: 180000, // refresh every 3 minutes
expireAfter: 60 * 60000, // delete if not refreshed in an hour
getPromise: ({ shopApi }) => shopApi.fetchHotCarDeals(),
}),
reactShouldFetchHotCarDeals: createSelector(
'selectHotCarDealsIsPendingForFetch',
shouldFetch => {
if (shouldFetch) {
return { actionCreator: 'doFetchHotCarDeals' }
}
}
),
}
import React from 'react'
import { useConnect } from 'redux-bundler-hook'
// ... other imports
export default function HotCarDeals() {
const { hotCarDeals, hotCarDealsError } = useConnect('selectHotCarDeals', 'selectHotCarDealsError')
if (!hotCarDeals && hotCarDealsError) {
return <ErrorMessage error={hotCarDealsError} />
}
if (!hotCarDeals) {
return <Spinner />
}
return <CarDealsList deals={hotCarDeals} />
}
select${Name}IsPendingForFetch
for a failed request will turn back on. Falsie value or Infinity
will disable retries.select${Name}IsPendingForFetch
back on). Falsie value or Infinity
will disable staling mechanism.Infinity
): similar to staleAfter
but will hard-remove the item from the store, resetting it to pristine state. Useful with caching to to prevent app user to see really old data when re-opening the page.cacheBundle
to cache on meaningful updates.userId
will listen to selector selectUserId
null
or undefined
, it will prevent resource from fetchinggetPromise
parameterscurrentUserId
or ['myResourceListPage', 'myResourceListPageSize']'
{ key: 'userId', staleOnChange: true '}
):
true
, will stale a resource when dependency changes, rather than clearing the storetrue
, will not lock resource from fetching when resolved value is null
or undefined
select${Name}Raw
– just get raw bundle state, to be used internallyselect${Name}
– returns item data or undefined
if there's nothing thereselect${Name}IsPresent
– returns true
if there is something to be returned by select${Name}
(i.e. there was at least one successful load before)select${Name}IsLoading
– returns true
if item is currently loading (irrelevant of whether there is some data or not in select${Name}
)select${Name}IsPendingForFetch
– returns true
if resource thinks it should load now (i.e. pristine or stale or there was an error and retryAfter
has passed or dependencies were specified and changed)select${Name}Error
– returns whatever gerPromise
rejected with previously; reset to null
or new error value after next load is finishedselect${Name}IsReadyForRetry
– returns true
if previous fetch resulted in error and retryAfter
has passedselect${Name}RetryAt
– returns null
or a timestamp at which item fetch will be retriedselect${Name}ErrorIsPermanent
– returns true
if previous fetch resulted in error and error object had permanent
field onselect${Name}IsStale
– returns true
if item is stale (manually or respective interval has passed)doFetch${Name}
– trigger a fetchdoClear${Name}
– force-clear a bundle and reset it to pristine statedoMark${Name}AsStale
– force-mark resource as outdated. Will not remove item from the bundle, but will turn "refetch me!" flag on.doAdjust${Name}(payload)
– if there is some data present, replace item data with specified payload
. If payload
is a function, call it a with single parameter (current data value), and replace data with that it returns. Primary use case is when you have some mutation API calls to your resource that always render a predictable change of your resource properties – so you want to save up on re-fetching it and just update in place.... some other selectors and action creators are present, though mostly technical and are needed for bundle functioning
import { composeBundles, createSelector } from 'redux-bundler'
import { createAsyncResourcesBundle } from 'redux-bundler-async-resources'
export default composeBundles(
createAsyncResourcesBundle({
name: 'carReviews',
staleAfter: 60000, // refresh every a minute
expireAfter: 60 * 60000, // delete if not refreshed in an hour
getPromise: (carId, { shopApi }) => shopApi.fetchCarReviews(carId),
}),
{
name: 'currentCarReviews',
reducer: (state = null, action) => {
if (action.type === 'currentCarReviews.CHANGED') {
return action.payload
}
return state
},
selectCurrentCarReviewsRaw: state => state.currentCarReviews,
selectCurrentCarReviews: createSelector(
'selectCurrentCarReviewsRaw',
reviewsItem => asyncResources.getItemData(reviewsItem)
),
selectCurrentCarReviewsError: createSelector(
'selectCurrentCarReviewsRaw',
reviewsItem => asyncResources.getItemError(reviewsItem)
),
selectCurrentCarReviewsLoading: createSelector(
'selectCurrentCarReviewsRaw',
reviewsItem => asyncResources.itemIsLoading(reviewsItem)
),
reactCurrentCarReviewsChanged: createSelector(
'selectCurrentCarReviewsRaw',
'selectCurrentCarId',
'selectItemsOfCarReviews',
(prevReviewsItem, carId, carReviews) => {
const reviewsItem = carReviews[carId]
if (prevReviewsItem !== reviewsItem) {
return { type: 'currentCarReviews.CHANGED', payload: reviewsItem }
}
}
),
reactShouldFetchCurrentCarReviews: createSelector(
'selectCurrentCarId',
'selectItemsOfCarReviews',
'selectIsOnline',
(carId, carReviews, isOnline) => {
if (carId && asyncResources.itemIsPendingForFetch(carReviews[carId], { isOnline })) {
return { actionCreator: 'doFetchItemOfCarReviews', args: [carId] }
}
}
),
}
// ... other bundles of your application
)
import React from 'react'
import { useConnect } from 'redux-bundler-hook'
import { asyncResources } from 'redux-bundler-async-resources'
// ... other imports
export default function CurrentCarReviews() {
const { currentCarReviews, currentCarReviewsError, currentCarReviewsLoading } = useConnect(
'selectCurrentCarReviews',
'selectCurrentCarReviewsError',
'selectCurrentCarReviewsLoading'
)
if (currentCarReviewsLoading) {
return <Spinner />
}
if (currentCarReviewsError) {
return <ErrorMessage error={currentCarReviewsError} />
}
return <ReviewList reviews={currentCarReviews} />
}
asyncResources.getItemData(itemId)
or asyncResources.getItemError(itemId)
asyncResources.itemIsPendingForFetch
for an item that has failed to fetch will turn back on. Falsie value or Infinity
will disable retries.asyncResources.itemIsPendingForFetch
back on). Falsie value or Infinity
will disable staling mechanism.Infinity
): similar to staleAfter
but will hard-remove the item from the store. Useful with caching to to prevent app user to see really old data when re-opening the page.createAsyncResource
– will instruct cacheBundle
to cache on meaningful updates.select${Name}Raw
– as usual, just get raw bundle stateselectItemsOf${Name}
– returns a hash of { [itemId]: item }
; item
to be used with asyncResources
helpers to get meaningful information from it.doFetchItemOf${Name}(itemId)
– trigger a fetch of a specific itemdoClearItemOf${Name}(itemId)
– force-remove a certain item from the bundle, resetting it to pristine statedoMarkItemOf${Name}AsStale(itemId)
– force-mark certain item as outdated. Will not remove item from the bundle, but will turn "refetch me!" flag on.doAdjustItemOf${Name}(itemId, payload)
– if there is some data present, replace item data with specified payload
. If payload
is a function, call it a with single parameter (current data value), and replace data with that it returns. Primary use case is when you have some mutation API calls to your resource that always render a predictable change of your resource properties – so you want to save up on re-fetching it and just update in place.asyncResources
helpersgetItemData(item)
– will return anything that getPromise
previously resolved with or undefined
if it didn't happen beforeitemIsPresent(item)
– true
if getItemData
is currently able to return some data to showitemIsLoading(item)
– true
if item is currently loading (irrelevant of whether it has some data or not, i.e. of itemIsPresent
/ getItemData
result)itemIsPendingForFetch(item, [{ isOnline = undefined }])
– true
if there are any of mentioned conditions are present that result in necessity to trigger doFetchItemOf${Name}
:
retryAfter
has passed (and error is not permanent)staleAfter
has passed)isOnline
is an optional check to not even try loading anything if device is offline; may omit if online check is not neededgetItemError(item)
– something that getPromise
previously rejected with. Will reset on when next fetch will finish (or fail).itemIsReadyForRetry(item)
– true
if this item contains an error, and retryAfter
has passed.itemRetryAt(item)
– returns a timestamp at which item fetch will be retried (if it will be, otherwise null
)itemErrorIsPermanent(item)
– true
if getPromise
has rejected with something that had persistent: true
property in it. Retry behavior will be disabled in this case.itemIsStale(item)
– true
if this item is stale (manually or because staleAfter
has passed since last successful fetch)In (rare) cases when you need to async resources in a resource-agnostic manner, there are two helpers available: makeAsyncResourceBundleKeys
and makeAsyncResourcesBundleKeys
for it's multi-item counterpart.
Calling this with a resource name
will return you an object of the following shape (assuming resource name "myResource"
):
(similar to)
{
"selectors": {
"raw": "selectMyResourceRaw",
"data": "selectMyResource",
"isLoading": "selectMyResourceIsLoading",
"isPresent": "selectMyResourceIsPresent",
"error": "selectMyResourceError",
"isReadyForRetry": "selectMyResourceIsReadyForRetry",
"errorIsPermanent": "selectMyResourceErrorIsPermanent",
"isStale": "selectMyResourceIsStale",
"isPendingForFetch": "selectMyResourceIsPendingForFetch"
},
"keys": {
"raw": "myResourceRaw",
"data": "myResource",
"isLoading": "myResourceIsLoading",
"isPresent": "myResourceIsPresent",
"error": "myResourceError",
"isReadyForRetry": "myResourceIsReadyForRetry",
"errorIsPermanent": "myResourceErrorIsPermanent",
"isStale": "myResourceIsStale",
"isPendingForFetch": "myResourceIsPendingForFetch"
},
"actionCreators": {
"doFetch": "doFetchMyResource",
"doClear": "doClearMyResource",
"doMarkAsStale": "doMarkMyResourceAsStale",
"doAdjust": "doAdjustMyResource"
},
"reactors": {
"shouldExpire": "reactMyResourceShouldExpire",
"shouldRetry": "reactMyResourceShouldRetry",
"shouldBecomeStale": "reactMyResourceShouldBecomeStale"
}
}
... and for makeAsyncResourcesBundleKeys
it will be similar to:
{
"selectors": {
"raw": "selectMyResourcesRaw",
"items": "selectItemsOfMyResources",
"nextExpiringItem": "selectNextExpiringItemOfMyResources",
"nextRetryingItem": "selectNextRetryingItemOfMyResources",
"nextStaleItem": "selectNextStaleItemOfMyResources"
},
"keys": {
"raw": "myResourcesRaw",
"items": "itemsOfMyResources",
"nextExpiringItem": "nextExpiringItemOfMyResources",
"nextRetryingItem": "nextRetryingItemOfMyResources",
"nextStaleItem": "nextStaleItemOfMyResources"
},
"actionCreators": {
"doFetch": "doFetchItemOfMyResources",
"doClear": "doClearItemOfMyResources",
"doMarkAsStale": "doMarkItemOfMyResourcesAsStale",
"doAdjust": "doAdjustItemOfMyResources"
},
"reactors": {
"shouldExpire": "reactItemOfMyResourcesShouldExpire",
"shouldRetry": "reactItemOfMyResourcesShouldRetry",
"shouldBecomeStale": "reactItemOfMyResourcesShouldBecomeStale"
}
}
FAQs
redux-bundler bundle that manages a collection of async resources
We found that @dwarvesf/redux-bundler-async-resources demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 2 open source maintainers 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
PyPI now allows maintainers to archive projects, improving security and helping users make informed decisions about their dependencies.
Research
Security News
Malicious npm package postcss-optimizer delivers BeaverTail malware, targeting developer systems; similarities to past campaigns suggest a North Korean connection.
Security News
CISA's KEV data is now on GitHub, offering easier access, API integration, commit history tracking, and automated updates for security teams and researchers.