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

@rest-hooks/normalizr

Package Overview
Dependencies
Maintainers
2
Versions
126
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@rest-hooks/normalizr - npm Package Compare versions

Comparing version 10.0.3 to 10.1.0

legacy/denormalize/cache.js

398

dist/normalizr.amd.js
define(['exports'], (function (exports) { 'use strict';
class LocalCache {
constructor() {
this.localCache = {};
}
getEntity(pk, schema, entity, computeValue) {
const key = schema.key;
if (!(key in this.localCache)) {
this.localCache[key] = Object.create(null);
}
const localCacheKey = this.localCache[key];
let found = true;
let deleted = false;
if (!localCacheKey[pk]) {
[found, deleted] = computeValue(localCacheKey);
}
return [localCacheKey[pk], found, deleted];
}
getResults(input, cachable, computeValue) {
const ret = computeValue();
// this is faster than spread
// https://www.measurethat.net/Benchmarks/Show/23636/0/spread-with-tuples
return [ret[0], ret[1], ret[2], []];
}
}
function isEntity(schema) {

@@ -27,3 +52,3 @@ return schema !== null && schema.pk !== undefined;

};
const denormalize$2 = (schema, input, unvisit) => {
const denormalize$3 = (schema, input, unvisit) => {
schema = validateSchema(schema);

@@ -99,3 +124,3 @@ return [input.map ? input.map(entityOrId => unvisit(entityOrId, schema)).filter(filterEmpty).map(([value]) => value) : input, true, false];

};
const denormalize$1 = (schema, input, unvisit) => {
const denormalize$2 = (schema, input, unvisit) => {
if (isImmutable(input)) {

@@ -129,2 +154,103 @@ return denormalizeImmutable(schema, input, unvisit);

const unvisitEntity = (entityOrId, schema, unvisit, getEntity, cache) => {
const entity = typeof entityOrId === 'object' ? entityOrId : getEntity({
pk: entityOrId,
key: schema.key
});
if (typeof entity === 'symbol' && entity.toString().includes('DELETED')) {
return [undefined, true, true];
// TODO: Change to this as breaking change once we only support newer entities
// also remove `(entity as symbol).toString().includes('DELETED')` and do this for all symbols
// return schema.denormalize(entity, unvisit);
}
if (typeof entity !== 'object' || entity === null) {
return [entity, false, false];
}
const pk =
// normalize must always place a string, because pk() return value is string | undefined
// therefore no need to check for numbers
typeof entityOrId === 'string' ? entityOrId : schema.pk(isImmutable(entity) ? entity.toJS() : entity);
// if we can't generate a working pk; this is hopeless so let's give them what's already there
// otherwise, even when we aren't doing a lookup we want to turn the entityOrId object into the
// expected class, and cache that class for referential equality. PK is used for global equality lookup.
if (pk === undefined || pk === '' || pk === 'undefined') {
return [entity, false, false];
}
// last function computes if it is not in any caches
return cache.getEntity(pk, schema, entity, localCacheKey => unvisitEntityObject(entity, schema, unvisit, pk, localCacheKey));
};
function unvisitEntityObject(entity, schema, unvisit, pk, localCacheKey) {
let entityCopy, found, deleted;
/* istanbul ignore else */
if (schema.createIfValid) {
entityCopy = localCacheKey[pk] = isImmutable(entity) ? schema.createIfValid(entity.toObject()) : schema.createIfValid(entity);
// TODO(breaking): remove once old verions no longer supported
} /* istanbul ignore next */else {
entityCopy = entity;
unvisit = withTrackedEntities(unvisit);
unvisit.setLocal = entityCopy => localCacheKey[pk] = entityCopy;
}
if (entityCopy === undefined) {
// undefined indicates we should suspense (perhaps failed validation)
found = false;
deleted = true;
} else {
[localCacheKey[pk], found, deleted] = schema.denormalize(entityCopy, unvisit);
}
return [found, deleted];
}
// TODO(breaking): remove once unused
/* istanbul ignore next */
function withTrackedEntities(unvisit) {
// every time we nest, we want to unwrap back to the top.
// this is due to only needed the next level of nested entities for lookup
const originalUnvisit = unvisit.og || unvisit;
const wrappedUnvisit = (input, schema) => originalUnvisit(input, schema);
wrappedUnvisit.og = unvisit;
return wrappedUnvisit;
}
const getUnvisit = (getEntity, cache) => {
function unvisit(input, schema) {
if (!schema) return [input, true, false];
// null is considered intentional, thus always 'found' as true
if (input === null) {
return [input, true, false];
}
const hasDenormalize = typeof schema.denormalize === 'function';
// deserialize fields (like Date)
if (!hasDenormalize && typeof schema === 'function') {
if (input instanceof schema) return [input, true, false];
// field deserialization should never count against 'found' (whether to used inferred results)
if (input === undefined) return [input, true, false];
return [new schema(input), true, false];
}
if (input === undefined) {
return [input, false, false];
}
if (!hasDenormalize && typeof schema === 'object') {
const method = Array.isArray(schema) ? denormalize$3 : denormalize$2;
return method(schema, input, unvisit);
}
if (isEntity(schema)) {
return unvisitEntity(input, schema, unvisit, getEntity, cache);
}
if (hasDenormalize) {
return schema.denormalize(input, unvisit);
}
return [input, true, false];
}
return (input, schema) => {
// in the case where WeakMap cannot be used
// this test ensures null is properly excluded from WeakMap
const cachable = Object(input) === input && Object(schema) === schema;
return cache.getResults(input, cachable, () => unvisit(input, schema));
};
};
var getUnvisit$1 = getUnvisit;
/** Maps entity dependencies to a value (usually their denormalized form)

@@ -206,169 +332,111 @@ *

const unvisitEntity = (entityOrId, schema, unvisit, getEntity, getCache, localCache, cycleCache, dependencies, cycleIndex) => {
const entity = typeof entityOrId === 'object' ? entityOrId : getEntity({
pk: entityOrId,
key: schema.key
});
if (typeof entity === 'symbol' && entity.toString().includes('DELETED')) {
return [undefined, true, true];
// TODO: Change to this as breaking change once we only support newer entities
// also remove `(entity as symbol).toString().includes('DELETED')` and do this for all symbols
// return schema.denormalize(entity, unvisit);
const denormalize$1 = (input, schema, entities) => {
// undefined means don't do anything
if (schema === undefined) {
return [input, true, false];
}
if (input === undefined) {
return [undefined, false, false];
}
const getEntity = getEntities(entities);
const ret = getUnvisit$1(getEntity, new LocalCache())(input, schema);
return [ret[0], ret[1], ret[2]];
};
if (typeof entity !== 'object' || entity === null) {
return [entity, false, false];
class GlobalCache {
constructor(getEntity, entityCache, resultCache) {
this.dependencies = [];
this.cycleCache = {};
this.cycleIndex = -1;
this.localCache = {};
this._getEntity = getEntity;
this.getCache = getEntityCaches(entityCache);
this.resultCache = resultCache;
}
const pk =
// normalize must always place a string, because pk() return value is string | undefined
// therefore no need to check for numbers
typeof entityOrId === 'string' ? entityOrId : schema.pk(isImmutable(entity) ? entity.toJS() : entity);
// if we can't generate a working pk; this is hopeless so let's give them what's already there
// otherwise, even when we aren't doing a lookup we want to turn the entityOrId object into the
// expected class, and cache that class for referential equality. PK is used for global equality lookup.
if (pk === undefined || pk === '' || pk === 'undefined') {
return [entity, false, false];
}
const key = schema.key;
if (!(key in localCache)) {
localCache[key] = Object.create(null);
}
if (!(key in cycleCache)) {
cycleCache[key] = Object.create(null);
}
const localCacheKey = localCache[key];
const cycleCacheKey = cycleCache[key];
let found = true;
let deleted = false;
getEntity(pk, schema, entity, computeValue) {
const key = schema.key;
if (!(key in this.localCache)) {
this.localCache[key] = Object.create(null);
}
if (!(key in this.cycleCache)) {
this.cycleCache[key] = Object.create(null);
}
const localCacheKey = this.localCache[key];
const cycleCacheKey = this.cycleCache[key];
let found = true;
let deleted = false;
if (!localCacheKey[pk]) {
const globalCache = this.getCache(pk, schema);
const [cacheValue] = globalCache.get(entity, this._getEntity);
// TODO: what if this just returned the deps - then we don't need to store them
// local cache lookup first
if (!localCacheKey[pk]) {
const globalCache = getCache(pk, schema);
const [cacheValue] = globalCache.get(entity, getEntity);
// TODO: what if this just returned the deps - then we don't need to store them
if (cacheValue) {
localCacheKey[pk] = cacheValue.value[0];
// TODO: can we store the cache values instead of tracking *all* their sources?
// this is only used for setting results cache correctly. if we got this far we will def need to set as we would have already tried getting it
this.dependencies.push(...cacheValue.dependencies);
return cacheValue.value;
}
// if we don't find in denormalize cache then do full denormalize
else {
const trackingIndex = this.dependencies.length;
cycleCacheKey[pk] = trackingIndex;
this.dependencies.push({
entity,
path: {
key,
pk
}
});
if (cacheValue) {
localCacheKey[pk] = cacheValue.value[0];
// TODO: can we store the cache values instead of tracking *all* their sources?
// this is only used for setting results cache correctly. if we got this far we will def need to set as we would have already tried getting it
dependencies.push(...cacheValue.dependencies);
return cacheValue.value;
}
// if we don't find in denormalize cache then do full denormalize
else {
const trackingIndex = dependencies.length;
dependencies.push({
entity,
path: {
key,
pk
/** NON-GLOBAL_CACHE CODE */
[found, deleted] = computeValue(localCacheKey);
/** /END NON-GLOBAL_CACHE CODE */
delete cycleCacheKey[pk];
// if in cycle, use the start of the cycle to track all deps
// otherwise, we use our own trackingIndex
const localKey = this.dependencies.slice(this.cycleIndex === -1 ? trackingIndex : this.cycleIndex);
const cacheValue = {
dependencies: localKey,
value: [localCacheKey[pk], found, deleted]
};
globalCache.set(localKey, cacheValue);
// start of cycle - reset cycle detection
if (this.cycleIndex === trackingIndex) {
this.cycleIndex = -1;
}
});
let entityCopy;
if (schema.createIfValid) {
entityCopy = localCacheKey[pk] = isImmutable(entity) ? schema.createIfValid(entity.toObject()) : schema.createIfValid(entity);
// TODO(breaking): remove once old verions no longer supported
} else {
entityCopy = entity;
unvisit = withTrackedEntities(unvisit);
unvisit.setLocal = entityCopy => localCacheKey[pk] = entityCopy;
}
cycleCacheKey[pk] = trackingIndex;
if (entityCopy === undefined) {
// undefined indicates we should suspense (perhaps failed validation)
found = false;
deleted = true;
} else {
// cycle detected
if (pk in cycleCacheKey) {
this.cycleIndex = cycleCacheKey[pk];
} else {
[localCacheKey[pk], found, deleted] = schema.denormalize(entityCopy, unvisit);
// with no cycle, globalCacheEntry will have already been set
this.dependencies.push({
entity,
path: {
key,
pk
}
});
}
delete cycleCacheKey[pk];
// if in cycle, use the start of the cycle to track all deps
// otherwise, we use our own trackingIndex
const localKey = dependencies.slice(cycleIndex.i === -1 ? trackingIndex : cycleIndex.i);
const cacheValue = {
dependencies: localKey,
value: [localCacheKey[pk], found, deleted]
};
globalCache.set(localKey, cacheValue);
// start of cycle - reset cycle detection
if (cycleIndex.i === trackingIndex) {
cycleIndex.i = -1;
}
}
} else {
// cycle detected
if (pk in cycleCacheKey) {
cycleIndex.i = cycleCacheKey[pk];
} else {
// with no cycle, globalCacheEntry will have already been set
dependencies.push({
entity,
path: {
key,
pk
}
});
}
return [localCacheKey[pk], found, deleted];
}
return [localCacheKey[pk], found, deleted];
};
const getUnvisit = (entities, entityCache, resultCache) => {
const getEntity = getEntities(entities);
const getCache = getEntityCaches(entityCache);
const localCache = {};
const dependencies = [];
const cycleIndex = {
i: -1
};
const cycleCache = {};
function unvisit(input, schema) {
if (!schema) return [input, true, false];
// null is considered intentional, thus always 'found' as true
if (input === null) {
return [input, true, false];
}
const hasDenormalize = typeof schema.denormalize === 'function';
// deserialize fields (like Date)
if (!hasDenormalize && typeof schema === 'function') {
if (input instanceof schema) return [input, true, false];
// field deserialization should never count against 'found' (whether to used inferred results)
if (input === undefined) return [input, true, false];
return [new schema(input), true, false];
}
if (input === undefined) {
return [input, false, false];
}
if (!hasDenormalize && typeof schema === 'object') {
const method = Array.isArray(schema) ? denormalize$2 : denormalize$1;
return method(schema, input, unvisit);
}
if (isEntity(schema)) {
return unvisitEntity(input, schema, unvisit, getEntity, getCache, localCache, cycleCache, dependencies, cycleIndex);
}
if (hasDenormalize) {
return schema.denormalize(input, unvisit);
}
return [input, true, false];
}
return (input, schema) => {
// in the case where WeakMap cannot be used
// this test ensures null is properly excluded from WeakMap
const cachable = Object(input) === input && Object(schema) === schema;
getResults(input, cachable, computeValue) {
if (!cachable) {
const ret = unvisit(input, schema);
const ret = computeValue();
// this is faster than spread
// https://www.measurethat.net/Benchmarks/Show/23636/0/spread-with-tuples
return [ret[0], ret[1], ret[2], depToPaths(dependencies)];
return [ret[0], ret[1], ret[2], this.paths()];
}
let [ret, entityPaths] = resultCache.get(input, getEntity);
let [ret, entityPaths] = this.resultCache.get(input, this._getEntity);
if (ret === undefined) {
ret = unvisit(input, schema);
ret = computeValue();
// we want to do this before we add our 'input' entry
entityPaths = depToPaths(dependencies);
entityPaths = this.paths();
// for the first entry, `path` is ignored so empty members is fine
dependencies.unshift({
this.dependencies.unshift({
entity: input,

@@ -380,7 +448,10 @@ path: {

});
resultCache.set(dependencies, ret);
this.resultCache.set(this.dependencies, ret);
}
return [ret[0], ret[1], ret[2], entityPaths];
};
};
}
paths() {
return depToPaths(this.dependencies);
}
}
const getEntityCaches = entityCache => {

@@ -402,5 +473,6 @@ return (pk, schema) => {

};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
const denormalize = (input, schema, entities, entityCache = {}, resultCache = new WeakEntityMap()) => {
// undefined mean don't do anything
// undefined means don't do anything
if (schema === undefined) {

@@ -412,15 +484,6 @@ return [input, true, false, []];

}
return getUnvisit(entities, entityCache, resultCache)(input, schema);
const getEntity = getEntities(entities);
return getUnvisit$1(getEntity, new GlobalCache(getEntity, entityCache, resultCache))(input, schema);
};
// TODO(breaking): remove once unused
function withTrackedEntities(unvisit) {
// every time we nest, we want to unwrap back to the top.
// this is due to only needed the next level of nested entities for lookup
const originalUnvisit = unvisit.og || unvisit;
const wrappedUnvisit = (input, schema) => originalUnvisit(input, schema);
wrappedUnvisit.og = unvisit;
return wrappedUnvisit;
}
const DELETED = Symbol('ENTITY WAS DELETED');

@@ -633,2 +696,3 @@

};
const denormalizeCached = denormalize;

@@ -639,2 +703,4 @@ exports.DELETED = DELETED;

exports.denormalize = denormalize;
exports.denormalizeCached = denormalizeCached;
exports.denormalizeSimple = denormalize$1;
exports.inferResults = inferResults;

@@ -641,0 +707,0 @@ exports.isEntity = isEntity;

var rest_hooks_normalizr = (function (exports) {
'use strict';
class LocalCache {
constructor() {
this.localCache = {};
}
getEntity(pk, schema, entity, computeValue) {
const key = schema.key;
if (!(key in this.localCache)) {
this.localCache[key] = Object.create(null);
}
const localCacheKey = this.localCache[key];
let found = true;
let deleted = false;
if (!localCacheKey[pk]) {
[found, deleted] = computeValue(localCacheKey);
}
return [localCacheKey[pk], found, deleted];
}
getResults(input, cachable, computeValue) {
const ret = computeValue();
// this is faster than spread
// https://www.measurethat.net/Benchmarks/Show/23636/0/spread-with-tuples
return [ret[0], ret[1], ret[2], []];
}
}
function isEntity(schema) {

@@ -28,3 +53,3 @@ return schema !== null && schema.pk !== undefined;

};
const denormalize$2 = (schema, input, unvisit) => {
const denormalize$3 = (schema, input, unvisit) => {
schema = validateSchema(schema);

@@ -100,3 +125,3 @@ return [input.map ? input.map(entityOrId => unvisit(entityOrId, schema)).filter(filterEmpty).map(([value]) => value) : input, true, false];

};
const denormalize$1 = (schema, input, unvisit) => {
const denormalize$2 = (schema, input, unvisit) => {
if (isImmutable(input)) {

@@ -130,2 +155,103 @@ return denormalizeImmutable(schema, input, unvisit);

const unvisitEntity = (entityOrId, schema, unvisit, getEntity, cache) => {
const entity = typeof entityOrId === 'object' ? entityOrId : getEntity({
pk: entityOrId,
key: schema.key
});
if (typeof entity === 'symbol' && entity.toString().includes('DELETED')) {
return [undefined, true, true];
// TODO: Change to this as breaking change once we only support newer entities
// also remove `(entity as symbol).toString().includes('DELETED')` and do this for all symbols
// return schema.denormalize(entity, unvisit);
}
if (typeof entity !== 'object' || entity === null) {
return [entity, false, false];
}
const pk =
// normalize must always place a string, because pk() return value is string | undefined
// therefore no need to check for numbers
typeof entityOrId === 'string' ? entityOrId : schema.pk(isImmutable(entity) ? entity.toJS() : entity);
// if we can't generate a working pk; this is hopeless so let's give them what's already there
// otherwise, even when we aren't doing a lookup we want to turn the entityOrId object into the
// expected class, and cache that class for referential equality. PK is used for global equality lookup.
if (pk === undefined || pk === '' || pk === 'undefined') {
return [entity, false, false];
}
// last function computes if it is not in any caches
return cache.getEntity(pk, schema, entity, localCacheKey => unvisitEntityObject(entity, schema, unvisit, pk, localCacheKey));
};
function unvisitEntityObject(entity, schema, unvisit, pk, localCacheKey) {
let entityCopy, found, deleted;
/* istanbul ignore else */
if (schema.createIfValid) {
entityCopy = localCacheKey[pk] = isImmutable(entity) ? schema.createIfValid(entity.toObject()) : schema.createIfValid(entity);
// TODO(breaking): remove once old verions no longer supported
} /* istanbul ignore next */else {
entityCopy = entity;
unvisit = withTrackedEntities(unvisit);
unvisit.setLocal = entityCopy => localCacheKey[pk] = entityCopy;
}
if (entityCopy === undefined) {
// undefined indicates we should suspense (perhaps failed validation)
found = false;
deleted = true;
} else {
[localCacheKey[pk], found, deleted] = schema.denormalize(entityCopy, unvisit);
}
return [found, deleted];
}
// TODO(breaking): remove once unused
/* istanbul ignore next */
function withTrackedEntities(unvisit) {
// every time we nest, we want to unwrap back to the top.
// this is due to only needed the next level of nested entities for lookup
const originalUnvisit = unvisit.og || unvisit;
const wrappedUnvisit = (input, schema) => originalUnvisit(input, schema);
wrappedUnvisit.og = unvisit;
return wrappedUnvisit;
}
const getUnvisit = (getEntity, cache) => {
function unvisit(input, schema) {
if (!schema) return [input, true, false];
// null is considered intentional, thus always 'found' as true
if (input === null) {
return [input, true, false];
}
const hasDenormalize = typeof schema.denormalize === 'function';
// deserialize fields (like Date)
if (!hasDenormalize && typeof schema === 'function') {
if (input instanceof schema) return [input, true, false];
// field deserialization should never count against 'found' (whether to used inferred results)
if (input === undefined) return [input, true, false];
return [new schema(input), true, false];
}
if (input === undefined) {
return [input, false, false];
}
if (!hasDenormalize && typeof schema === 'object') {
const method = Array.isArray(schema) ? denormalize$3 : denormalize$2;
return method(schema, input, unvisit);
}
if (isEntity(schema)) {
return unvisitEntity(input, schema, unvisit, getEntity, cache);
}
if (hasDenormalize) {
return schema.denormalize(input, unvisit);
}
return [input, true, false];
}
return (input, schema) => {
// in the case where WeakMap cannot be used
// this test ensures null is properly excluded from WeakMap
const cachable = Object(input) === input && Object(schema) === schema;
return cache.getResults(input, cachable, () => unvisit(input, schema));
};
};
var getUnvisit$1 = getUnvisit;
/** Maps entity dependencies to a value (usually their denormalized form)

@@ -207,169 +333,111 @@ *

const unvisitEntity = (entityOrId, schema, unvisit, getEntity, getCache, localCache, cycleCache, dependencies, cycleIndex) => {
const entity = typeof entityOrId === 'object' ? entityOrId : getEntity({
pk: entityOrId,
key: schema.key
});
if (typeof entity === 'symbol' && entity.toString().includes('DELETED')) {
return [undefined, true, true];
// TODO: Change to this as breaking change once we only support newer entities
// also remove `(entity as symbol).toString().includes('DELETED')` and do this for all symbols
// return schema.denormalize(entity, unvisit);
const denormalize$1 = (input, schema, entities) => {
// undefined means don't do anything
if (schema === undefined) {
return [input, true, false];
}
if (input === undefined) {
return [undefined, false, false];
}
const getEntity = getEntities(entities);
const ret = getUnvisit$1(getEntity, new LocalCache())(input, schema);
return [ret[0], ret[1], ret[2]];
};
if (typeof entity !== 'object' || entity === null) {
return [entity, false, false];
class GlobalCache {
constructor(getEntity, entityCache, resultCache) {
this.dependencies = [];
this.cycleCache = {};
this.cycleIndex = -1;
this.localCache = {};
this._getEntity = getEntity;
this.getCache = getEntityCaches(entityCache);
this.resultCache = resultCache;
}
const pk =
// normalize must always place a string, because pk() return value is string | undefined
// therefore no need to check for numbers
typeof entityOrId === 'string' ? entityOrId : schema.pk(isImmutable(entity) ? entity.toJS() : entity);
// if we can't generate a working pk; this is hopeless so let's give them what's already there
// otherwise, even when we aren't doing a lookup we want to turn the entityOrId object into the
// expected class, and cache that class for referential equality. PK is used for global equality lookup.
if (pk === undefined || pk === '' || pk === 'undefined') {
return [entity, false, false];
}
const key = schema.key;
if (!(key in localCache)) {
localCache[key] = Object.create(null);
}
if (!(key in cycleCache)) {
cycleCache[key] = Object.create(null);
}
const localCacheKey = localCache[key];
const cycleCacheKey = cycleCache[key];
let found = true;
let deleted = false;
getEntity(pk, schema, entity, computeValue) {
const key = schema.key;
if (!(key in this.localCache)) {
this.localCache[key] = Object.create(null);
}
if (!(key in this.cycleCache)) {
this.cycleCache[key] = Object.create(null);
}
const localCacheKey = this.localCache[key];
const cycleCacheKey = this.cycleCache[key];
let found = true;
let deleted = false;
if (!localCacheKey[pk]) {
const globalCache = this.getCache(pk, schema);
const [cacheValue] = globalCache.get(entity, this._getEntity);
// TODO: what if this just returned the deps - then we don't need to store them
// local cache lookup first
if (!localCacheKey[pk]) {
const globalCache = getCache(pk, schema);
const [cacheValue] = globalCache.get(entity, getEntity);
// TODO: what if this just returned the deps - then we don't need to store them
if (cacheValue) {
localCacheKey[pk] = cacheValue.value[0];
// TODO: can we store the cache values instead of tracking *all* their sources?
// this is only used for setting results cache correctly. if we got this far we will def need to set as we would have already tried getting it
this.dependencies.push(...cacheValue.dependencies);
return cacheValue.value;
}
// if we don't find in denormalize cache then do full denormalize
else {
const trackingIndex = this.dependencies.length;
cycleCacheKey[pk] = trackingIndex;
this.dependencies.push({
entity,
path: {
key,
pk
}
});
if (cacheValue) {
localCacheKey[pk] = cacheValue.value[0];
// TODO: can we store the cache values instead of tracking *all* their sources?
// this is only used for setting results cache correctly. if we got this far we will def need to set as we would have already tried getting it
dependencies.push(...cacheValue.dependencies);
return cacheValue.value;
}
// if we don't find in denormalize cache then do full denormalize
else {
const trackingIndex = dependencies.length;
dependencies.push({
entity,
path: {
key,
pk
/** NON-GLOBAL_CACHE CODE */
[found, deleted] = computeValue(localCacheKey);
/** /END NON-GLOBAL_CACHE CODE */
delete cycleCacheKey[pk];
// if in cycle, use the start of the cycle to track all deps
// otherwise, we use our own trackingIndex
const localKey = this.dependencies.slice(this.cycleIndex === -1 ? trackingIndex : this.cycleIndex);
const cacheValue = {
dependencies: localKey,
value: [localCacheKey[pk], found, deleted]
};
globalCache.set(localKey, cacheValue);
// start of cycle - reset cycle detection
if (this.cycleIndex === trackingIndex) {
this.cycleIndex = -1;
}
});
let entityCopy;
if (schema.createIfValid) {
entityCopy = localCacheKey[pk] = isImmutable(entity) ? schema.createIfValid(entity.toObject()) : schema.createIfValid(entity);
// TODO(breaking): remove once old verions no longer supported
} else {
entityCopy = entity;
unvisit = withTrackedEntities(unvisit);
unvisit.setLocal = entityCopy => localCacheKey[pk] = entityCopy;
}
cycleCacheKey[pk] = trackingIndex;
if (entityCopy === undefined) {
// undefined indicates we should suspense (perhaps failed validation)
found = false;
deleted = true;
} else {
// cycle detected
if (pk in cycleCacheKey) {
this.cycleIndex = cycleCacheKey[pk];
} else {
[localCacheKey[pk], found, deleted] = schema.denormalize(entityCopy, unvisit);
// with no cycle, globalCacheEntry will have already been set
this.dependencies.push({
entity,
path: {
key,
pk
}
});
}
delete cycleCacheKey[pk];
// if in cycle, use the start of the cycle to track all deps
// otherwise, we use our own trackingIndex
const localKey = dependencies.slice(cycleIndex.i === -1 ? trackingIndex : cycleIndex.i);
const cacheValue = {
dependencies: localKey,
value: [localCacheKey[pk], found, deleted]
};
globalCache.set(localKey, cacheValue);
// start of cycle - reset cycle detection
if (cycleIndex.i === trackingIndex) {
cycleIndex.i = -1;
}
}
} else {
// cycle detected
if (pk in cycleCacheKey) {
cycleIndex.i = cycleCacheKey[pk];
} else {
// with no cycle, globalCacheEntry will have already been set
dependencies.push({
entity,
path: {
key,
pk
}
});
}
return [localCacheKey[pk], found, deleted];
}
return [localCacheKey[pk], found, deleted];
};
const getUnvisit = (entities, entityCache, resultCache) => {
const getEntity = getEntities(entities);
const getCache = getEntityCaches(entityCache);
const localCache = {};
const dependencies = [];
const cycleIndex = {
i: -1
};
const cycleCache = {};
function unvisit(input, schema) {
if (!schema) return [input, true, false];
// null is considered intentional, thus always 'found' as true
if (input === null) {
return [input, true, false];
}
const hasDenormalize = typeof schema.denormalize === 'function';
// deserialize fields (like Date)
if (!hasDenormalize && typeof schema === 'function') {
if (input instanceof schema) return [input, true, false];
// field deserialization should never count against 'found' (whether to used inferred results)
if (input === undefined) return [input, true, false];
return [new schema(input), true, false];
}
if (input === undefined) {
return [input, false, false];
}
if (!hasDenormalize && typeof schema === 'object') {
const method = Array.isArray(schema) ? denormalize$2 : denormalize$1;
return method(schema, input, unvisit);
}
if (isEntity(schema)) {
return unvisitEntity(input, schema, unvisit, getEntity, getCache, localCache, cycleCache, dependencies, cycleIndex);
}
if (hasDenormalize) {
return schema.denormalize(input, unvisit);
}
return [input, true, false];
}
return (input, schema) => {
// in the case where WeakMap cannot be used
// this test ensures null is properly excluded from WeakMap
const cachable = Object(input) === input && Object(schema) === schema;
getResults(input, cachable, computeValue) {
if (!cachable) {
const ret = unvisit(input, schema);
const ret = computeValue();
// this is faster than spread
// https://www.measurethat.net/Benchmarks/Show/23636/0/spread-with-tuples
return [ret[0], ret[1], ret[2], depToPaths(dependencies)];
return [ret[0], ret[1], ret[2], this.paths()];
}
let [ret, entityPaths] = resultCache.get(input, getEntity);
let [ret, entityPaths] = this.resultCache.get(input, this._getEntity);
if (ret === undefined) {
ret = unvisit(input, schema);
ret = computeValue();
// we want to do this before we add our 'input' entry
entityPaths = depToPaths(dependencies);
entityPaths = this.paths();
// for the first entry, `path` is ignored so empty members is fine
dependencies.unshift({
this.dependencies.unshift({
entity: input,

@@ -381,7 +449,10 @@ path: {

});
resultCache.set(dependencies, ret);
this.resultCache.set(this.dependencies, ret);
}
return [ret[0], ret[1], ret[2], entityPaths];
};
};
}
paths() {
return depToPaths(this.dependencies);
}
}
const getEntityCaches = entityCache => {

@@ -403,5 +474,6 @@ return (pk, schema) => {

};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
const denormalize = (input, schema, entities, entityCache = {}, resultCache = new WeakEntityMap()) => {
// undefined mean don't do anything
// undefined means don't do anything
if (schema === undefined) {

@@ -413,15 +485,6 @@ return [input, true, false, []];

}
return getUnvisit(entities, entityCache, resultCache)(input, schema);
const getEntity = getEntities(entities);
return getUnvisit$1(getEntity, new GlobalCache(getEntity, entityCache, resultCache))(input, schema);
};
// TODO(breaking): remove once unused
function withTrackedEntities(unvisit) {
// every time we nest, we want to unwrap back to the top.
// this is due to only needed the next level of nested entities for lookup
const originalUnvisit = unvisit.og || unvisit;
const wrappedUnvisit = (input, schema) => originalUnvisit(input, schema);
wrappedUnvisit.og = unvisit;
return wrappedUnvisit;
}
const DELETED = Symbol('ENTITY WAS DELETED');

@@ -634,2 +697,3 @@

};
const denormalizeCached = denormalize;

@@ -640,2 +704,4 @@ exports.DELETED = DELETED;

exports.denormalize = denormalize;
exports.denormalizeCached = denormalizeCached;
exports.denormalizeSimple = denormalize$1;
exports.inferResults = inferResults;

@@ -642,0 +708,0 @@ exports.isEntity = isEntity;

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

function e(e){return null!==e&&void 0!==e.pk}const t=e=>{if("production"!==process.env.NODE_ENV){if(Array.isArray(e)&&e.length>1)throw new Error(`Expected schema definition to be a single schema, but found ${e.length}.`)}return e[0]},n=([e,,t])=>void 0!==e&&!t,r=(e,n,r,o,i,s,c)=>{e=t(e);const a=(e=>Array.isArray(e)?e:Object.keys(e).map((t=>e[t])))(n);return a.map(((t,n)=>i(t,r,o,e,s,c)))},o=(e,r,o)=>(e=t(e),[r.map?r.map((t=>o(t,e))).filter(n).map((([e])=>e)):r,!0,!1]);function i(e,t,n,r){}function s(e){return!("function"!=typeof e.hasOwnProperty||!(Object.hasOwnProperty.call(e,"__ownerID")||e._map&&Object.hasOwnProperty.call(e._map,"__ownerID")))}const c=(e,t,n,r,o,i,s)=>{const c=Object.assign({},t);return Object.keys(e).forEach((n=>{const r=e[n],a=o(t[n],t,n,r,i,s);null==a?delete c[n]:c[n]=a})),c},a=(e,t,n)=>{if(s(t))return function(e,t,n){let r=!0,o=!1;return[Object.keys(e).reduce(((t,i)=>{const s=`${i}`,[c,a,u]=n(t.get(s),e[s]);return a||(r=!1),u&&(o=!0),t.has(s)?t.set(s,c):t}),t),r,o]}(e,t,n);const r=Object.assign({},t);let o=!0,i=!1;return Object.keys(e).forEach((t=>{const[s,c,a]=n(r[t],e[t]);void 0!==r[t]&&(r[t]=s),a&&(i=!0),c||(o=!1)})),[r,o,i]};function u(e,t,n,r,o){const i={};for(const s of Object.keys(e))i[s]=r(e[s],t,n,o);return i}class f{constructor(){this.next=new WeakMap}get(e,t){let n=this.next.get(e);if(!n)return l;for(;n.nextPath;){const e=t(n.nextPath);if(n=n.next.get(e),!n)return l}return[n.value,n.journey]}set(e,t){if(e.length<1)throw new y;let n=this;for(const{entity:t,path:r}of e){let e=n.next.get(t);e||(e=new d,n.next.set(t,e)),n.nextPath=r,n=e}delete n.nextPath,n.value=t,n.journey=p(e)}}const l=[void 0,void 0];function p(e){return e.map((e=>e.path))}class d{constructor(){this.next=new WeakMap}}class y extends Error{constructor(...e){super(...e),this.message="Keys must include at least one member"}}const h=(t,n,r)=>{const i=s(c=t)?({key:e,pk:t})=>c.getIn([e,t]):({key:e,pk:t})=>{var n;return null==(n=c[e])?void 0:n[t]};var c;const u=g(n),f={},l=[],d={i:-1},y={};function h(t,n){if(!n)return[t,!0,!1];if(null===t)return[t,!0,!1];const r="function"==typeof n.denormalize;if(!r&&"function"==typeof n)return t instanceof n||void 0===t?[t,!0,!1]:[new n(t),!0,!1];if(void 0===t)return[t,!1,!1];if(!r&&"object"==typeof n){return(Array.isArray(n)?o:a)(n,t,h)}return e(n)?((e,t,n,r,o,i,c,a,u)=>{const f="object"==typeof e?e:r({pk:e,key:t.key});if("symbol"==typeof f&&f.toString().includes("DELETED"))return[void 0,!0,!0];if("object"!=typeof f||null===f)return[f,!1,!1];const l="string"==typeof e?e:t.pk(s(f)?f.toJS():f);if(void 0===l||""===l||"undefined"===l)return[f,!1,!1];const p=t.key;p in i||(i[p]=Object.create(null)),p in c||(c[p]=Object.create(null));const d=i[p],y=c[p];let h=!0,g=!1;if(d[l])l in y?u.i=y[l]:a.push({entity:f,path:{key:p,pk:l}});else{const e=o(l,t),[i]=e.get(f,r);if(i)return d[l]=i.value[0],a.push(...i.dependencies),i.value;{const r=a.length;let o;a.push({entity:f,path:{key:p,pk:l}}),t.createIfValid?o=d[l]=s(f)?t.createIfValid(f.toObject()):t.createIfValid(f):(o=f,n=function(e){const t=e.og||e,n=(e,n)=>t(e,n);return n.og=e,n}(n),n.setLocal=e=>d[l]=e),y[l]=r,void 0===o?(h=!1,g=!0):[d[l],h,g]=t.denormalize(o,n),delete y[l];const i=a.slice(-1===u.i?r:u.i),c={dependencies:i,value:[d[l],h,g]};e.set(i,c),u.i===r&&(u.i=-1)}}return[d[l],h,g]})(t,n,h,i,u,f,y,l,d):r?n.denormalize(t,h):[t,!0,!1]}return(e,t)=>{if(!(Object(e)===e&&Object(t)===t)){const n=h(e,t);return[n[0],n[1],n[2],p(l)]}let[n,o]=r.get(e,i);return void 0===n&&(n=h(e,t),o=p(l),l.unshift({entity:e,path:{key:"",pk:""}}),r.set(l,n)),[n[0],n[1],n[2],o]}},g=e=>(t,n)=>{const r=n.key;r in e||(e[r]=Object.create(null));const o=e[r];o[t]||(o[t]=new WeakMap);let i=o[t].get(n);return i||(i=new f,o[t].set(n,i)),i},b=(e,t,n,r={},o=new f)=>void 0===t?[e,!0,!1,[]]:void 0===e?[void 0,!1,!1,[]]:h(n,r,o)(e,t);const m=Symbol("ENTITY WAS DELETED"),O=(e,t,n,o,i,s)=>{if(!e||!o)return e;if(o.normalize&&"function"==typeof o.normalize)return"object"!=typeof e?e:o.normalize(e,t,n,O,i,s);if("function"==typeof o)return new o(e);if("object"!=typeof e||"object"!=typeof o)return e;return(Array.isArray(o)?r:c)(o,e,t,n,O,i,s)};const v=(e,t,n={},r={},o={},i={date:Date.now(),expiresAt:1/0,fetchedAt:0})=>{if(null==t)return{entities:n,indexes:r,result:e,entityMeta:o};const s=function(e){return["object","function"].includes(typeof e)?"object":typeof e}(t);if(null===e||typeof e!==s&&(void 0===t.key||void 0!==t.pk||"string"!=typeof e)){if("production"!==process.env.NODE_ENV){const n=e=>{try{return"string"!=typeof JSON.parse(e)}catch(e){return!1}};throw"string"==typeof e&&n(e)?new Error(`Normalizing a string, but this does match schema.\n\nParsing this input string as JSON worked. This likely indicates fetch function did not parse\nthe JSON. By default, this only happens if "content-type" header includes "json".\nSee https://resthooks.io/rest/api/RestEndpoint#parseResponse for more information\n\n Schema: ${JSON.stringify(t,void 0,2)}\n Input: "${e}"`):new Error(`Unexpected input given to normalize. Expected type to be "${s}", found "${null===e?"null":typeof e}".\n\n Schema: ${JSON.stringify(t,void 0,2)}\n Input: "${e}"`)}throw new Error(`Unexpected input given to normalize. Expected type to be "${s}", found "${null===e?"null":typeof e}".`)}const c=Object.assign({},n),a=Object.assign({},r),u=Object.assign({},o),f=((e,t,n,r,o,i)=>(s,c,a)=>{const u=s.key;u in e||(e[u]={},n[u]=Object.assign({},n[u]),o[u]=Object.assign({},o[u]));const f=e[u][a];if(f)e[u][a]=s.merge(f,c);else{const t=s.expiresAt?s.expiresAt(i,c):i.expiresAt,r=n[u][a];let f;var l,p;r&&(f=o[u][a])?(e[u][a]=s.mergeWithStore?s.mergeWithStore(f,i,r,c):function(e,t,n,r,o){return(e.useIncoming&&n.fetchedAt?e.useIncoming(t,n,r,o):t.date<=n.date)?typeof o!=typeof r?o:e.merge(r,o):r}(s,f,i,r,c),o[u][a]={expiresAt:Math.max(t,f.expiresAt),date:Math.max(i.date,f.date),fetchedAt:Math.max(null!=(l=i.fetchedAt)?l:0,f.fetchedAt)}):(e[u][a]=c,o[u][a]={expiresAt:t,date:i.date,fetchedAt:null!=(p=i.fetchedAt)?p:i.date})}if(s.indexes){const o=e[u][a];u in t||(t[u]={},r[u]=Object.assign({},r[u]));for(const e of s.indexes){e in t[u]||(r[u][e]=t[u][e]={});const i=t[u][e];f&&delete i[f[e]],n[u]&&n[u][a]&&n[u][a][e]!==o[e]&&(i[n[u][a][e]]=m),e in o?i[o[e]]=a:"production"!==process.env.NODE_ENV&&console.warn(`Index not found in entity. Indexes must be top-level members of your entity.\nIndex: ${e}\nEntity: ${JSON.stringify(o,void 0,2)}`)}}n[u][a]=e[u][a]})({},{},c,a,u,i);return{entities:c,indexes:a,result:O(e,e,void 0,t,f,{}),entityMeta:u}};function j(e,t,n,r={}){if(function(e){return!!e&&"function"==typeof e.infer}(e))return e.infer(t,n,j,r);if("object"==typeof e&&e){return(Array.isArray(e)?i:u)(e,t,n,j,r)}return e}var x={Invalid:1,InvalidIfStale:2,Valid:3};Object.hasOwn=Object.hasOwn||function(e,t){return Object.prototype.hasOwnProperty.call(e,t)};export{m as DELETED,x as ExpiryStatus,f as WeakEntityMap,b as denormalize,j as inferResults,e as isEntity,v as normalize};
class e{constructor(){this.localCache={}}getEntity(e,t,n,r){const i=t.key;i in this.localCache||(this.localCache[i]=Object.create(null));const s=this.localCache[i];let o=!0,c=!1;return s[e]||([o,c]=r(s)),[s[e],o,c]}getResults(e,t,n){const r=n();return[r[0],r[1],r[2],[]]}}function t(e){return null!==e&&void 0!==e.pk}const n=e=>{if("production"!==process.env.NODE_ENV){if(Array.isArray(e)&&e.length>1)throw new Error(`Expected schema definition to be a single schema, but found ${e.length}.`)}return e[0]},r=([e,,t])=>void 0!==e&&!t,i=(e,t,r,i,s,o,c)=>{e=n(e);const a=(e=>Array.isArray(e)?e:Object.keys(e).map((t=>e[t])))(t);return a.map(((t,n)=>s(t,r,i,e,o,c)))},s=(e,t,i)=>(e=n(e),[t.map?t.map((t=>i(t,e))).filter(r).map((([e])=>e)):t,!0,!1]);function o(e,t,n,r){}function c(e){return!("function"!=typeof e.hasOwnProperty||!(Object.hasOwnProperty.call(e,"__ownerID")||e._map&&Object.hasOwnProperty.call(e._map,"__ownerID")))}const a=(e,t,n,r,i,s,o)=>{const c=Object.assign({},t);return Object.keys(e).forEach((n=>{const r=e[n],a=i(t[n],t,n,r,s,o);null==a?delete c[n]:c[n]=a})),c},u=(e,t,n)=>{if(c(t))return function(e,t,n){let r=!0,i=!1;return[Object.keys(e).reduce(((t,s)=>{const o=`${s}`,[c,a,u]=n(t.get(o),e[o]);return a||(r=!1),u&&(i=!0),t.has(o)?t.set(o,c):t}),t),r,i]}(e,t,n);const r=Object.assign({},t);let i=!0,s=!1;return Object.keys(e).forEach((t=>{const[o,c,a]=n(r[t],e[t]);void 0!==r[t]&&(r[t]=o),a&&(s=!0),c||(i=!1)})),[r,i,s]};function l(e,t,n,r,i){const s={};for(const o of Object.keys(e))s[o]=r(e[o],t,n,i);return s}const h=(e,t,n,r,i)=>{const s="object"==typeof e?e:r({pk:e,key:t.key});if("symbol"==typeof s&&s.toString().includes("DELETED"))return[void 0,!0,!0];if("object"!=typeof s||null===s)return[s,!1,!1];const o="string"==typeof e?e:t.pk(c(s)?s.toJS():s);return void 0===o||""===o||"undefined"===o?[s,!1,!1]:i.getEntity(o,t,s,(e=>function(e,t,n,r,i){let s,o,a;t.createIfValid?s=i[r]=c(e)?t.createIfValid(e.toObject()):t.createIfValid(e):(s=e,n=function(e){const t=e.og||e,n=(e,n)=>t(e,n);return n.og=e,n}(n),n.setLocal=e=>i[r]=e);void 0===s?(o=!1,a=!0):[i[r],o,a]=t.denormalize(s,n);return[o,a]}(s,t,n,o,e)))};var f=(e,n)=>{function r(i,o){if(!o)return[i,!0,!1];if(null===i)return[i,!0,!1];const c="function"==typeof o.denormalize;if(!c&&"function"==typeof o)return i instanceof o||void 0===i?[i,!0,!1]:[new o(i),!0,!1];if(void 0===i)return[i,!1,!1];if(!c&&"object"==typeof o){return(Array.isArray(o)?s:u)(o,i,r)}return t(o)?h(i,o,r,e,n):c?o.denormalize(i,r):[i,!0,!1]}return(e,t)=>{const i=Object(e)===e&&Object(t)===t;return n.getResults(e,i,(()=>r(e,t)))}};class d{constructor(){this.next=new WeakMap}get(e,t){let n=this.next.get(e);if(!n)return p;for(;n.nextPath;){const e=t(n.nextPath);if(n=n.next.get(e),!n)return p}return[n.value,n.journey]}set(e,t){if(e.length<1)throw new b;let n=this;for(const{entity:t,path:r}of e){let e=n.next.get(t);e||(e=new m,n.next.set(t,e)),n.nextPath=r,n=e}delete n.nextPath,n.value=t,n.journey=g(e)}}const p=[void 0,void 0];function y(e){return c(e)?({key:t,pk:n})=>e.getIn([t,n]):({key:t,pk:n})=>{var r;return null==(r=e[t])?void 0:r[n]}}function g(e){return e.map((e=>e.path))}class m{constructor(){this.next=new WeakMap}}class b extends Error{constructor(...e){super(...e),this.message="Keys must include at least one member"}}const v=(t,n,r)=>{if(void 0===n)return[t,!0,!1];if(void 0===t)return[void 0,!1,!1];const i=y(r),s=f(i,new e)(t,n);return[s[0],s[1],s[2]]};class x{constructor(e,t,n){this.dependencies=[],this.cycleCache={},this.cycleIndex=-1,this.localCache={},this._getEntity=e,this.getCache=O(t),this.resultCache=n}getEntity(e,t,n,r){const i=t.key;i in this.localCache||(this.localCache[i]=Object.create(null)),i in this.cycleCache||(this.cycleCache[i]=Object.create(null));const s=this.localCache[i],o=this.cycleCache[i];let c=!0,a=!1;if(s[e])e in o?this.cycleIndex=o[e]:this.dependencies.push({entity:n,path:{key:i,pk:e}});else{const u=this.getCache(e,t),[l]=u.get(n,this._getEntity);if(l)return s[e]=l.value[0],this.dependencies.push(...l.dependencies),l.value;{const t=this.dependencies.length;o[e]=t,this.dependencies.push({entity:n,path:{key:i,pk:e}}),[c,a]=r(s),delete o[e];const l=this.dependencies.slice(-1===this.cycleIndex?t:this.cycleIndex),h={dependencies:l,value:[s[e],c,a]};u.set(l,h),this.cycleIndex===t&&(this.cycleIndex=-1)}}return[s[e],c,a]}getResults(e,t,n){if(!t){const e=n();return[e[0],e[1],e[2],this.paths()]}let[r,i]=this.resultCache.get(e,this._getEntity);return void 0===r&&(r=n(),i=this.paths(),this.dependencies.unshift({entity:e,path:{key:"",pk:""}}),this.resultCache.set(this.dependencies,r)),[r[0],r[1],r[2],i]}paths(){return g(this.dependencies)}}const O=e=>(t,n)=>{const r=n.key;r in e||(e[r]=Object.create(null));const i=e[r];i[t]||(i[t]=new WeakMap);let s=i[t].get(n);return s||(s=new d,i[t].set(n,s)),s},j=(e,t,n,r={},i=new d)=>{if(void 0===t)return[e,!0,!1,[]];if(void 0===e)return[void 0,!1,!1,[]];const s=y(n);return f(s,new x(s,r,i))(e,t)},k=Symbol("ENTITY WAS DELETED"),E=(e,t,n,r,s,o)=>{if(!e||!r)return e;if(r.normalize&&"function"==typeof r.normalize)return"object"!=typeof e?e:r.normalize(e,t,n,E,s,o);if("function"==typeof r)return new r(e);if("object"!=typeof e||"object"!=typeof r)return e;return(Array.isArray(r)?i:a)(r,e,t,n,E,s,o)};const w=(e,t,n={},r={},i={},s={date:Date.now(),expiresAt:1/0,fetchedAt:0})=>{if(null==t)return{entities:n,indexes:r,result:e,entityMeta:i};const o=function(e){return["object","function"].includes(typeof e)?"object":typeof e}(t);if(null===e||typeof e!==o&&(void 0===t.key||void 0!==t.pk||"string"!=typeof e)){if("production"!==process.env.NODE_ENV){const n=e=>{try{return"string"!=typeof JSON.parse(e)}catch(e){return!1}};throw"string"==typeof e&&n(e)?new Error(`Normalizing a string, but this does match schema.\n\nParsing this input string as JSON worked. This likely indicates fetch function did not parse\nthe JSON. By default, this only happens if "content-type" header includes "json".\nSee https://resthooks.io/rest/api/RestEndpoint#parseResponse for more information\n\n Schema: ${JSON.stringify(t,void 0,2)}\n Input: "${e}"`):new Error(`Unexpected input given to normalize. Expected type to be "${o}", found "${null===e?"null":typeof e}".\n\n Schema: ${JSON.stringify(t,void 0,2)}\n Input: "${e}"`)}throw new Error(`Unexpected input given to normalize. Expected type to be "${o}", found "${null===e?"null":typeof e}".`)}const c=Object.assign({},n),a=Object.assign({},r),u=Object.assign({},i),l=((e,t,n,r,i,s)=>(o,c,a)=>{const u=o.key;u in e||(e[u]={},n[u]=Object.assign({},n[u]),i[u]=Object.assign({},i[u]));const l=e[u][a];if(l)e[u][a]=o.merge(l,c);else{const t=o.expiresAt?o.expiresAt(s,c):s.expiresAt,r=n[u][a];let l;var h,f;r&&(l=i[u][a])?(e[u][a]=o.mergeWithStore?o.mergeWithStore(l,s,r,c):function(e,t,n,r,i){return(e.useIncoming&&n.fetchedAt?e.useIncoming(t,n,r,i):t.date<=n.date)?typeof i!=typeof r?i:e.merge(r,i):r}(o,l,s,r,c),i[u][a]={expiresAt:Math.max(t,l.expiresAt),date:Math.max(s.date,l.date),fetchedAt:Math.max(null!=(h=s.fetchedAt)?h:0,l.fetchedAt)}):(e[u][a]=c,i[u][a]={expiresAt:t,date:s.date,fetchedAt:null!=(f=s.fetchedAt)?f:s.date})}if(o.indexes){const i=e[u][a];u in t||(t[u]={},r[u]=Object.assign({},r[u]));for(const e of o.indexes){e in t[u]||(r[u][e]=t[u][e]={});const s=t[u][e];l&&delete s[l[e]],n[u]&&n[u][a]&&n[u][a][e]!==i[e]&&(s[n[u][a][e]]=k),e in i?s[i[e]]=a:"production"!==process.env.NODE_ENV&&console.warn(`Index not found in entity. Indexes must be top-level members of your entity.\nIndex: ${e}\nEntity: ${JSON.stringify(i,void 0,2)}`)}}n[u][a]=e[u][a]})({},{},c,a,u,s);return{entities:c,indexes:a,result:E(e,e,void 0,t,l,{}),entityMeta:u}};function A(e,t,n,r={}){if(function(e){return!!e&&"function"==typeof e.infer}(e))return e.infer(t,n,A,r);if("object"==typeof e&&e){return(Array.isArray(e)?o:l)(e,t,n,A,r)}return e}var I={Invalid:1,InvalidIfStale:2,Valid:3};Object.hasOwn=Object.hasOwn||function(e,t){return Object.prototype.hasOwnProperty.call(e,t)};const C=j;export{k as DELETED,I as ExpiryStatus,d as WeakEntityMap,j as denormalize,C as denormalizeCached,v as denormalizeSimple,A as inferResults,t as isEntity,w as normalize};

@@ -5,2 +5,27 @@ 'use strict';

class LocalCache {
constructor() {
this.localCache = {};
}
getEntity(pk, schema, entity, computeValue) {
const key = schema.key;
if (!(key in this.localCache)) {
this.localCache[key] = Object.create(null);
}
const localCacheKey = this.localCache[key];
let found = true;
let deleted = false;
if (!localCacheKey[pk]) {
[found, deleted] = computeValue(localCacheKey);
}
return [localCacheKey[pk], found, deleted];
}
getResults(input, cachable, computeValue) {
const ret = computeValue();
// this is faster than spread
// https://www.measurethat.net/Benchmarks/Show/23636/0/spread-with-tuples
return [ret[0], ret[1], ret[2], []];
}
}
function isEntity(schema) {

@@ -30,3 +55,3 @@ return schema !== null && schema.pk !== undefined;

};
const denormalize$2 = (schema, input, unvisit) => {
const denormalize$3 = (schema, input, unvisit) => {
schema = validateSchema(schema);

@@ -104,3 +129,3 @@ return [input.map ? input.map(entityOrId => unvisit(entityOrId, schema)).filter(filterEmpty).map(([value]) => value) : input, true, false];

};
const denormalize$1 = (schema, input, unvisit) => {
const denormalize$2 = (schema, input, unvisit) => {
if (isImmutable(input)) {

@@ -136,2 +161,103 @@ return denormalizeImmutable(schema, input, unvisit);

const unvisitEntity = (entityOrId, schema, unvisit, getEntity, cache) => {
const entity = typeof entityOrId === 'object' ? entityOrId : getEntity({
pk: entityOrId,
key: schema.key
});
if (typeof entity === 'symbol' && entity.toString().includes('DELETED')) {
return [undefined, true, true];
// TODO: Change to this as breaking change once we only support newer entities
// also remove `(entity as symbol).toString().includes('DELETED')` and do this for all symbols
// return schema.denormalize(entity, unvisit);
}
if (typeof entity !== 'object' || entity === null) {
return [entity, false, false];
}
const pk =
// normalize must always place a string, because pk() return value is string | undefined
// therefore no need to check for numbers
typeof entityOrId === 'string' ? entityOrId : schema.pk(isImmutable(entity) ? entity.toJS() : entity);
// if we can't generate a working pk; this is hopeless so let's give them what's already there
// otherwise, even when we aren't doing a lookup we want to turn the entityOrId object into the
// expected class, and cache that class for referential equality. PK is used for global equality lookup.
if (pk === undefined || pk === '' || pk === 'undefined') {
return [entity, false, false];
}
// last function computes if it is not in any caches
return cache.getEntity(pk, schema, entity, localCacheKey => unvisitEntityObject(entity, schema, unvisit, pk, localCacheKey));
};
function unvisitEntityObject(entity, schema, unvisit, pk, localCacheKey) {
let entityCopy, found, deleted;
/* istanbul ignore else */
if (schema.createIfValid) {
entityCopy = localCacheKey[pk] = isImmutable(entity) ? schema.createIfValid(entity.toObject()) : schema.createIfValid(entity);
// TODO(breaking): remove once old verions no longer supported
} /* istanbul ignore next */else {
entityCopy = entity;
unvisit = withTrackedEntities(unvisit);
unvisit.setLocal = entityCopy => localCacheKey[pk] = entityCopy;
}
if (entityCopy === undefined) {
// undefined indicates we should suspense (perhaps failed validation)
found = false;
deleted = true;
} else {
[localCacheKey[pk], found, deleted] = schema.denormalize(entityCopy, unvisit);
}
return [found, deleted];
}
// TODO(breaking): remove once unused
/* istanbul ignore next */
function withTrackedEntities(unvisit) {
// every time we nest, we want to unwrap back to the top.
// this is due to only needed the next level of nested entities for lookup
const originalUnvisit = unvisit.og || unvisit;
const wrappedUnvisit = (input, schema) => originalUnvisit(input, schema);
wrappedUnvisit.og = unvisit;
return wrappedUnvisit;
}
const getUnvisit = (getEntity, cache) => {
function unvisit(input, schema) {
if (!schema) return [input, true, false];
// null is considered intentional, thus always 'found' as true
if (input === null) {
return [input, true, false];
}
const hasDenormalize = typeof schema.denormalize === 'function';
// deserialize fields (like Date)
if (!hasDenormalize && typeof schema === 'function') {
if (input instanceof schema) return [input, true, false];
// field deserialization should never count against 'found' (whether to used inferred results)
if (input === undefined) return [input, true, false];
return [new schema(input), true, false];
}
if (input === undefined) {
return [input, false, false];
}
if (!hasDenormalize && typeof schema === 'object') {
const method = Array.isArray(schema) ? denormalize$3 : denormalize$2;
return method(schema, input, unvisit);
}
if (isEntity(schema)) {
return unvisitEntity(input, schema, unvisit, getEntity, cache);
}
if (hasDenormalize) {
return schema.denormalize(input, unvisit);
}
return [input, true, false];
}
return (input, schema) => {
// in the case where WeakMap cannot be used
// this test ensures null is properly excluded from WeakMap
const cachable = Object(input) === input && Object(schema) === schema;
return cache.getResults(input, cachable, () => unvisit(input, schema));
};
};
var getUnvisit$1 = getUnvisit;
/** Maps entity dependencies to a value (usually their denormalized form)

@@ -213,169 +339,111 @@ *

const unvisitEntity = (entityOrId, schema, unvisit, getEntity, getCache, localCache, cycleCache, dependencies, cycleIndex) => {
const entity = typeof entityOrId === 'object' ? entityOrId : getEntity({
pk: entityOrId,
key: schema.key
});
if (typeof entity === 'symbol' && entity.toString().includes('DELETED')) {
return [undefined, true, true];
// TODO: Change to this as breaking change once we only support newer entities
// also remove `(entity as symbol).toString().includes('DELETED')` and do this for all symbols
// return schema.denormalize(entity, unvisit);
const denormalize$1 = (input, schema, entities) => {
// undefined means don't do anything
if (schema === undefined) {
return [input, true, false];
}
if (input === undefined) {
return [undefined, false, false];
}
const getEntity = getEntities(entities);
const ret = getUnvisit$1(getEntity, new LocalCache())(input, schema);
return [ret[0], ret[1], ret[2]];
};
if (typeof entity !== 'object' || entity === null) {
return [entity, false, false];
class GlobalCache {
constructor(getEntity, entityCache, resultCache) {
this.dependencies = [];
this.cycleCache = {};
this.cycleIndex = -1;
this.localCache = {};
this._getEntity = getEntity;
this.getCache = getEntityCaches(entityCache);
this.resultCache = resultCache;
}
const pk =
// normalize must always place a string, because pk() return value is string | undefined
// therefore no need to check for numbers
typeof entityOrId === 'string' ? entityOrId : schema.pk(isImmutable(entity) ? entity.toJS() : entity);
// if we can't generate a working pk; this is hopeless so let's give them what's already there
// otherwise, even when we aren't doing a lookup we want to turn the entityOrId object into the
// expected class, and cache that class for referential equality. PK is used for global equality lookup.
if (pk === undefined || pk === '' || pk === 'undefined') {
return [entity, false, false];
}
const key = schema.key;
if (!(key in localCache)) {
localCache[key] = Object.create(null);
}
if (!(key in cycleCache)) {
cycleCache[key] = Object.create(null);
}
const localCacheKey = localCache[key];
const cycleCacheKey = cycleCache[key];
let found = true;
let deleted = false;
getEntity(pk, schema, entity, computeValue) {
const key = schema.key;
if (!(key in this.localCache)) {
this.localCache[key] = Object.create(null);
}
if (!(key in this.cycleCache)) {
this.cycleCache[key] = Object.create(null);
}
const localCacheKey = this.localCache[key];
const cycleCacheKey = this.cycleCache[key];
let found = true;
let deleted = false;
if (!localCacheKey[pk]) {
const globalCache = this.getCache(pk, schema);
const [cacheValue] = globalCache.get(entity, this._getEntity);
// TODO: what if this just returned the deps - then we don't need to store them
// local cache lookup first
if (!localCacheKey[pk]) {
const globalCache = getCache(pk, schema);
const [cacheValue] = globalCache.get(entity, getEntity);
// TODO: what if this just returned the deps - then we don't need to store them
if (cacheValue) {
localCacheKey[pk] = cacheValue.value[0];
// TODO: can we store the cache values instead of tracking *all* their sources?
// this is only used for setting results cache correctly. if we got this far we will def need to set as we would have already tried getting it
this.dependencies.push(...cacheValue.dependencies);
return cacheValue.value;
}
// if we don't find in denormalize cache then do full denormalize
else {
const trackingIndex = this.dependencies.length;
cycleCacheKey[pk] = trackingIndex;
this.dependencies.push({
entity,
path: {
key,
pk
}
});
if (cacheValue) {
localCacheKey[pk] = cacheValue.value[0];
// TODO: can we store the cache values instead of tracking *all* their sources?
// this is only used for setting results cache correctly. if we got this far we will def need to set as we would have already tried getting it
dependencies.push(...cacheValue.dependencies);
return cacheValue.value;
}
// if we don't find in denormalize cache then do full denormalize
else {
const trackingIndex = dependencies.length;
dependencies.push({
entity,
path: {
key,
pk
/** NON-GLOBAL_CACHE CODE */
[found, deleted] = computeValue(localCacheKey);
/** /END NON-GLOBAL_CACHE CODE */
delete cycleCacheKey[pk];
// if in cycle, use the start of the cycle to track all deps
// otherwise, we use our own trackingIndex
const localKey = this.dependencies.slice(this.cycleIndex === -1 ? trackingIndex : this.cycleIndex);
const cacheValue = {
dependencies: localKey,
value: [localCacheKey[pk], found, deleted]
};
globalCache.set(localKey, cacheValue);
// start of cycle - reset cycle detection
if (this.cycleIndex === trackingIndex) {
this.cycleIndex = -1;
}
});
let entityCopy;
if (schema.createIfValid) {
entityCopy = localCacheKey[pk] = isImmutable(entity) ? schema.createIfValid(entity.toObject()) : schema.createIfValid(entity);
// TODO(breaking): remove once old verions no longer supported
} else {
entityCopy = entity;
unvisit = withTrackedEntities(unvisit);
unvisit.setLocal = entityCopy => localCacheKey[pk] = entityCopy;
}
cycleCacheKey[pk] = trackingIndex;
if (entityCopy === undefined) {
// undefined indicates we should suspense (perhaps failed validation)
found = false;
deleted = true;
} else {
// cycle detected
if (pk in cycleCacheKey) {
this.cycleIndex = cycleCacheKey[pk];
} else {
[localCacheKey[pk], found, deleted] = schema.denormalize(entityCopy, unvisit);
// with no cycle, globalCacheEntry will have already been set
this.dependencies.push({
entity,
path: {
key,
pk
}
});
}
delete cycleCacheKey[pk];
// if in cycle, use the start of the cycle to track all deps
// otherwise, we use our own trackingIndex
const localKey = dependencies.slice(cycleIndex.i === -1 ? trackingIndex : cycleIndex.i);
const cacheValue = {
dependencies: localKey,
value: [localCacheKey[pk], found, deleted]
};
globalCache.set(localKey, cacheValue);
// start of cycle - reset cycle detection
if (cycleIndex.i === trackingIndex) {
cycleIndex.i = -1;
}
}
} else {
// cycle detected
if (pk in cycleCacheKey) {
cycleIndex.i = cycleCacheKey[pk];
} else {
// with no cycle, globalCacheEntry will have already been set
dependencies.push({
entity,
path: {
key,
pk
}
});
}
return [localCacheKey[pk], found, deleted];
}
return [localCacheKey[pk], found, deleted];
};
const getUnvisit = (entities, entityCache, resultCache) => {
const getEntity = getEntities(entities);
const getCache = getEntityCaches(entityCache);
const localCache = {};
const dependencies = [];
const cycleIndex = {
i: -1
};
const cycleCache = {};
function unvisit(input, schema) {
if (!schema) return [input, true, false];
// null is considered intentional, thus always 'found' as true
if (input === null) {
return [input, true, false];
}
const hasDenormalize = typeof schema.denormalize === 'function';
// deserialize fields (like Date)
if (!hasDenormalize && typeof schema === 'function') {
if (input instanceof schema) return [input, true, false];
// field deserialization should never count against 'found' (whether to used inferred results)
if (input === undefined) return [input, true, false];
return [new schema(input), true, false];
}
if (input === undefined) {
return [input, false, false];
}
if (!hasDenormalize && typeof schema === 'object') {
const method = Array.isArray(schema) ? denormalize$2 : denormalize$1;
return method(schema, input, unvisit);
}
if (isEntity(schema)) {
return unvisitEntity(input, schema, unvisit, getEntity, getCache, localCache, cycleCache, dependencies, cycleIndex);
}
if (hasDenormalize) {
return schema.denormalize(input, unvisit);
}
return [input, true, false];
}
return (input, schema) => {
// in the case where WeakMap cannot be used
// this test ensures null is properly excluded from WeakMap
const cachable = Object(input) === input && Object(schema) === schema;
getResults(input, cachable, computeValue) {
if (!cachable) {
const ret = unvisit(input, schema);
const ret = computeValue();
// this is faster than spread
// https://www.measurethat.net/Benchmarks/Show/23636/0/spread-with-tuples
return [ret[0], ret[1], ret[2], depToPaths(dependencies)];
return [ret[0], ret[1], ret[2], this.paths()];
}
let [ret, entityPaths] = resultCache.get(input, getEntity);
let [ret, entityPaths] = this.resultCache.get(input, this._getEntity);
if (ret === undefined) {
ret = unvisit(input, schema);
ret = computeValue();
// we want to do this before we add our 'input' entry
entityPaths = depToPaths(dependencies);
entityPaths = this.paths();
// for the first entry, `path` is ignored so empty members is fine
dependencies.unshift({
this.dependencies.unshift({
entity: input,

@@ -387,7 +455,10 @@ path: {

});
resultCache.set(dependencies, ret);
this.resultCache.set(this.dependencies, ret);
}
return [ret[0], ret[1], ret[2], entityPaths];
};
};
}
paths() {
return depToPaths(this.dependencies);
}
}
const getEntityCaches = entityCache => {

@@ -409,5 +480,6 @@ return (pk, schema) => {

};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
const denormalize = (input, schema, entities, entityCache = {}, resultCache = new WeakEntityMap()) => {
// undefined mean don't do anything
// undefined means don't do anything
if (schema === undefined) {

@@ -419,15 +491,6 @@ return [input, true, false, []];

}
return getUnvisit(entities, entityCache, resultCache)(input, schema);
const getEntity = getEntities(entities);
return getUnvisit$1(getEntity, new GlobalCache(getEntity, entityCache, resultCache))(input, schema);
};
// TODO(breaking): remove once unused
function withTrackedEntities(unvisit) {
// every time we nest, we want to unwrap back to the top.
// this is due to only needed the next level of nested entities for lookup
const originalUnvisit = unvisit.og || unvisit;
const wrappedUnvisit = (input, schema) => originalUnvisit(input, schema);
wrappedUnvisit.og = unvisit;
return wrappedUnvisit;
}
const DELETED = Symbol('ENTITY WAS DELETED');

@@ -647,2 +710,3 @@

};
const denormalizeCached = denormalize;

@@ -653,4 +717,6 @@ exports.DELETED = DELETED;

exports.denormalize = denormalize;
exports.denormalizeCached = denormalizeCached;
exports.denormalizeSimple = denormalize$1;
exports.inferResults = inferResults;
exports.isEntity = isEntity;
exports.normalize = normalize;

@@ -7,2 +7,27 @@ (function (global, factory) {

class LocalCache {
constructor() {
this.localCache = {};
}
getEntity(pk, schema, entity, computeValue) {
const key = schema.key;
if (!(key in this.localCache)) {
this.localCache[key] = Object.create(null);
}
const localCacheKey = this.localCache[key];
let found = true;
let deleted = false;
if (!localCacheKey[pk]) {
[found, deleted] = computeValue(localCacheKey);
}
return [localCacheKey[pk], found, deleted];
}
getResults(input, cachable, computeValue) {
const ret = computeValue();
// this is faster than spread
// https://www.measurethat.net/Benchmarks/Show/23636/0/spread-with-tuples
return [ret[0], ret[1], ret[2], []];
}
}
function isEntity(schema) {

@@ -32,3 +57,3 @@ return schema !== null && schema.pk !== undefined;

};
const denormalize$2 = (schema, input, unvisit) => {
const denormalize$3 = (schema, input, unvisit) => {
schema = validateSchema(schema);

@@ -104,3 +129,3 @@ return [input.map ? input.map(entityOrId => unvisit(entityOrId, schema)).filter(filterEmpty).map(([value]) => value) : input, true, false];

};
const denormalize$1 = (schema, input, unvisit) => {
const denormalize$2 = (schema, input, unvisit) => {
if (isImmutable(input)) {

@@ -134,2 +159,103 @@ return denormalizeImmutable(schema, input, unvisit);

const unvisitEntity = (entityOrId, schema, unvisit, getEntity, cache) => {
const entity = typeof entityOrId === 'object' ? entityOrId : getEntity({
pk: entityOrId,
key: schema.key
});
if (typeof entity === 'symbol' && entity.toString().includes('DELETED')) {
return [undefined, true, true];
// TODO: Change to this as breaking change once we only support newer entities
// also remove `(entity as symbol).toString().includes('DELETED')` and do this for all symbols
// return schema.denormalize(entity, unvisit);
}
if (typeof entity !== 'object' || entity === null) {
return [entity, false, false];
}
const pk =
// normalize must always place a string, because pk() return value is string | undefined
// therefore no need to check for numbers
typeof entityOrId === 'string' ? entityOrId : schema.pk(isImmutable(entity) ? entity.toJS() : entity);
// if we can't generate a working pk; this is hopeless so let's give them what's already there
// otherwise, even when we aren't doing a lookup we want to turn the entityOrId object into the
// expected class, and cache that class for referential equality. PK is used for global equality lookup.
if (pk === undefined || pk === '' || pk === 'undefined') {
return [entity, false, false];
}
// last function computes if it is not in any caches
return cache.getEntity(pk, schema, entity, localCacheKey => unvisitEntityObject(entity, schema, unvisit, pk, localCacheKey));
};
function unvisitEntityObject(entity, schema, unvisit, pk, localCacheKey) {
let entityCopy, found, deleted;
/* istanbul ignore else */
if (schema.createIfValid) {
entityCopy = localCacheKey[pk] = isImmutable(entity) ? schema.createIfValid(entity.toObject()) : schema.createIfValid(entity);
// TODO(breaking): remove once old verions no longer supported
} /* istanbul ignore next */else {
entityCopy = entity;
unvisit = withTrackedEntities(unvisit);
unvisit.setLocal = entityCopy => localCacheKey[pk] = entityCopy;
}
if (entityCopy === undefined) {
// undefined indicates we should suspense (perhaps failed validation)
found = false;
deleted = true;
} else {
[localCacheKey[pk], found, deleted] = schema.denormalize(entityCopy, unvisit);
}
return [found, deleted];
}
// TODO(breaking): remove once unused
/* istanbul ignore next */
function withTrackedEntities(unvisit) {
// every time we nest, we want to unwrap back to the top.
// this is due to only needed the next level of nested entities for lookup
const originalUnvisit = unvisit.og || unvisit;
const wrappedUnvisit = (input, schema) => originalUnvisit(input, schema);
wrappedUnvisit.og = unvisit;
return wrappedUnvisit;
}
const getUnvisit = (getEntity, cache) => {
function unvisit(input, schema) {
if (!schema) return [input, true, false];
// null is considered intentional, thus always 'found' as true
if (input === null) {
return [input, true, false];
}
const hasDenormalize = typeof schema.denormalize === 'function';
// deserialize fields (like Date)
if (!hasDenormalize && typeof schema === 'function') {
if (input instanceof schema) return [input, true, false];
// field deserialization should never count against 'found' (whether to used inferred results)
if (input === undefined) return [input, true, false];
return [new schema(input), true, false];
}
if (input === undefined) {
return [input, false, false];
}
if (!hasDenormalize && typeof schema === 'object') {
const method = Array.isArray(schema) ? denormalize$3 : denormalize$2;
return method(schema, input, unvisit);
}
if (isEntity(schema)) {
return unvisitEntity(input, schema, unvisit, getEntity, cache);
}
if (hasDenormalize) {
return schema.denormalize(input, unvisit);
}
return [input, true, false];
}
return (input, schema) => {
// in the case where WeakMap cannot be used
// this test ensures null is properly excluded from WeakMap
const cachable = Object(input) === input && Object(schema) === schema;
return cache.getResults(input, cachable, () => unvisit(input, schema));
};
};
var getUnvisit$1 = getUnvisit;
/** Maps entity dependencies to a value (usually their denormalized form)

@@ -211,169 +337,111 @@ *

const unvisitEntity = (entityOrId, schema, unvisit, getEntity, getCache, localCache, cycleCache, dependencies, cycleIndex) => {
const entity = typeof entityOrId === 'object' ? entityOrId : getEntity({
pk: entityOrId,
key: schema.key
});
if (typeof entity === 'symbol' && entity.toString().includes('DELETED')) {
return [undefined, true, true];
// TODO: Change to this as breaking change once we only support newer entities
// also remove `(entity as symbol).toString().includes('DELETED')` and do this for all symbols
// return schema.denormalize(entity, unvisit);
const denormalize$1 = (input, schema, entities) => {
// undefined means don't do anything
if (schema === undefined) {
return [input, true, false];
}
if (input === undefined) {
return [undefined, false, false];
}
const getEntity = getEntities(entities);
const ret = getUnvisit$1(getEntity, new LocalCache())(input, schema);
return [ret[0], ret[1], ret[2]];
};
if (typeof entity !== 'object' || entity === null) {
return [entity, false, false];
class GlobalCache {
constructor(getEntity, entityCache, resultCache) {
this.dependencies = [];
this.cycleCache = {};
this.cycleIndex = -1;
this.localCache = {};
this._getEntity = getEntity;
this.getCache = getEntityCaches(entityCache);
this.resultCache = resultCache;
}
const pk =
// normalize must always place a string, because pk() return value is string | undefined
// therefore no need to check for numbers
typeof entityOrId === 'string' ? entityOrId : schema.pk(isImmutable(entity) ? entity.toJS() : entity);
// if we can't generate a working pk; this is hopeless so let's give them what's already there
// otherwise, even when we aren't doing a lookup we want to turn the entityOrId object into the
// expected class, and cache that class for referential equality. PK is used for global equality lookup.
if (pk === undefined || pk === '' || pk === 'undefined') {
return [entity, false, false];
}
const key = schema.key;
if (!(key in localCache)) {
localCache[key] = Object.create(null);
}
if (!(key in cycleCache)) {
cycleCache[key] = Object.create(null);
}
const localCacheKey = localCache[key];
const cycleCacheKey = cycleCache[key];
let found = true;
let deleted = false;
getEntity(pk, schema, entity, computeValue) {
const key = schema.key;
if (!(key in this.localCache)) {
this.localCache[key] = Object.create(null);
}
if (!(key in this.cycleCache)) {
this.cycleCache[key] = Object.create(null);
}
const localCacheKey = this.localCache[key];
const cycleCacheKey = this.cycleCache[key];
let found = true;
let deleted = false;
if (!localCacheKey[pk]) {
const globalCache = this.getCache(pk, schema);
const [cacheValue] = globalCache.get(entity, this._getEntity);
// TODO: what if this just returned the deps - then we don't need to store them
// local cache lookup first
if (!localCacheKey[pk]) {
const globalCache = getCache(pk, schema);
const [cacheValue] = globalCache.get(entity, getEntity);
// TODO: what if this just returned the deps - then we don't need to store them
if (cacheValue) {
localCacheKey[pk] = cacheValue.value[0];
// TODO: can we store the cache values instead of tracking *all* their sources?
// this is only used for setting results cache correctly. if we got this far we will def need to set as we would have already tried getting it
this.dependencies.push(...cacheValue.dependencies);
return cacheValue.value;
}
// if we don't find in denormalize cache then do full denormalize
else {
const trackingIndex = this.dependencies.length;
cycleCacheKey[pk] = trackingIndex;
this.dependencies.push({
entity,
path: {
key,
pk
}
});
if (cacheValue) {
localCacheKey[pk] = cacheValue.value[0];
// TODO: can we store the cache values instead of tracking *all* their sources?
// this is only used for setting results cache correctly. if we got this far we will def need to set as we would have already tried getting it
dependencies.push(...cacheValue.dependencies);
return cacheValue.value;
}
// if we don't find in denormalize cache then do full denormalize
else {
const trackingIndex = dependencies.length;
dependencies.push({
entity,
path: {
key,
pk
/** NON-GLOBAL_CACHE CODE */
[found, deleted] = computeValue(localCacheKey);
/** /END NON-GLOBAL_CACHE CODE */
delete cycleCacheKey[pk];
// if in cycle, use the start of the cycle to track all deps
// otherwise, we use our own trackingIndex
const localKey = this.dependencies.slice(this.cycleIndex === -1 ? trackingIndex : this.cycleIndex);
const cacheValue = {
dependencies: localKey,
value: [localCacheKey[pk], found, deleted]
};
globalCache.set(localKey, cacheValue);
// start of cycle - reset cycle detection
if (this.cycleIndex === trackingIndex) {
this.cycleIndex = -1;
}
});
let entityCopy;
if (schema.createIfValid) {
entityCopy = localCacheKey[pk] = isImmutable(entity) ? schema.createIfValid(entity.toObject()) : schema.createIfValid(entity);
// TODO(breaking): remove once old verions no longer supported
} else {
entityCopy = entity;
unvisit = withTrackedEntities(unvisit);
unvisit.setLocal = entityCopy => localCacheKey[pk] = entityCopy;
}
cycleCacheKey[pk] = trackingIndex;
if (entityCopy === undefined) {
// undefined indicates we should suspense (perhaps failed validation)
found = false;
deleted = true;
} else {
// cycle detected
if (pk in cycleCacheKey) {
this.cycleIndex = cycleCacheKey[pk];
} else {
[localCacheKey[pk], found, deleted] = schema.denormalize(entityCopy, unvisit);
// with no cycle, globalCacheEntry will have already been set
this.dependencies.push({
entity,
path: {
key,
pk
}
});
}
delete cycleCacheKey[pk];
// if in cycle, use the start of the cycle to track all deps
// otherwise, we use our own trackingIndex
const localKey = dependencies.slice(cycleIndex.i === -1 ? trackingIndex : cycleIndex.i);
const cacheValue = {
dependencies: localKey,
value: [localCacheKey[pk], found, deleted]
};
globalCache.set(localKey, cacheValue);
// start of cycle - reset cycle detection
if (cycleIndex.i === trackingIndex) {
cycleIndex.i = -1;
}
}
} else {
// cycle detected
if (pk in cycleCacheKey) {
cycleIndex.i = cycleCacheKey[pk];
} else {
// with no cycle, globalCacheEntry will have already been set
dependencies.push({
entity,
path: {
key,
pk
}
});
}
return [localCacheKey[pk], found, deleted];
}
return [localCacheKey[pk], found, deleted];
};
const getUnvisit = (entities, entityCache, resultCache) => {
const getEntity = getEntities(entities);
const getCache = getEntityCaches(entityCache);
const localCache = {};
const dependencies = [];
const cycleIndex = {
i: -1
};
const cycleCache = {};
function unvisit(input, schema) {
if (!schema) return [input, true, false];
// null is considered intentional, thus always 'found' as true
if (input === null) {
return [input, true, false];
}
const hasDenormalize = typeof schema.denormalize === 'function';
// deserialize fields (like Date)
if (!hasDenormalize && typeof schema === 'function') {
if (input instanceof schema) return [input, true, false];
// field deserialization should never count against 'found' (whether to used inferred results)
if (input === undefined) return [input, true, false];
return [new schema(input), true, false];
}
if (input === undefined) {
return [input, false, false];
}
if (!hasDenormalize && typeof schema === 'object') {
const method = Array.isArray(schema) ? denormalize$2 : denormalize$1;
return method(schema, input, unvisit);
}
if (isEntity(schema)) {
return unvisitEntity(input, schema, unvisit, getEntity, getCache, localCache, cycleCache, dependencies, cycleIndex);
}
if (hasDenormalize) {
return schema.denormalize(input, unvisit);
}
return [input, true, false];
}
return (input, schema) => {
// in the case where WeakMap cannot be used
// this test ensures null is properly excluded from WeakMap
const cachable = Object(input) === input && Object(schema) === schema;
getResults(input, cachable, computeValue) {
if (!cachable) {
const ret = unvisit(input, schema);
const ret = computeValue();
// this is faster than spread
// https://www.measurethat.net/Benchmarks/Show/23636/0/spread-with-tuples
return [ret[0], ret[1], ret[2], depToPaths(dependencies)];
return [ret[0], ret[1], ret[2], this.paths()];
}
let [ret, entityPaths] = resultCache.get(input, getEntity);
let [ret, entityPaths] = this.resultCache.get(input, this._getEntity);
if (ret === undefined) {
ret = unvisit(input, schema);
ret = computeValue();
// we want to do this before we add our 'input' entry
entityPaths = depToPaths(dependencies);
entityPaths = this.paths();
// for the first entry, `path` is ignored so empty members is fine
dependencies.unshift({
this.dependencies.unshift({
entity: input,

@@ -385,7 +453,10 @@ path: {

});
resultCache.set(dependencies, ret);
this.resultCache.set(this.dependencies, ret);
}
return [ret[0], ret[1], ret[2], entityPaths];
};
};
}
paths() {
return depToPaths(this.dependencies);
}
}
const getEntityCaches = entityCache => {

@@ -407,5 +478,6 @@ return (pk, schema) => {

};
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
const denormalize = (input, schema, entities, entityCache = {}, resultCache = new WeakEntityMap()) => {
// undefined mean don't do anything
// undefined means don't do anything
if (schema === undefined) {

@@ -417,15 +489,6 @@ return [input, true, false, []];

}
return getUnvisit(entities, entityCache, resultCache)(input, schema);
const getEntity = getEntities(entities);
return getUnvisit$1(getEntity, new GlobalCache(getEntity, entityCache, resultCache))(input, schema);
};
// TODO(breaking): remove once unused
function withTrackedEntities(unvisit) {
// every time we nest, we want to unwrap back to the top.
// this is due to only needed the next level of nested entities for lookup
const originalUnvisit = unvisit.og || unvisit;
const wrappedUnvisit = (input, schema) => originalUnvisit(input, schema);
wrappedUnvisit.og = unvisit;
return wrappedUnvisit;
}
const DELETED = Symbol('ENTITY WAS DELETED');

@@ -638,2 +701,3 @@

};
const denormalizeCached = denormalize;

@@ -644,2 +708,4 @@ exports.DELETED = DELETED;

exports.denormalize = denormalize;
exports.denormalizeCached = denormalizeCached;
exports.denormalizeSimple = denormalize$1;
exports.inferResults = inferResults;

@@ -646,0 +712,0 @@ exports.isEntity = isEntity;

Object.hasOwn = Object.hasOwn || /* istanbul ignore next */function hasOwn(it, key) {
return Object.prototype.hasOwnProperty.call(it, key);
};
import { denormalize } from './denormalize.js';
import { denormalize as denormalizeSimple } from './denormalize/denormalize.js';
import { denormalize } from './denormalize/denormalizeCached.js';
import { isEntity } from './isEntity.js';

@@ -14,3 +15,4 @@ import { normalize } from './normalize.js';

export * from './normal.js';
export { denormalize, normalize, isEntity, WeakEntityMap };
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJPYmplY3QiLCJoYXNPd24iLCJpdCIsImtleSIsInByb3RvdHlwZSIsImhhc093blByb3BlcnR5IiwiY2FsbCIsImRlbm9ybWFsaXplIiwiaXNFbnRpdHkiLCJub3JtYWxpemUiLCJXZWFrRW50aXR5TWFwIiwiZGVmYXVsdCIsImluZmVyUmVzdWx0cyIsIkRFTEVURUQiXSwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwic291cmNlc0NvbnRlbnQiOlsiT2JqZWN0Lmhhc093biA9XG4gIE9iamVjdC5oYXNPd24gfHxcbiAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi8gZnVuY3Rpb24gaGFzT3duKGl0LCBrZXkpIHtcbiAgICByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGl0LCBrZXkpO1xuICB9O1xuaW1wb3J0IHsgZGVub3JtYWxpemUgfSBmcm9tICcuL2Rlbm9ybWFsaXplLmpzJztcbmltcG9ydCB7IGlzRW50aXR5IH0gZnJvbSAnLi9pc0VudGl0eS5qcyc7XG5pbXBvcnQgeyBub3JtYWxpemUgfSBmcm9tICcuL25vcm1hbGl6ZS5qcyc7XG5pbXBvcnQgV2Vha0VudGl0eU1hcCBmcm9tICcuL1dlYWtFbnRpdHlNYXAuanMnO1xuZXhwb3J0IHsgZGVmYXVsdCBhcyBpbmZlclJlc3VsdHMgfSBmcm9tICcuL2luZmVyUmVzdWx0cy5qcyc7XG5leHBvcnQgeyBERUxFVEVEIH0gZnJvbSAnLi9zcGVjaWFsLmpzJztcblxuZXhwb3J0IHR5cGUge1xuICBBYnN0cmFjdEluc3RhbmNlVHlwZSxcbiAgTm9ybWFsaXplUmV0dXJuVHlwZSxcbiAgTm9ybWFsaXplZFNjaGVtYSxcbiAgRGVub3JtYWxpemVSZXR1cm5UeXBlLFxuICBEZW5vcm1hbGl6ZUNhY2hlLFxuICBQYXRoLFxufSBmcm9tICcuL3R5cGVzLmpzJztcbmV4cG9ydCAqIGZyb20gJy4vZW5kcG9pbnQvdHlwZXMuanMnO1xuZXhwb3J0ICogZnJvbSAnLi9pbnRlcmZhY2UuanMnO1xuZXhwb3J0ICogZnJvbSAnLi9FeHBpcnkuanMnO1xuZXhwb3J0ICogZnJvbSAnLi9ub3JtYWwuanMnO1xuXG5leHBvcnQgeyBkZW5vcm1hbGl6ZSwgbm9ybWFsaXplLCBpc0VudGl0eSwgV2Vha0VudGl0eU1hcCB9O1xuIl0sIm1hcHBpbmdzIjoiQUFBQUEsTUFBTSxDQUFDQyxNQUFNLEdBQ1hELE1BQU0sQ0FBQ0MsTUFBTSxJQUNiLDBCQUEyQixTQUFTQSxNQUFNQSxDQUFDQyxFQUFFLEVBQUVDLEdBQUcsRUFBRTtFQUNsRCxPQUFPSCxNQUFNLENBQUNJLFNBQVMsQ0FBQ0MsY0FBYyxDQUFDQyxJQUFJLENBQUNKLEVBQUUsRUFBRUMsR0FBRyxDQUFDO0FBQ3RELENBQUM7QUFDSCxTQUFTSSxXQUFXLFFBQVEsa0JBQWtCO0FBQzlDLFNBQVNDLFFBQVEsUUFBUSxlQUFlO0FBQ3hDLFNBQVNDLFNBQVMsUUFBUSxnQkFBZ0I7QUFDMUMsT0FBT0MsYUFBYSxNQUFNLG9CQUFvQjtBQUM5QyxTQUFTQyxPQUFPLElBQUlDLFlBQVksUUFBUSxtQkFBbUI7QUFDM0QsU0FBU0MsT0FBTyxRQUFRLGNBQWM7QUFVdEMsY0FBYyxxQkFBcUI7QUFDbkMsY0FBYyxnQkFBZ0I7QUFDOUIsY0FBYyxhQUFhO0FBQzNCLGNBQWMsYUFBYTtBQUUzQixTQUFTTixXQUFXLEVBQUVFLFNBQVMsRUFBRUQsUUFBUSxFQUFFRSxhQUFhIn0=
export const denormalizeCached = denormalize;
export { denormalize, denormalizeSimple, normalize, isEntity, WeakEntityMap };
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJPYmplY3QiLCJoYXNPd24iLCJpdCIsImtleSIsInByb3RvdHlwZSIsImhhc093blByb3BlcnR5IiwiY2FsbCIsImRlbm9ybWFsaXplIiwiZGVub3JtYWxpemVTaW1wbGUiLCJpc0VudGl0eSIsIm5vcm1hbGl6ZSIsIldlYWtFbnRpdHlNYXAiLCJkZWZhdWx0IiwiaW5mZXJSZXN1bHRzIiwiREVMRVRFRCIsImRlbm9ybWFsaXplQ2FjaGVkIl0sInNvdXJjZXMiOlsiLi4vc3JjL2luZGV4LnRzIl0sInNvdXJjZXNDb250ZW50IjpbIk9iamVjdC5oYXNPd24gPVxuICBPYmplY3QuaGFzT3duIHx8XG4gIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovIGZ1bmN0aW9uIGhhc093bihpdCwga2V5KSB7XG4gICAgcmV0dXJuIE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChpdCwga2V5KTtcbiAgfTtcbmltcG9ydCB7IGRlbm9ybWFsaXplIGFzIGRlbm9ybWFsaXplU2ltcGxlIH0gZnJvbSAnLi9kZW5vcm1hbGl6ZS9kZW5vcm1hbGl6ZS5qcyc7XG5pbXBvcnQgeyBkZW5vcm1hbGl6ZSB9IGZyb20gJy4vZGVub3JtYWxpemUvZGVub3JtYWxpemVDYWNoZWQuanMnO1xuaW1wb3J0IHsgaXNFbnRpdHkgfSBmcm9tICcuL2lzRW50aXR5LmpzJztcbmltcG9ydCB7IG5vcm1hbGl6ZSB9IGZyb20gJy4vbm9ybWFsaXplLmpzJztcbmltcG9ydCBXZWFrRW50aXR5TWFwIGZyb20gJy4vV2Vha0VudGl0eU1hcC5qcyc7XG5leHBvcnQgeyBkZWZhdWx0IGFzIGluZmVyUmVzdWx0cyB9IGZyb20gJy4vaW5mZXJSZXN1bHRzLmpzJztcbmV4cG9ydCB7IERFTEVURUQgfSBmcm9tICcuL3NwZWNpYWwuanMnO1xuXG5leHBvcnQgdHlwZSB7XG4gIEFic3RyYWN0SW5zdGFuY2VUeXBlLFxuICBOb3JtYWxpemVSZXR1cm5UeXBlLFxuICBOb3JtYWxpemVkU2NoZW1hLFxuICBEZW5vcm1hbGl6ZVJldHVyblR5cGUsXG4gIERlbm9ybWFsaXplQ2FjaGUsXG4gIFBhdGgsXG59IGZyb20gJy4vdHlwZXMuanMnO1xuZXhwb3J0ICogZnJvbSAnLi9lbmRwb2ludC90eXBlcy5qcyc7XG5leHBvcnQgKiBmcm9tICcuL2ludGVyZmFjZS5qcyc7XG5leHBvcnQgKiBmcm9tICcuL0V4cGlyeS5qcyc7XG5leHBvcnQgKiBmcm9tICcuL25vcm1hbC5qcyc7XG5cbmV4cG9ydCBjb25zdCBkZW5vcm1hbGl6ZUNhY2hlZCA9IGRlbm9ybWFsaXplO1xuZXhwb3J0IHsgZGVub3JtYWxpemUsIGRlbm9ybWFsaXplU2ltcGxlLCBub3JtYWxpemUsIGlzRW50aXR5LCBXZWFrRW50aXR5TWFwIH07XG4iXSwibWFwcGluZ3MiOiJBQUFBQSxNQUFNLENBQUNDLE1BQU0sR0FDWEQsTUFBTSxDQUFDQyxNQUFNLElBQ2IsMEJBQTJCLFNBQVNBLE1BQU1BLENBQUNDLEVBQUUsRUFBRUMsR0FBRyxFQUFFO0VBQ2xELE9BQU9ILE1BQU0sQ0FBQ0ksU0FBUyxDQUFDQyxjQUFjLENBQUNDLElBQUksQ0FBQ0osRUFBRSxFQUFFQyxHQUFHLENBQUM7QUFDdEQsQ0FBQztBQUNILFNBQVNJLFdBQVcsSUFBSUMsaUJBQWlCLFFBQVEsOEJBQThCO0FBQy9FLFNBQVNELFdBQVcsUUFBUSxvQ0FBb0M7QUFDaEUsU0FBU0UsUUFBUSxRQUFRLGVBQWU7QUFDeEMsU0FBU0MsU0FBUyxRQUFRLGdCQUFnQjtBQUMxQyxPQUFPQyxhQUFhLE1BQU0sb0JBQW9CO0FBQzlDLFNBQVNDLE9BQU8sSUFBSUMsWUFBWSxRQUFRLG1CQUFtQjtBQUMzRCxTQUFTQyxPQUFPLFFBQVEsY0FBYztBQVV0QyxjQUFjLHFCQUFxQjtBQUNuQyxjQUFjLGdCQUFnQjtBQUM5QixjQUFjLGFBQWE7QUFDM0IsY0FBYyxhQUFhO0FBRTNCLE9BQU8sTUFBTUMsaUJBQWlCLEdBQUdSLFdBQVc7QUFDNUMsU0FBU0EsV0FBVyxFQUFFQyxpQkFBaUIsRUFBRUUsU0FBUyxFQUFFRCxRQUFRLEVBQUVFLGFBQWEifQ==

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

import { denormalize } from './denormalize.js';
import { denormalize as denormalizeSimple } from './denormalize/denormalize.js';
import { denormalize } from './denormalize/denormalizeCached.js';
import { isEntity } from './isEntity.js';

@@ -12,3 +13,8 @@ import { normalize } from './normalize.js';

export * from './normal.js';
export { denormalize, normalize, isEntity, WeakEntityMap };
export declare const denormalizeCached: <S extends import("./interface.js").Schema>(input: unknown, schema: S | undefined, entities: any, entityCache?: {
[key: string]: {
[pk: string]: WeakMap<import("./interface.js").EntityInterface<any>, WeakEntityMap<object, any>>;
};
}, resultCache?: WeakEntityMap<object, any>) => [denormalized: import("./types.js").Denormalize<S>, found: true, deleted: false, entityPaths: import("./types.js").Path[]] | [denormalized: import("./types.js").DenormalizeNullable<S>, found: boolean, deleted: true, entityPaths: import("./types.js").Path[]] | [denormalized: import("./types.js").DenormalizeNullable<S>, found: false, deleted: boolean, entityPaths: import("./types.js").Path[]];
export { denormalize, denormalizeSimple, normalize, isEntity, WeakEntityMap };
//# sourceMappingURL=index.d.ts.map
Object.hasOwn = Object.hasOwn || /* istanbul ignore next */function hasOwn(it, key) {
return Object.prototype.hasOwnProperty.call(it, key);
};
import { denormalize } from './denormalize.js';
import { denormalize as denormalizeSimple } from './denormalize/denormalize.js';
import { denormalize } from './denormalize/denormalizeCached.js';
import { isEntity } from './isEntity.js';

@@ -14,3 +15,4 @@ import { normalize } from './normalize.js';

export * from './normal.js';
export { denormalize, normalize, isEntity, WeakEntityMap };
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJPYmplY3QiLCJoYXNPd24iLCJpdCIsImtleSIsInByb3RvdHlwZSIsImhhc093blByb3BlcnR5IiwiY2FsbCIsImRlbm9ybWFsaXplIiwiaXNFbnRpdHkiLCJub3JtYWxpemUiLCJXZWFrRW50aXR5TWFwIiwiZGVmYXVsdCIsImluZmVyUmVzdWx0cyIsIkRFTEVURUQiXSwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwic291cmNlc0NvbnRlbnQiOlsiT2JqZWN0Lmhhc093biA9XG4gIE9iamVjdC5oYXNPd24gfHxcbiAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi8gZnVuY3Rpb24gaGFzT3duKGl0LCBrZXkpIHtcbiAgICByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGl0LCBrZXkpO1xuICB9O1xuaW1wb3J0IHsgZGVub3JtYWxpemUgfSBmcm9tICcuL2Rlbm9ybWFsaXplLmpzJztcbmltcG9ydCB7IGlzRW50aXR5IH0gZnJvbSAnLi9pc0VudGl0eS5qcyc7XG5pbXBvcnQgeyBub3JtYWxpemUgfSBmcm9tICcuL25vcm1hbGl6ZS5qcyc7XG5pbXBvcnQgV2Vha0VudGl0eU1hcCBmcm9tICcuL1dlYWtFbnRpdHlNYXAuanMnO1xuZXhwb3J0IHsgZGVmYXVsdCBhcyBpbmZlclJlc3VsdHMgfSBmcm9tICcuL2luZmVyUmVzdWx0cy5qcyc7XG5leHBvcnQgeyBERUxFVEVEIH0gZnJvbSAnLi9zcGVjaWFsLmpzJztcblxuZXhwb3J0IHR5cGUge1xuICBBYnN0cmFjdEluc3RhbmNlVHlwZSxcbiAgTm9ybWFsaXplUmV0dXJuVHlwZSxcbiAgTm9ybWFsaXplZFNjaGVtYSxcbiAgRGVub3JtYWxpemVSZXR1cm5UeXBlLFxuICBEZW5vcm1hbGl6ZUNhY2hlLFxuICBQYXRoLFxufSBmcm9tICcuL3R5cGVzLmpzJztcbmV4cG9ydCAqIGZyb20gJy4vZW5kcG9pbnQvdHlwZXMuanMnO1xuZXhwb3J0ICogZnJvbSAnLi9pbnRlcmZhY2UuanMnO1xuZXhwb3J0ICogZnJvbSAnLi9FeHBpcnkuanMnO1xuZXhwb3J0ICogZnJvbSAnLi9ub3JtYWwuanMnO1xuXG5leHBvcnQgeyBkZW5vcm1hbGl6ZSwgbm9ybWFsaXplLCBpc0VudGl0eSwgV2Vha0VudGl0eU1hcCB9O1xuIl0sIm1hcHBpbmdzIjoiQUFBQUEsTUFBTSxDQUFDQyxNQUFNLEdBQ1hELE1BQU0sQ0FBQ0MsTUFBTSxJQUNiLDBCQUEyQixTQUFTQSxNQUFNQSxDQUFDQyxFQUFFLEVBQUVDLEdBQUcsRUFBRTtFQUNsRCxPQUFPSCxNQUFNLENBQUNJLFNBQVMsQ0FBQ0MsY0FBYyxDQUFDQyxJQUFJLENBQUNKLEVBQUUsRUFBRUMsR0FBRyxDQUFDO0FBQ3RELENBQUM7QUFDSCxTQUFTSSxXQUFXLFFBQVEsa0JBQWtCO0FBQzlDLFNBQVNDLFFBQVEsUUFBUSxlQUFlO0FBQ3hDLFNBQVNDLFNBQVMsUUFBUSxnQkFBZ0I7QUFDMUMsT0FBT0MsYUFBYSxNQUFNLG9CQUFvQjtBQUM5QyxTQUFTQyxPQUFPLElBQUlDLFlBQVksUUFBUSxtQkFBbUI7QUFDM0QsU0FBU0MsT0FBTyxRQUFRLGNBQWM7QUFVdEMsY0FBYyxxQkFBcUI7QUFDbkMsY0FBYyxnQkFBZ0I7QUFDOUIsY0FBYyxhQUFhO0FBQzNCLGNBQWMsYUFBYTtBQUUzQixTQUFTTixXQUFXLEVBQUVFLFNBQVMsRUFBRUQsUUFBUSxFQUFFRSxhQUFhIn0=
export const denormalizeCached = denormalize;
export { denormalize, denormalizeSimple, normalize, isEntity, WeakEntityMap };
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJPYmplY3QiLCJoYXNPd24iLCJpdCIsImtleSIsInByb3RvdHlwZSIsImhhc093blByb3BlcnR5IiwiY2FsbCIsImRlbm9ybWFsaXplIiwiZGVub3JtYWxpemVTaW1wbGUiLCJpc0VudGl0eSIsIm5vcm1hbGl6ZSIsIldlYWtFbnRpdHlNYXAiLCJkZWZhdWx0IiwiaW5mZXJSZXN1bHRzIiwiREVMRVRFRCIsImRlbm9ybWFsaXplQ2FjaGVkIl0sInNvdXJjZXMiOlsiLi4vc3JjL2luZGV4LnRzIl0sInNvdXJjZXNDb250ZW50IjpbIk9iamVjdC5oYXNPd24gPVxuICBPYmplY3QuaGFzT3duIHx8XG4gIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovIGZ1bmN0aW9uIGhhc093bihpdCwga2V5KSB7XG4gICAgcmV0dXJuIE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChpdCwga2V5KTtcbiAgfTtcbmltcG9ydCB7IGRlbm9ybWFsaXplIGFzIGRlbm9ybWFsaXplU2ltcGxlIH0gZnJvbSAnLi9kZW5vcm1hbGl6ZS9kZW5vcm1hbGl6ZS5qcyc7XG5pbXBvcnQgeyBkZW5vcm1hbGl6ZSB9IGZyb20gJy4vZGVub3JtYWxpemUvZGVub3JtYWxpemVDYWNoZWQuanMnO1xuaW1wb3J0IHsgaXNFbnRpdHkgfSBmcm9tICcuL2lzRW50aXR5LmpzJztcbmltcG9ydCB7IG5vcm1hbGl6ZSB9IGZyb20gJy4vbm9ybWFsaXplLmpzJztcbmltcG9ydCBXZWFrRW50aXR5TWFwIGZyb20gJy4vV2Vha0VudGl0eU1hcC5qcyc7XG5leHBvcnQgeyBkZWZhdWx0IGFzIGluZmVyUmVzdWx0cyB9IGZyb20gJy4vaW5mZXJSZXN1bHRzLmpzJztcbmV4cG9ydCB7IERFTEVURUQgfSBmcm9tICcuL3NwZWNpYWwuanMnO1xuXG5leHBvcnQgdHlwZSB7XG4gIEFic3RyYWN0SW5zdGFuY2VUeXBlLFxuICBOb3JtYWxpemVSZXR1cm5UeXBlLFxuICBOb3JtYWxpemVkU2NoZW1hLFxuICBEZW5vcm1hbGl6ZVJldHVyblR5cGUsXG4gIERlbm9ybWFsaXplQ2FjaGUsXG4gIFBhdGgsXG59IGZyb20gJy4vdHlwZXMuanMnO1xuZXhwb3J0ICogZnJvbSAnLi9lbmRwb2ludC90eXBlcy5qcyc7XG5leHBvcnQgKiBmcm9tICcuL2ludGVyZmFjZS5qcyc7XG5leHBvcnQgKiBmcm9tICcuL0V4cGlyeS5qcyc7XG5leHBvcnQgKiBmcm9tICcuL25vcm1hbC5qcyc7XG5cbmV4cG9ydCBjb25zdCBkZW5vcm1hbGl6ZUNhY2hlZCA9IGRlbm9ybWFsaXplO1xuZXhwb3J0IHsgZGVub3JtYWxpemUsIGRlbm9ybWFsaXplU2ltcGxlLCBub3JtYWxpemUsIGlzRW50aXR5LCBXZWFrRW50aXR5TWFwIH07XG4iXSwibWFwcGluZ3MiOiJBQUFBQSxNQUFNLENBQUNDLE1BQU0sR0FDWEQsTUFBTSxDQUFDQyxNQUFNLElBQ2IsMEJBQTJCLFNBQVNBLE1BQU1BLENBQUNDLEVBQUUsRUFBRUMsR0FBRyxFQUFFO0VBQ2xELE9BQU9ILE1BQU0sQ0FBQ0ksU0FBUyxDQUFDQyxjQUFjLENBQUNDLElBQUksQ0FBQ0osRUFBRSxFQUFFQyxHQUFHLENBQUM7QUFDdEQsQ0FBQztBQUNILFNBQVNJLFdBQVcsSUFBSUMsaUJBQWlCLFFBQVEsOEJBQThCO0FBQy9FLFNBQVNELFdBQVcsUUFBUSxvQ0FBb0M7QUFDaEUsU0FBU0UsUUFBUSxRQUFRLGVBQWU7QUFDeEMsU0FBU0MsU0FBUyxRQUFRLGdCQUFnQjtBQUMxQyxPQUFPQyxhQUFhLE1BQU0sb0JBQW9CO0FBQzlDLFNBQVNDLE9BQU8sSUFBSUMsWUFBWSxRQUFRLG1CQUFtQjtBQUMzRCxTQUFTQyxPQUFPLFFBQVEsY0FBYztBQVV0QyxjQUFjLHFCQUFxQjtBQUNuQyxjQUFjLGdCQUFnQjtBQUM5QixjQUFjLGFBQWE7QUFDM0IsY0FBYyxhQUFhO0FBRTNCLE9BQU8sTUFBTUMsaUJBQWlCLEdBQUdSLFdBQVc7QUFDNUMsU0FBU0EsV0FBVyxFQUFFQyxpQkFBaUIsRUFBRUUsU0FBUyxFQUFFRCxRQUFRLEVBQUVFLGFBQWEifQ==
{
"name": "@rest-hooks/normalizr",
"version": "10.0.3",
"version": "10.1.0",
"description": "Normalizes and denormalizes JSON according to schema for Redux and Flux applications",

@@ -78,16 +78,12 @@ "homepage": "https://resthooks.io/docs/concepts/normalization",

"scripts": {
"build": "yarn run build:lib && yarn run build:legacy:lib && yarn run build:bundle",
"build:js:development": "BROWSERSLIST_ENV=legacy NODE_ENV=development rollup -c",
"build:js:production": "BROWSERSLIST_ENV=legacy NODE_ENV=production rollup -c",
"build:js:node": "BROWSERSLIST_ENV=node12 NODE_ENV=development rollup -c && echo '{\"type\":\"commonjs\"}' > dist/package.json",
"build:lib": "NODE_ENV=production BROWSERSLIST_ENV='2020' babel --root-mode upward src --out-dir lib --extensions '.ts,.tsx,.js' --ignore '**/__tests__/**' --ignore '**/*.d.ts'",
"build:legacy:lib": "NODE_ENV=production BROWSERSLIST_ENV='2018' babel --root-mode upward src --out-dir legacy --extensions '.ts,.tsx,.js' --ignore '**/__tests__/**' --ignore '**/*.d.ts'",
"build:bundle": "run-s build:js:\\*",
"build:clean": "rimraf lib ts3.4 legacy dist *.tsbuildinfo",
"build:legacy-types": "yarn run downlevel-dts lib ts3.4",
"lint": "yarn lint:cmd --fix",
"lint:ci": "yarn lint:cmd",
"lint:cmd": "eslint . --ext '.js,.json,.snap' --cache",
"precommit": "flow check && lint-staged",
"prepublishOnly": "npm run build"
"build": "run build:lib && run build:legacy:lib && run build:bundle",
"build:js:development": "BROWSERSLIST_ENV=legacy NODE_ENV=development yarn g:rollup",
"build:js:production": "BROWSERSLIST_ENV=legacy NODE_ENV=production yarn g:rollup",
"build:js:node": "BROWSERSLIST_ENV=node12 NODE_ENV=development yarn g:rollup && echo '{\"type\":\"commonjs\"}' > dist/package.json",
"build:lib": "NODE_ENV=production BROWSERSLIST_ENV='2020' yarn g:babel --out-dir lib",
"build:legacy:lib": "NODE_ENV=production BROWSERSLIST_ENV='2018' yarn g:babel --out-dir legacy",
"build:bundle": "yarn g:runs build:js:\\*",
"build:clean": "yarn g:clean",
"build:legacy-types": "yarn g:downtypes lib ts3.4",
"prepublishOnly": "run build"
},

@@ -101,21 +97,9 @@ "author": "Nathaniel Tucker",

"devDependencies": {
"@babel/cli": "7.21.0",
"@babel/core": "7.21.3",
"@types/babel__core": "^7",
"downlevel-dts": "^0.10.0",
"immutable": "4.2.2",
"npm-run-all": "^4.1.5",
"rollup": "2.79.1",
"rollup-plugin-babel": "^4.4.0",
"rollup-plugin-commonjs": "^10.1.0",
"rollup-plugin-filesize": "^9.1.2",
"rollup-plugin-json": "^4.0.0",
"rollup-plugin-node-resolve": "^5.2.0",
"rollup-plugin-replace": "^2.2.0",
"rollup-plugin-terser": "^7.0.2"
"@anansi/browserslist-config": "^1.4.2",
"@types/node": "^18.15.10",
"immutable": "4.2.2"
},
"dependencies": {
"@babel/runtime": "^7.17.0"
},
"gitHead": "c0248d68395248454f494f4cb8203ed7a5cdd94a"
}
}

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

import { denormalize } from './denormalize.js';
import { denormalize as denormalizeSimple } from './denormalize/denormalize.js';
import { denormalize } from './denormalize/denormalizeCached.js';
import { isEntity } from './isEntity.js';

@@ -12,3 +13,23 @@ import { normalize } from './normalize.js';

export * from './normal.js';
export { denormalize, normalize, isEntity, WeakEntityMap };
export declare const denormalizeCached: <S extends import("./interface.js").Schema>(input: unknown, schema: S | undefined, entities: any, entityCache?: {
[key: string]: {
[pk: string]: WeakMap<import("./interface.js").EntityInterface<any>, WeakEntityMap<object, any>>;
};
}, resultCache?: WeakEntityMap<object, any>) => [
/*denormalized*/ import("./types.js").Denormalize<S>,
/*found*/ true,
/*deleted*/ false,
/*entityPaths*/ import("./types.js").Path[]
] | [
/*denormalized*/ import("./types.js").DenormalizeNullable<S>,
/*found*/ boolean,
/*deleted*/ true,
/*entityPaths*/ import("./types.js").Path[]
] | [
/*denormalized*/ import("./types.js").DenormalizeNullable<S>,
/*found*/ false,
/*deleted*/ boolean,
/*entityPaths*/ import("./types.js").Path[]
];
export { denormalize, denormalizeSimple, normalize, isEntity, WeakEntityMap };
//# sourceMappingURL=index.d.ts.map

Sorry, the diff of this file is not supported yet

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