@rest-hooks/normalizr
Advanced tools
Comparing version 10.0.3 to 10.1.0
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
450780
3
135
5057