react-smart-state
Version:
Next generation local and global state management
172 lines (171 loc) • 5.6 kB
JavaScript
import { useRef, useState, useEffect } from "react";
import { CustomError } from "./objects";
export const reactEffect = useEffect;
export const reactRef = useRef;
export const reactState = useState;
export function updater() {
const [value, setValue] = reactState(0);
return ({
value,
refresh: () => {
setValue(prev => (prev < 1000 ? prev + 1 : 1));
}
});
}
export function SmartStateError(err, extraInfo) {
const message = err instanceof Error ? err.message : typeof err === 'string' ? err : 'Unknown error';
const item = new CustomError(message, {
originalError: err,
code: extraInfo === null || extraInfo === void 0 ? void 0 : extraInfo.code,
details: extraInfo === null || extraInfo === void 0 ? void 0 : extraInfo.details,
});
console.error(item);
return item;
}
export const clone = (o) => {
var _a, _b;
if (!valid(o, true))
return o;
let item = o;
if (((_a = item.getInstanceType) === null || _a === void 0 ? void 0 : _a.call(item)) === "react-smart-state-item")
return Object.assign({}, item);
if (((_b = item.getInstanceType) === null || _b === void 0 ? void 0 : _b.call(item)) === "react-smart-state-array")
return [...o];
return o;
};
export const isSame = (a, b) => {
if (valid(a, true) && valid(b, true)) {
return a === b;
}
return false;
};
let ids = new Map();
let lastDate = new Date();
export const newId = (inc) => {
if ((Date.now() - lastDate.getTime()) > 60 * 1000) {
ids = new Map();
lastDate = new Date();
}
let id = (inc !== null && inc !== void 0 ? inc : "") + Date.now().toString(36) + Math.floor(1e12 + Math.random() * 9e12).toString(36);
if (ids.has(id)) {
// Retry without prefix to avoid exponential growth
return newId();
}
if (ids.size >= 1000)
ids.clear();
ids.set(id, id);
return id;
};
export function isPromise(obj) {
return !!obj && typeof obj.then === 'function';
}
export const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));
export function getItem(item) {
if (!item)
throw "item cannot be undefined or null";
if (typeof item === "function")
return getItem(item());
return item;
}
export function refCondition(fn) {
const ref = reactRef(undefined);
if (ref.current == undefined)
ref.current = fn();
return { value: ref.current, setValue: (value) => ref.current = value };
}
export const toObject = (nested = false, ...keys) => {
if (keys.length === 0)
return { AllKeys: true, _keys: keys };
let item = keys.reduce((c, v) => {
c[v] = true;
if (nested) {
let parts = v.split(".");
if (parts.length > 1) {
let fullKey = "";
for (let p of parts) {
fullKey += p + ".";
c[fullKey] = true;
}
}
}
return c;
}, { _keys: keys });
return item;
};
export function getPrototypeChain(obj) {
let prototypeChain = [];
(function innerRecursiveFunction(obj) {
let currentPrototype = obj != null ? Object.getPrototypeOf(obj) : null;
prototypeChain.push(currentPrototype);
if (currentPrototype != null) {
innerRecursiveFunction(currentPrototype);
}
})(obj);
return prototypeChain.filter(x => x !== null);
}
export const keys = (item, prototype) => {
let prototypes = getPrototypeChain(item);
let ks = [
...Object.keys(item),
...prototypes.flatMap(x => Object.getOwnPropertyNames(x))
];
let obp = Object.getOwnPropertyNames(Object.prototype);
let cbp = Object.getOwnPropertyNames(prototype);
ks = ks
.filter(x => !obp.includes(x) && !cbp.includes(x))
.filter((value, index, array) => array.indexOf(value) === index);
// alert(JSON.stringify(ks, undefined, 4));
return ks;
};
export const getValueByPath = (value, path) => {
if (!path)
return value;
const segments = path.split(".");
let current = value;
for (const key of segments) {
if (current == null || current == undefined)
return undefined; // handles null and undefined
current = current[key];
}
return current;
};
export const isArray = (item) => {
var _a, _b;
if (item == undefined || item === null)
return false;
if (Array.isArray(item) || ((_b = (_a = item).getInstanceType) === null || _b === void 0 ? void 0 : _b.call(_a)) === "react-smart-state-array")
return true;
return false;
};
export const valid = (item, validArray) => {
if (item === undefined || item === null)
return false;
if (typeof item === "string")
return false;
if (typeof item === "function")
return false;
if (item instanceof Set)
return false;
if (item instanceof Map)
return false;
if (item instanceof WeakSet)
return false;
if (item instanceof WeakMap)
return false;
if (item instanceof Date)
return false;
if (item instanceof RegExp)
return false;
if (item instanceof ArrayBuffer)
return false;
if (ArrayBuffer.isView(item))
return false; // covers Uint8Array, Float32Array, etc.
if (item instanceof Promise)
return false;
if (isArray(item) && item.length > 0) {
if (validArray)
return valid(item[0], validArray);
return false;
}
return typeof item === "object";
};