Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

wappsto-blanket

Package Overview
Dependencies
Maintainers
1
Versions
57
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

wappsto-blanket - npm Package Compare versions

Comparing version 1.0.0 to 1.1.0

hooks/useAlwaysSubscribe.js

31

hooks/index.js

@@ -0,13 +1,20 @@

export { default as useEntitySelector } from './useAlwaysSubscribe';
export { default as useEntitySelector } from './useEntitiesSelector';
export { default as useEntitySelector } from './useEntitySelector';
export { default as useIds } from './useIds';
export { default as useList } from './useList';
export { default as useLogs } from './useLogs';
export { default as useMetrics } from './useMetrics';
export { default as usePrevious } from './usePrevious';
export { default as useRefresh } from './useRefresh';
export { default as useRefreshTimestamp } from './useRefreshTimestamp';
export { default as useRequest } from './useRequest';
export { default as useSubscribe } from './useSubscribe';
export { default as useVisible } from './useVisible';
export { default as useFetchItems } from './useFetchItems';
export { default as usePagination } from './usePagination';
export { default as useEntitySelector } from './useFetchItems';
export { default as useEntitySelector } from './useIds';
export { default as useEntitySelector } from './useItemSelector';
export { default as useEntitySelector } from './useList';
export { default as useEntitySelector } from './useLogs';
export { default as useEntitySelector } from './useMetrics';
export { default as useEntitySelector } from './useMountedRef';
export { default as useEntitySelector } from './usePagination';
export { default as useEntitySelector } from './usePathSubscribe';
export { default as useEntitySelector } from './usePrevious';
export { default as useEntitySelector } from './useRefresh';
export { default as useEntitySelector } from './useRefreshTimestamp';
export { default as useEntitySelector } from './useRequest';
export { default as useEntitySelector } from './useStoreItem';
export { default as useEntitySelector } from './useStorePagination';
export { default as useEntitySelector } from './useSubscribe';
export { default as useEntitySelector } from './useVisible';

@@ -1,11 +0,12 @@

import { useState, useEffect } from 'react';
import { useState, useEffect, useMemo } from 'react';
import { useStore } from 'react-redux';
import { findRequest, startRequest } from 'wappsto-redux/actions/request';
import { startRequest } from 'wappsto-redux/actions/request';
import { addEntities } from 'wappsto-redux/actions/entities';
import { getSession } from 'wappsto-redux/selectors/session';
import { ITEMS_PER_SLICE } from '../util';
import querystring from 'query-string';
const ITEMS_PER_SLICE = 100;
const CHILDREN = { 'network': 'device', 'device': 'value', 'value': 'state' }
const fetch = async (ids, type, store, lvl = 0) => {
const fetch = async (ids, type, store, query, lvl = 0, useCache) => {
const state = store.getState();

@@ -15,3 +16,3 @@ const uniqIds = [...new Set(ids)];

let missingIds;
if (state.entities[type+'s']) {
if (useCache && state.entities[type+'s']) {
missingIds = uniqIds.filter(id => !state.entities[type+'s'][id]);

@@ -30,12 +31,6 @@ } else {

const promises = slices.map((e) => {
const url = `/${type}?expand=0&id=[${e.join(',')}]&from_last=true`;
const existingRequest = findRequest(state, url, 'GET');
if (existingRequest) {
const promise = state.request[existingRequest].promise;
return promise;
} else {
const session = getSession(state);
const { promise } = startRequest(store.dispatch, url, 'GET', null, {}, session);
return promise;
}
const url = `/${type}?expand=0&id=[${e.join(',')}]&${querystring.stringify(query)}`;
const session = getSession(state);
const promise = startRequest(store.dispatch, { url, method: 'GET' }, session);
return promise;
});

@@ -56,10 +51,10 @@

const cachedResults = state.entities[type+'s'];
if (cachedResults) {
if (useCache && cachedResults) {
const cachedIds = uniqIds.filter(id => state.entities[type+'s'][id]);
cachedIds.forEach((e) => {
const item = cachedResults[e];
if (item) {
itemList = [...itemList, item];
if (item && !itemList.find(i => i.meta.id === e)) {
itemList.push(item);
}
})
});
}

@@ -69,3 +64,3 @@

const itemListIds = itemList.reduce((arr, e) => [...arr, ...(e[CHILDREN[type]] || [])], []);
const result = await fetch(itemListIds, CHILDREN[type], store, lvl-1);
const result = await fetch(itemListIds, CHILDREN[type], store, query, lvl-1, useCache);
return { [type]: itemList, ...result };

@@ -77,5 +72,19 @@ } else {

const useFetchItems = (objIds, expand) => {
const useFetchItems = (objIds, query, useCache=true) => {
const store = useStore();
const [[status, items], setState] = useState(['pending', {}]);
const [queryClone, lvl] = useMemo(() => {
if(query && query.constructor === Object){
const queryClone = {...query};
const lvl = queryClone.expand;
if(queryClone.hasOwnProperty('expand')){
delete queryClone.expand;
}
if(!queryClone.hasOwnProperty('from_last')){
queryClone.from_last = true;
}
return [queryClone, lvl];
}
return [null, query];
}, [query]);

@@ -93,7 +102,7 @@ useEffect(() => {

if (CHILDREN[type] || type === 'state') {
const response = await fetch(ids, type, store, expand);
const response = await fetch(ids, type, store, queryClone, lvl, useCache);
items[type] = response;
} else {
const response = await fetch(ids, type, store, 0);
items = response[type];
const response = await fetch(ids, type, store, queryClone, 0, useCache);
Object.assign(items, response);
}

@@ -114,3 +123,3 @@ }

// eslint-disable-next-line react-hooks/exhaustive-deps
}, [objIds, expand]);
}, [objIds, query]);

@@ -117,0 +126,0 @@ return { status, items };

@@ -1,3 +0,3 @@

import { useState, useEffect, useRef, useCallback, useMemo } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { useState, useRef, useCallback, useMemo } from 'react';
import { useSelector, useDispatch, useStore } from 'react-redux';

@@ -7,5 +7,7 @@ import { setItem } from 'wappsto-redux/actions/items';

import { makeItemSelector } from 'wappsto-redux/selectors/items';
import { getSession } from 'wappsto-redux/selectors/session';
import { startRequest } from 'wappsto-redux/actions/request';
import usePrevious from '../hooks/usePrevious';
import useRequest from '../hooks/useRequest';
import { matchArray, matchObject } from '../util';
import { ITEMS_PER_SLICE } from '../util';
import equal from 'deep-equal';

@@ -20,3 +22,30 @@ const itemName = 'useIds_status';

function useIds(service, ids, query){
const sendGetIds = (store, ids, service, query, sliceLength) => {
const res = [];
const slices = Math.ceil(ids.length / sliceLength);
for(let i = 0; i < slices; i++){
res.push(ids.slice(i * sliceLength, (i + 1) * sliceLength));
}
const state = store.getState();
const session = getSession(state);
res.forEach(arr => {
const options = {
url: '/' + service,
method: 'GET',
query: {
...query,
id: arr
}
}
const promise = startRequest(store.dispatch, options, session);
promise.then(result => {
setCacheStatus(store.dispatch, arr, result.ok ? 'success' : 'error', query);
}).catch(() => {
setCacheStatus(store.dispatch, arr, 'error', query);
});
});
}
function useIds(service, ids, query={}, sliceLength=ITEMS_PER_SLICE){
const store = useStore();
const [ status, setStatus ] = useState('idle');

@@ -30,7 +59,7 @@ const prevStatus = usePrevious(status);

const getItem = useMemo(makeItemSelector, []);
const cacheItems = useSelector(state => getEntities(state, service, { filter: ids.map(id => ({ meta: { id: id } }))}));
const cacheItems = useSelector(state => getEntities(state, service, ids));
const idsStatus = useSelector(state => getItem(state, itemName));
const updateMissingIds = useCallback(() => {
if(matchArray(ids, prevIds)){
if(equal(ids, prevIds)){
return;

@@ -45,3 +74,3 @@ }

const cQ = {...query, expand: null};
if(!matchObject(cidQ, cQ) || cid.query.expand < query.expand || cid.status === 'error' || cid.status === 'idle'){
if(!equal(cidQ, cQ) || cid.query.expand < query.expand || cid.status === 'error' || cid.status === 'idle'){
arr.push(id);

@@ -69,36 +98,15 @@ }

const { request, send, removeRequest } = useRequest();
const getMissingIds = (checkIds = true) => {
if(checkIds && matchArray(ids, prevIds)){
if(checkIds && equal(ids, prevIds)){
return;
}
const prevMissingIds = updateMissingIds();
updateMissingIds();
if(missingIds.current.length > 0){
if(request && request.status === 'pending' && prevMissingIds.length > 0){
setCacheStatus(dispatch, prevMissingIds, '', query);
}
removeRequest();
setCacheStatus(dispatch, missingIds.current, 'pending', query);
send({
method: 'GET',
url: '/' + service,
query: {
...query,
id: missingIds.current
}
});
sendGetIds(store, missingIds.current, service, query, sliceLength);
}
}
// Update cache when request is over
useEffect(() => {
if(request){
setCacheStatus(dispatch, missingIds.current, request.status, query);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [request]);
// Make request to get the ids
useEffect(() => {
useMemo(() => {
getMissingIds();

@@ -109,3 +117,3 @@ // eslint-disable-next-line react-hooks/exhaustive-deps

// Update status
useEffect(() => {
useMemo(() => {
if(status !== 'success' || prevIds !== ids){

@@ -130,3 +138,3 @@ for(let i = 0; i < ids.length; i++){

useEffect(() => {
useMemo(() => {
if(status === 'success'){

@@ -133,0 +141,0 @@ setItems(cacheItems);

@@ -59,4 +59,4 @@ import { useState, useEffect, useCallback, useRef, useMemo } from 'react';

}
} else {
url = '/' + type;
} else if(type){
url = '/' + type;
if(id){

@@ -98,3 +98,3 @@ if(id.startsWith('?')){

const [ customRequest, setCustomRequest ] = useState({ status: 'pending', options: { query: props.query } });
const [ customRequest, setCustomRequest ] = useState({ status: propsData.url ? 'pending' : 'success', options: { query: props.query } });
const name = props.name || (propsData.url + JSON.stringify(propsData.query));

@@ -105,8 +105,5 @@ const idsItemName = name + '_ids';

const savedIds = useSelector(state => getSavedIdsItem(state, idsItemName)) || empty;
const cachedRequestId = requestIdCache[requestIdName];
const { request, requestId, setRequestId, send } = useRequest();
const { request, send } = useRequest(requestIdName, true);
if(cachedRequestId && requestId !== cachedRequestId){
setRequestId(cachedRequestId);
} if(!cachedRequestId && customRequest.status !== 'pending'){
if(propsData.url && !request && customRequest.status !== 'pending'){
setCustomRequest({ status: 'pending', options: { query: props.query } });

@@ -117,3 +114,3 @@ }

const options = { filter: savedIds, limit: savedIds.length };
const options = { ids: savedIds, limit: savedIds.length };

@@ -150,3 +147,3 @@ const getEntities = useMemo(makeEntitiesSelector, []);

setCustomRequest({ status: 'pending', options: options });
const crid = send({
send({
method: 'GET',

@@ -156,5 +153,4 @@ url: propsData.url,

});
requestIdCache[requestIdName] = crid;
}
}, [propsData.url, requestIdName, send]);
}, [propsData.url, send]);

@@ -174,7 +170,5 @@ const refresh = useCallback((reset) => {

useEffect(() => {
if(props.useCache === false || !cachedRequestId || (savedIds === empty && !request) || (request && request.status === 'error')){
if(props.useCache === false || !request || (savedIds === empty && !request) || (request && request.status === 'error')){
refresh(props.reset);
} else if(cachedRequestId !== requestId){
setRequestId(cachedRequestId);
}
}
// eslint-disable-next-line react-hooks/exhaustive-deps

@@ -192,3 +186,3 @@ }, [propsData.query, props.id, propsData.url, refresh, props.useCache]);

if(request.json.constructor === Array){
ids = [...(ids || []), ...request.json.map(item => item.constructor === Object ? ({ meta: { id: item.meta.id }}) : ({ meta: { id: item }}))];
ids = [...(ids || []), ...request.json.map(item => item.constructor === Object ? item.meta.id : item)];
} else if(request.json.meta.type === 'attributelist'){

@@ -252,19 +246,23 @@ ids = [propsData.id];

const addItem = useCallback((id, position = 'start') => {
const found = savedIds.find(obj => obj.meta.id === id);
const found = savedIds.find(existingId => existingId === id);
if(!found){
dispatch(setItem(idsItemName, (ids = []) => {
if(position === 'start'){
return [{ meta: { id }}, ...ids];
return [id, ...ids];
} else {
return [...ids, { meta: { id }}];
return [...ids, id];
}
}));
return true;
}
return false;
}, [dispatch, idsItemName, savedIds]);
const removeItem = useCallback((id) => {
const index = savedIds.findIndex(obj => obj.meta.id === id);
const index = savedIds.findIndex(existingId => existingId === id);
if(index !== -1){
dispatch(setItem(idsItemName, (ids = []) => [...ids.slice(0, index), ...ids.slice(index + 1)]));
return true;
}
return false;
}, [dispatch, idsItemName, savedIds]);

@@ -271,0 +269,0 @@

@@ -7,2 +7,3 @@ import { useState, useRef, useCallback, useEffect } from 'react';

import axios from 'axios';
import equal from 'deep-equal';

@@ -19,3 +20,5 @@ const CancelToken = axios.CancelToken;

function useLogs(stateId, sessionId){
const cache = {};
function useLogs(stateId, sessionId, cacheId){
const [ data, setData ] = useState([]);

@@ -43,2 +46,7 @@ const cachedData = useRef([]);

}
if(cacheId && cache[cacheId] && equal(cache[cacheId].options, options)){
setData(cache[cacheId].data);
setCurrentStatus(cache[cacheId].status);
return true;
}
if(cOptions.start.constructor === Date){

@@ -57,3 +65,3 @@ cOptions.start = cOptions.start.toISOString();

try{
while(more && !isCanceled.current && !unmounted.current){
while(more && !isCanceled.current && (cacheId || (!cacheId && !unmounted.current))){
if(cachedData.current.length > 0){

@@ -76,2 +84,9 @@ const last = cachedData.current[cachedData.current.length - 1];

}
if(cacheId){
cache[cacheId] = {
data: cachedData.current,
options: options,
status: STATUS.SUCCESS
};
}
if(unmounted.current){

@@ -85,2 +100,9 @@ return;

} catch(e){
if(cacheId){
cache[cacheId] = {
data: cachedData.current,
options: options,
status: STATUS.ERROR
};
}
if(unmounted.current){

@@ -114,6 +136,9 @@ return;

const reset = useCallback(() => {
const reset = useCallback((resetCache = true) => {
if(cancelFunc.current){
cancelFunc.current('Operation canceled');
}
if(cacheId && resetCache){
delete cache[cacheId];
}
setData([]);

@@ -123,3 +148,3 @@ setCurrentStatus(STATUS.IDLE);

cachedData.current = [];
}, []);
}, [cacheId]);

@@ -126,0 +151,0 @@ return { data, status, getLogs, reset, cancel };

import { useState, useEffect, useRef } from 'react';
import { useStore } from 'react-redux';
import useRequest from './useRequest';
import { findRequest, startRequest, STATUS } from 'wappsto-redux/actions/request';
import { startRequest, STATUS } from 'wappsto-redux/actions/request';
import { getSession } from 'wappsto-redux/selectors/session';

@@ -20,3 +20,7 @@

const v = query[k];
urlInstance.searchParams.set(k, v);
if(v !== null){
urlInstance.searchParams.set(k, v);
} else{
urlInstance.searchParams.delete(k);
}
}

@@ -46,12 +50,4 @@ urlInstance.searchParams.set('limit', pageSize);

const fireRequest = (state, url, store, session, requestsRef, key) => {
let id, promise;
id = findRequest(state, url, 'GET');
if(id){
promise = state.request[id].promise;
} else {
const req = startRequest(store.dispatch, url, 'GET', null, { reset: false }, session);
promise = req.promise;
id = req.id;
}
requestsRef.current[key] = { promise, id, status: STATUS.pending };
const promise = startRequest(store.dispatch, { url, method: 'GET' }, session);
requestsRef.current[key] = { promise, status: STATUS.pending };
return promise;

@@ -104,3 +100,3 @@ }

const usePagination = ({ url, query={}, page: pageNo=1, pageSize=MAX_PER_PAGE, useCache=true }) => {
const usePagination = ({ url, query, page: pageNo=1, pageSize=MAX_PER_PAGE, useCache=true }) => {
const store = useStore();

@@ -112,5 +108,6 @@ const [status, setStatus] = useState();

const mounted = useRef(true);
const skipPageChange = useRef(false);
const requestsRef = useRef({ items: null, count: null });
const start = (resetCache) => {
const start = (currentPage=page, resetCache) => {
requestsRef.current = { items: { status: STATUS.pending }, count: { status: STATUS.pending } };

@@ -121,3 +118,3 @@ mounted.current = true;

const promise1 = getPageCount({ store, url, requestsRef, resetCache, useCache });
const { promise: promise2, cacheUrl } = getItems({ store, url, query, pageSize, page, requestsRef, resetCache, useCache });
const { promise: promise2, cacheUrl } = getItems({ store, url, query, pageSize, page: currentPage, requestsRef, resetCache, useCache });

@@ -159,8 +156,12 @@ Promise.all([promise1, promise2]).then(([resCount, resItems]) => {

}
cache.pageRequests[cacheUrl].pages[page] = itemsRes;
if (page > 1 && !itemsRes.length) {
setPage(page-1);
cache.pageRequests[cacheUrl].pages[currentPage] = itemsRes;
if (currentPage > 1 && !itemsRes.length) {
setPage(1);
return;
}
if (mounted.current) {
if(currentPage !== page){
skipPageChange.current = true;
setPage(currentPage);
}
setCount(countRes.count);

@@ -180,3 +181,3 @@ setStatus(STATUS.success);

const refresh = () => {
start(true);
start(null, true);
}

@@ -209,7 +210,9 @@

}
Object.keys(pagesCache).forEach(pageNumber => {
if(pageNumber > currentPage){
pagesCache[pageNumber].invalid = true
}
});
if(currentPage * pageSize < cache.countRequests[url].count){
Object.keys(pagesCache).forEach(pageNumber => {
if(pageNumber > currentPage){
pagesCache[pageNumber].invalid = true
}
});
}
setCount(cache.countRequests[url].count);

@@ -237,7 +240,9 @@ const pageItems = cache.pageRequests[cacheUrl].pages[page];

Object.keys(pagesCache).forEach(pageNumber => {
if(pageNumber >= currentPage){
pagesCache[pageNumber].invalid = true;
}
});
if(currentPage * pageSize < cache.countRequests[url].count){
Object.keys(pagesCache).forEach(pageNumber => {
if(pageNumber >= currentPage){
pagesCache[pageNumber].invalid = true;
}
});
}
}

@@ -280,7 +285,16 @@

useEffect(() => {
if(skipPageChange.current){
skipPageChange.current = false;
return;
}
start();
return () => mounted.current = false;
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [url, page, store, pageSize]);
}, [page, store, pageSize]);
useEffect(() => {
start(1);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [url, query]);
return { items, count, page, setPage, refresh, status, requests: requestsRef.current, addItem, removeItem };

@@ -287,0 +301,0 @@ }

@@ -5,6 +5,9 @@ import { useMemo, useState, useCallback, useEffect } from 'react';

import { makeRequest, removeRequest as removeStoreRequest } from 'wappsto-redux/actions/request';
import uuidv4 from 'uuid/v4';
const useRequestSelector = (removeOldRequest=true) => {
const useRequest = (id, removeOldRequest) => {
const dispatch = useDispatch();
const [ requestId, setRequestId ] = useState();
const [ requestId, setRequestId ] = useState(() => {
return id || uuidv4();
});
const getRequest = useMemo(makeRequestSelector, []);

@@ -17,13 +20,11 @@ const request = useSelector(state => getRequest(state, requestId));

const send = useCallback((...args) => {
const newId = dispatch(makeRequest(...args));
setRequestId(newId);
return newId;
}, [dispatch]);
const send = useCallback((obj) => {
return dispatch(makeRequest({...obj, id: requestId}));
}, [dispatch, requestId]);
useEffect(() => () => {
if(removeOldRequest && requestId){
if((removeOldRequest && requestId) || (!id && removeOldRequest !== false)){
removeRequest();
}
}, [removeOldRequest, requestId, removeRequest]);
}, [removeOldRequest, requestId, removeRequest, id]);

@@ -33,2 +34,2 @@ return { request, requestId, setRequestId, send, removeRequest };

export default useRequestSelector;
export default useRequest;
{
"name": "wappsto-blanket",
"version": "1.0.0",
"version": "1.1.0",
"description": "",

@@ -17,3 +17,6 @@ "scripts": {

},
"homepage": "https://github.com/Wappsto/wappsto-blanket#readme"
"homepage": "https://github.com/Wappsto/wappsto-blanket#readme",
"dependencies": {
"uuid": "^8.3.1"
}
}

@@ -5,2 +5,4 @@ import { getServiceVersion } from 'wappsto-redux/util/helpers';

export const ITEMS_PER_SLICE = 100;
export function getLastKey(data){

@@ -7,0 +9,0 @@ if(!data){

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc