@rest-hooks/normalizr
Advanced tools
Comparing version 6.0.0-gamma.2 to 6.0.0-h.0
@@ -6,2 +6,28 @@ # Change Log | ||
## 6.0.0-h.0 (2020-07-13) | ||
* pkg: Bump babel runtime ([c6bf844](https://github.com/coinbase/rest-hooks/commit/c6bf844)) | ||
## 6.0.0-delta.0 (2020-07-08) | ||
* feat: Deletes and invalidates trigger suspense always (#360) ([96175ba](https://github.com/coinbase/rest-hooks/commit/96175ba)), closes [#360](https://github.com/coinbase/rest-hooks/issues/360) | ||
### BREAKING CHANGE | ||
* - denormalize has third boolean value to track deletion | ||
- deletes no long remove entities, but replace them with DELETE symbol (exported from normalizr) | ||
- schema of delete shape should be the `new schemas.Delete()` | ||
- useInvalidator()'s function calls will always suspend - even without invalidIfStale | ||
- deleted entities that are required by a useResource() will now cause it to suspend rather than throwing `404` | ||
- required entities missing from network response will now throw error in useResource() just like other unexpected deserializations | ||
- FetchShape type is now just 'read' | 'mutate'. No more 'delete'. (use schema.Delete()) | ||
## 6.0.0-gamma.2 (2020-06-13) | ||
@@ -8,0 +34,0 @@ |
import { Denormalize, DenormalizeNullable, Schema } from './types'; | ||
export declare const denormalize: <S extends Schema>(input: any, schema: S, entities: any) => [Denormalize<S>, true, Record<string, Record<string, any>>] | [DenormalizeNullable<S>, false, Record<string, Record<string, any>>]; | ||
export declare const denormalizeSimple: <S extends Schema>(input: any, schema: S, entities: any) => [Denormalize<S>, true] | [DenormalizeNullable<S>, false]; | ||
export declare const denormalize: <S extends Schema>(input: any, schema: S, entities: any) => [Denormalize<S>, true, false, Record<string, Record<string, any>>] | [DenormalizeNullable<S>, false, boolean, Record<string, Record<string, any>>] | [DenormalizeNullable<S>, boolean, true, Record<string, Record<string, any>>]; | ||
export declare const denormalizeSimple: <S extends Schema>(input: any, schema: S, entities: any) => [Denormalize<S>, true, false] | [DenormalizeNullable<S>, boolean, true] | [DenormalizeNullable<S>, false, boolean]; | ||
//# sourceMappingURL=denormalize.d.ts.map |
@@ -6,2 +6,9 @@ import SimpleRecord from './SimpleRecord'; | ||
export default abstract class Entity extends SimpleRecord { | ||
static toJSON(): { | ||
key: string; | ||
name: string; | ||
schema: { | ||
[k: string]: Schema; | ||
}; | ||
}; | ||
/** | ||
@@ -27,5 +34,5 @@ * A unique identifier for each Entity | ||
static normalize(input: any, parent: any, key: string | undefined, visit: (...args: any) => any, addEntity: (...args: any) => any, visitedEntities: Record<string, any>): any; | ||
static denormalize<T extends typeof SimpleRecord>(this: T, entity: AbstractInstanceType<T>, unvisit: schema.UnvisitFunction): [AbstractInstanceType<T>, boolean]; | ||
static denormalize<T extends typeof SimpleRecord>(this: T, entity: AbstractInstanceType<T>, unvisit: schema.UnvisitFunction): [AbstractInstanceType<T>, boolean, boolean]; | ||
} | ||
export declare function isEntity(schema: Schema | null): schema is typeof Entity; | ||
//# sourceMappingURL=Entity.d.ts.map |
@@ -6,4 +6,4 @@ import Entity from './Entity'; | ||
export default abstract class FlatEntity extends Entity { | ||
static denormalize<T extends typeof SimpleRecord>(this: T, entity: any, unvisit: schema.UnvisitFunction): [AbstractInstanceType<T>, boolean]; | ||
static denormalize<T extends typeof SimpleRecord>(this: T, entity: any, unvisit: schema.UnvisitFunction): [AbstractInstanceType<T>, boolean, boolean]; | ||
} | ||
//# sourceMappingURL=FlatEntity.d.ts.map |
@@ -6,2 +6,8 @@ import { AbstractInstanceType, Schema, NormalizedEntity } from '../types'; | ||
toString(): string; | ||
static toJSON(): { | ||
name: string; | ||
schema: { | ||
[k: string]: Schema; | ||
}; | ||
}; | ||
/** Defines nested entities */ | ||
@@ -27,3 +33,3 @@ static schema: { | ||
static normalize<T extends typeof SimpleRecord>(this: T, ...args: any[]): NormalizedEntity<T>; | ||
static denormalize<T extends typeof SimpleRecord>(this: T, input: any, unvisit: any): [AbstractInstanceType<T>, boolean]; | ||
static denormalize<T extends typeof SimpleRecord>(this: T, input: any, unvisit: any): [AbstractInstanceType<T>, boolean, boolean]; | ||
static asSchema<T extends typeof SimpleRecord>(this: T): T; | ||
@@ -30,0 +36,0 @@ } |
@@ -7,4 +7,5 @@ import { denormalize } from './denormalize'; | ||
export { default as FlatEntity } from './entities/FlatEntity'; | ||
export { DELETED } from './special'; | ||
export type { AbstractInstanceType, Schema, Normalize, NormalizeNullable, NormalizedIndex, NormalizeReturnType, NormalizedSchema, Denormalize, DenormalizeNullable, DenormalizeReturnType, } from './types'; | ||
export { denormalize, schema, normalize, SimpleRecord, Entity, isEntity }; | ||
//# sourceMappingURL=index.d.ts.map |
@@ -31,2 +31,3 @@ define(['exports'], function (exports) { 'use strict'; | ||
let found = true; | ||
let deleted = false; | ||
return [Object.keys(schema).reduce((object, key) => { | ||
@@ -36,3 +37,3 @@ // Immutable maps cast keys to strings on write so we need to ensure | ||
const stringKey = `${key}`; | ||
const [item, foundItem] = unvisit(object.get(stringKey), schema[stringKey]); | ||
const [item, foundItem, deletedItem] = unvisit(object.get(stringKey), schema[stringKey]); | ||
@@ -43,2 +44,6 @@ if (!foundItem) { | ||
if (deletedItem) { | ||
deleted = true; | ||
} | ||
if (object.has(stringKey)) { | ||
@@ -49,3 +54,3 @@ return object.set(stringKey, item); | ||
} | ||
}, input), found]; | ||
}, input), found, deleted]; | ||
} | ||
@@ -101,3 +106,3 @@ | ||
if (!this.isSingleSchema && !schemaKey) { | ||
return [value, true]; | ||
return [value, true, true]; | ||
} | ||
@@ -112,2 +117,4 @@ | ||
const DELETED = Symbol('ENTITY WAS DELETED'); | ||
const validateSchema = definition => { | ||
@@ -125,2 +132,4 @@ const isArray = Array.isArray(definition); | ||
const filterEmpty = ([, foundItem, deletedItem]) => foundItem && !deletedItem; | ||
const normalize = (schema, input, parent, key, visit, addEntity, visitedEntities) => { | ||
@@ -135,9 +144,10 @@ schema = validateSchema(schema); | ||
schema = validateSchema(schema); | ||
let deleted = false; | ||
let found = true; | ||
if (input === undefined && schema) { | ||
[, found] = unvisit(undefined, schema); | ||
[, found, deleted] = unvisit(undefined, schema); | ||
} | ||
return [input && input.map ? input.map(entityOrId => unvisit(entityOrId, schema)).filter(([, foundItem]) => foundItem).map(([value]) => value) : input, found]; | ||
return [input && input.map ? input.map(entityOrId => unvisit(entityOrId, schema)).filter(filterEmpty).map(([value]) => value) : input, found, deleted]; | ||
}; | ||
@@ -151,9 +161,10 @@ class ArraySchema extends PolymorphicSchema { | ||
denormalize(input, unvisit) { | ||
let deleted = false; | ||
let found = true; | ||
if (input === undefined && this.schema) { | ||
[, found] = unvisit(undefined, this.schema); | ||
[, found, deleted] = unvisit(undefined, this.schema); | ||
} | ||
return [input && input.map ? input.map(entityOrId => this.denormalizeValue(entityOrId, unvisit)).filter(([, foundItem]) => foundItem).map(([value]) => value) : input, found]; | ||
return [input && input.map ? input.map(entityOrId => this.denormalizeValue(entityOrId, unvisit)).filter(filterEmpty).map(([value]) => value) : input, found, deleted]; | ||
} | ||
@@ -186,4 +197,5 @@ | ||
let found = true; | ||
let deleted = false; | ||
Object.keys(schema).forEach(key => { | ||
const [item, foundItem] = unvisit(object[key], schema[key]); | ||
const [item, foundItem, deletedItem] = unvisit(object[key], schema[key]); | ||
@@ -194,2 +206,6 @@ if (object[key] !== undefined) { | ||
if (deletedItem) { | ||
deleted = true; | ||
} | ||
if (!foundItem) { | ||
@@ -199,3 +215,3 @@ found = false; | ||
}); | ||
return [object, found]; | ||
return [object, found, deleted]; | ||
}; | ||
@@ -236,2 +252,9 @@ class ObjectSchema { | ||
} | ||
static toJSON() { | ||
return { | ||
name: this.name, | ||
schema: this.schema | ||
}; | ||
} | ||
/** Defines nested entities */ | ||
@@ -308,5 +331,6 @@ | ||
}; | ||
let deleted = false; | ||
let found = true; | ||
Object.keys(this.schema).forEach(key => { | ||
const [item, foundItem] = unvisit(object[key], this.schema[key]); | ||
const [item, foundItem, deletedItem] = unvisit(object[key], this.schema[key]); | ||
@@ -322,5 +346,9 @@ if (object[key] !== undefined) { | ||
} | ||
if (deletedItem && !(key in instance && !instance[key])) { | ||
deleted = true; | ||
} | ||
}); // useDenormalized will memo based on entities, so creating a new object each time is fine | ||
return [this.fromJS(object), found]; | ||
return [this.fromJS(object), found, deleted]; | ||
} | ||
@@ -348,2 +376,7 @@ /* istanbul ignore next */ | ||
class Entity extends SimpleRecord { | ||
static toJSON() { | ||
return { ...super.toJSON(), | ||
key: this.key | ||
}; | ||
} | ||
/** | ||
@@ -356,2 +389,3 @@ * A unique identifier for each Entity | ||
/** Returns the globally unique identifier for the static Entity */ | ||
@@ -470,4 +504,4 @@ static get key() { | ||
if (isImmutable(entity)) { | ||
const [denormEntity, found] = denormalizeImmutable(this.schema, entity, unvisit); | ||
return [this.fromJS(denormEntity.toObject()), found]; | ||
const [denormEntity, found, deleted] = denormalizeImmutable(this.schema, entity, unvisit); | ||
return [this.fromJS(denormEntity.toObject()), found, deleted]; | ||
} // TODO: This creates unneeded memory pressure | ||
@@ -477,2 +511,3 @@ | ||
const instance = new this(); | ||
let deleted = false; | ||
let found = true; | ||
@@ -483,3 +518,3 @@ const denormEntity = entity; | ||
const input = this.hasDefined(entity, key) ? entity[key] : undefined; | ||
const [value, foundItem] = unvisit(input, schema); // members who default to falsy values are considered 'optional' | ||
const [value, foundItem, deletedItem] = unvisit(input, schema); // members who default to falsy values are considered 'optional' | ||
// if falsy value, and default is actually set then it is optional so pass through | ||
@@ -491,2 +526,6 @@ | ||
if (deletedItem && !(key in instance && !instance[key])) { | ||
deleted = true; | ||
} | ||
if (this.hasDefined(entity, key) && denormEntity[key] !== value) { | ||
@@ -496,7 +535,6 @@ denormEntity[key] = value; | ||
}); | ||
return [denormEntity, found]; | ||
return [denormEntity, found, deleted]; | ||
} | ||
} | ||
/* istanbul ignore next */ | ||
@@ -518,3 +556,3 @@ if (process.env.NODE_ENV !== 'production') { | ||
static denormalize(entity, unvisit) { | ||
return [entity, true]; | ||
return [entity, true, false]; | ||
} | ||
@@ -527,4 +565,8 @@ | ||
if (entity === DELETED) { | ||
return [undefined, true, true]; | ||
} | ||
if (typeof entity !== 'object' || entity === null) { | ||
return [entity, false]; | ||
return [entity, false, false]; | ||
} | ||
@@ -537,2 +579,3 @@ | ||
let found = true; | ||
let deleted = false; | ||
@@ -545,6 +588,6 @@ if (!cache[schema.key][id]) { | ||
cache[schema.key][id] = entityCopy; | ||
[cache[schema.key][id], found] = schema.denormalize(entityCopy, unvisit); | ||
[cache[schema.key][id], found, deleted] = schema.denormalize(entityCopy, unvisit); | ||
} | ||
return [cache[schema.key][id], found]; | ||
return [cache[schema.key][id], found, deleted]; | ||
}; | ||
@@ -556,8 +599,8 @@ | ||
return [function unvisit(input, schema) { | ||
if (!schema) return [input, true]; | ||
if (!schema) return [input, true, false]; | ||
if (!schema.denormalize || typeof schema.denormalize !== 'function') { | ||
if (typeof schema === 'function') { | ||
if (input instanceof schema) return [input, true]; | ||
return [new schema(input), true]; | ||
if (input instanceof schema) return [input, true, false]; | ||
return [new schema(input), true, false]; | ||
} else if (typeof schema === 'object') { | ||
@@ -571,3 +614,3 @@ const method = Array.isArray(schema) ? denormalize : denormalize$1; | ||
if (input === null) { | ||
return [input, true]; | ||
return [input, true, false]; | ||
} | ||
@@ -578,3 +621,3 @@ | ||
if (input === undefined) { | ||
return [input, false]; | ||
return [input, false, false]; | ||
} | ||
@@ -589,3 +632,3 @@ | ||
return [input, true]; | ||
return [input, true, false]; | ||
}, cache]; | ||
@@ -621,3 +664,3 @@ }; | ||
return [undefined, false, {}]; | ||
return [undefined, false, false, {}]; | ||
}; | ||
@@ -774,5 +817,6 @@ | ||
let found = true; | ||
let deleted = false; | ||
return [Object.keys(input).reduce((output, key) => { | ||
const entityOrId = input[key]; | ||
const [value, foundItem] = this.denormalizeValue(entityOrId, unvisit); | ||
const [value, foundItem, deletedItem] = this.denormalizeValue(entityOrId, unvisit); | ||
@@ -783,6 +827,11 @@ if (!foundItem) { | ||
if (deletedItem) { | ||
deleted = true; | ||
} | ||
if (!foundItem || deletedItem) return output; | ||
return { ...output, | ||
[key]: value | ||
}; | ||
}, {}), found]; | ||
}, {}), found, deleted]; | ||
} | ||
@@ -792,2 +841,47 @@ | ||
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */ | ||
class Delete { | ||
constructor(entity) { | ||
if (process.env.NODE_ENV !== 'production' && !entity) { | ||
throw new Error('Expected option "entity" not found on DeleteSchema.'); | ||
} | ||
this._entity = entity; | ||
} | ||
normalize(input, parent, key, visit, addEntity, visitedEntities) { | ||
// pass over already processed entities | ||
if (typeof input === 'string') return input; // TODO: what's store needs to be a differing type from fromJS | ||
const processedEntity = this._entity.fromJS(input, parent, key); | ||
const id = processedEntity.pk(parent, key); | ||
addEntity(this._entity, DELETED, processedEntity, parent, key); | ||
return id; | ||
} | ||
denormalize(id, unvisit) { | ||
return unvisit(id, this._entity); | ||
} | ||
/* istanbul ignore next */ | ||
_denormalizeNullable() { | ||
return []; | ||
} | ||
/* istanbul ignore next */ | ||
_normalizeNullable() { | ||
return []; | ||
} | ||
/* istanbul ignore next */ | ||
merge(existing, incoming) { | ||
return incoming; | ||
} | ||
} | ||
/* istanbul ignore file */ | ||
@@ -800,5 +894,7 @@ | ||
Array: ArraySchema, | ||
Object: ObjectSchema | ||
Object: ObjectSchema, | ||
Delete: Delete | ||
}); | ||
exports.DELETED = DELETED; | ||
exports.Entity = Entity; | ||
@@ -805,0 +901,0 @@ exports.FlatEntity = FlatEntity; |
@@ -1,1 +0,1 @@ | ||
define(["exports"],(function(e){"use strict";function t(e){return!(!e||"function"!=typeof e.hasOwnProperty||!(Object.hasOwnProperty.call(e,"__ownerID")||e._map&&Object.hasOwnProperty.call(e._map,"__ownerID")))}function n(e,t,n){let r=!0;return[Object.keys(e).reduce((t,s)=>{const i=""+s,[o,c]=n(t.get(i),e[i]);return c||(r=!1),t.has(i)?t.set(i,o):t},t),r]}class r{constructor(e,t){t&&(this._schemaAttribute="string"==typeof t?e=>e[t]:t),this.define(e)}get isSingleSchema(){return!this._schemaAttribute}define(e){this.schema=e}getSchemaAttribute(e,t,n){return!this.isSingleSchema&&this._schemaAttribute(e,t,n)}inferSchema(e,t,n){if(this.isSingleSchema)return this.schema;const r=this.getSchemaAttribute(e,t,n);return this.schema[r]}normalizeValue(e,t,n,r,s,i){const o=this.inferSchema(e,t,n);if(!o)return e;const c=r(e,t,n,o,s,i);return this.isSingleSchema||null==c?c:{id:c,schema:this.getSchemaAttribute(e,t,n)}}denormalizeValue(e,n){const r=t(e)?e.get("schema"):e.schema;if(!this.isSingleSchema&&!r)return[e,!0];return n((this.isSingleSchema?void 0:t(e)?e.get("id"):e.id)||e,this.isSingleSchema?this.schema:this.schema[r])}}const s=e=>{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]},i=e=>Array.isArray(e)?e:Object.keys(e).map(t=>e[t]),o=(e,t,n,r,o,c,a)=>{e=s(e);return i(t).map((t,s)=>o(t,n,r,e,c,a))},c=(e,t,n)=>{e=s(e);let r=!0;return void 0===t&&e&&([,r]=n(void 0,e)),[t&&t.map?t.map(t=>n(t,e)).filter(([,e])=>e).map(([e])=>e):t,r]};const a=(e,t,n,r,s,i,o)=>{const c=Object.assign({},t);return Object.keys(e).forEach(n=>{const r=e[n],a=s(t[n],t,n,r,i,o);null==a?delete c[n]:c[n]=a}),c},u=(e,r,s)=>{if(t(r))return n(e,r,s);const i=Object.assign({},r);let o=!0;return Object.keys(e).forEach(t=>{const[n,r]=s(i[t],e[t]);void 0!==i[t]&&(i[t]=n),r||(o=!1)}),[i,o]};const h=Symbol("Defined Members"),l=Symbol("unq");class f{toString(){return this[l]}static fromJS(e={},t,n){const r=new this(e);return e instanceof f&&(e=e.constructor.toObjectDefined(e)),Object.assign(r,e),Object.defineProperty(r,h,{value:Object.keys(e),writable:!1}),Object.defineProperty(r,l,{value:""+Math.random(),writable:!1}),r}static merge(e,t){const n=Object.assign(this.toObjectDefined(e),this.toObjectDefined(t));return this.fromJS(n)}static hasDefined(e,t){return e[h].includes(t)}static toObjectDefined(e){const t={};for(const n of e[h])t[n]=e[n];return t}static keysDefined(e){return e[h]}static normalize(...e){return a(this.schema,...e)}static denormalize(e,t){const n=new this,r=Object.assign({},e);let s=!0;return Object.keys(this.schema).forEach(e=>{const[i,o]=t(r[e],this.schema[e]);void 0!==r[e]&&(r[e]=i),o||e in n&&!n[e]||(s=!1)}),[this.fromJS(r),s]}static asSchema(){return"development"===process.env.NODE_ENV&&console.error("asSchema() is deprecated - use Entity directly instead."),this}}f.schema={};class m extends f{static get key(){if("production"!==process.env.NODE_ENV&&(""===this.name||"Entity"===this.name))throw new Error("Entity classes without a name must define `static get key()`");return this.name}static pk(e,t,n){return this.prototype.pk.call(e,t,n)||n}static normalize(e,t,n,r,s,i){if("string"==typeof e)return e;const o=this.fromJS(e,t,n);if("production"!==process.env.NODE_ENV){const e=new this,t=new Set(Object.keys(e)),n=this.keysDefined(o),[r,s,i]=[[],[],[]];for(const e of n)t.has(e)?r.push(e):i.push(e);for(const e of t)r.includes(e)||s.push(e);if((Math.max(n.length/2,1)<=i.length&&t.size>Math.max(i.length,2)||r.length<Math.min(1,t.size/2))&&t.size){const e=new Error(`Attempted to initialize ${this.name} with substantially different than expected keys\n\n This is likely due to a malformed response.\n Try inspecting the network response or fetch() return value.\n\n Expected keys:\n Found: ${r}\n Missing: ${s}\n Unexpected keys: ${i}\n Value: ${JSON.stringify(this.toObjectDefined(o),null,2)}`);throw e.status=400,e}}const c=o.pk(t,n);if(void 0===c||""===c){if("production"!==process.env.NODE_ENV){const t=new Error(`Missing usable resource key when normalizing response.\n\n This is likely due to a malformed response.\n Try inspecting the network response or fetch() return value.\n\n Entity: ${this.name}\n Value: ${e&&JSON.stringify(e,null,2)}\n `);throw t.status=400,t}return}const a=this.key;return a in i||(i[a]={}),c in i[a]||(i[a][c]=[]),i[a][c].some(t=>t===e)||(i[a][c].push(e),Object.keys(this.schema).forEach(e=>{if(Object.hasOwnProperty.call(o,e)){const t=this.schema[e];o[e]=r(o[e],o,e,t,s,i)}}),s(this,o,o,t,n)),c}static denormalize(e,r){if(t(e)){const[t,s]=n(this.schema,e,r);return[this.fromJS(t.toObject()),s]}const s=new this;let i=!0;const o=e;return Object.keys(this.schema).forEach(t=>{const n=this.schema[t],c=this.hasDefined(e,t)?e[t]:void 0,[a,u]=r(c,n);u||t in s&&!s[t]||(i=!1),this.hasDefined(e,t)&&o[t]!==a&&(o[t]=a)}),[o,i]}}function d(e){return null!==e&&void 0!==e.pk}"production"!==process.env.NODE_ENV&&(m.fromJS=function(e){if(void 0===this.prototype.pk)throw new Error("cannot construct on abstract types");return f.fromJS.call(this,e)});class p extends m{static denormalize(e,t){return[e,!0]}}const y=e=>{const n={},r=b(e);return[function e(s,i){if(!i)return[s,!0];if(!i.denormalize||"function"!=typeof i.denormalize){if("function"==typeof i)return s instanceof i?[s,!0]:[new i(s),!0];if("object"==typeof i){return(Array.isArray(i)?c:u)(i,s,e)}}return null===s?[s,!0]:d(i)?void 0===s?[s,!1]:((e,n,r,s,i)=>{const o=s(e,n);if("object"!=typeof o||null===o)return[o,!1];i[n.key]||(i[n.key]={});let c=!0;if(!i[n.key][e]){const s=t(o)||o instanceof p?o:n.fromJS(o);i[n.key][e]=s,[i[n.key][e],c]=n.denormalize(s,r)}return[i[n.key][e],c]})(s,i,e,r,n):"function"==typeof i.denormalize?i.denormalize(s,e):[s,!0]},n]},b=e=>{const n=t(e);return(t,r)=>{const s=r.key;return"object"==typeof t?t:n?e.getIn([s,t]):e[s]&&e[s][t]}},g=(e,t,n,r,s,i)=>{if(!e||!r||!["function","object"].includes(typeof r))return e;if(!r.normalize||"function"!=typeof r.normalize){if("function"==typeof r)return new r(e);return(Array.isArray(r)?o:a)(r,e,t,n,g,s,i)}return r.normalize(e,t,n,g,s,i)};var O=Object.freeze({__proto__:null,Union:class extends r{constructor(e,t){if(!t)throw new Error('Expected option "schemaAttribute" not found on UnionSchema.');super(e,t)}normalize(e,t,n,r,s,i){return this.normalizeValue(e,t,n,r,s,i)}denormalize(e,t){return this.denormalizeValue(e,t)}},Values:class extends r{normalize(e,t,n,r,s,i){return Object.keys(e).reduce((t,n,o)=>{const c=e[n];return null!=c?Object.assign({},t,{[n]:this.normalizeValue(c,e,n,r,s,i)}):t},{})}denormalize(e,t){let n=!0;return[Object.keys(e).reduce((r,s)=>{const i=e[s],[o,c]=this.denormalizeValue(i,t);return c||(n=!1),Object.assign({},r,{[s]:o})},{}),n]}},Array:class extends r{normalize(e,t,n,r,s,o){return i(e).map((e,i)=>this.normalizeValue(e,t,n,r,s,o)).filter(e=>null!=e)}denormalize(e,t){let n=!0;return void 0===e&&this.schema&&([,n]=t(void 0,this.schema)),[e&&e.map?e.map(e=>this.denormalizeValue(e,t)).filter(([,e])=>e).map(([e])=>e):e,n]}},Object:class{constructor(e){this.define(e)}define(e){this.schema=Object.keys(e).reduce((t,n)=>{const r=e[n];return Object.assign({},t,{[n]:r})},this.schema||{})}normalize(...e){return a(this.schema,...e)}denormalize(...e){return u(this.schema,...e)}}});e.Entity=m,e.FlatEntity=p,e.SimpleRecord=f,e.denormalize=(e,t,n)=>{if("production"!==process.env.NODE_ENV&&void 0===t)throw new Error("schema needed");if(void 0!==e){const[r,s]=y(n);return[...r(e,t),s]}return[void 0,!1,{}]},e.isEntity=d,e.normalize=(e,t)=>{const n=function(e){return["object","function"].includes(typeof e)?"object":typeof e}(t);if(null===e||typeof e!==n){if("production"!==process.env.NODE_ENV){const r=e=>{try{return"string"!=typeof JSON.parse(e)}catch(e){return!1}};throw"string"==typeof e&&r(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/docs/guides/custom-networking 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 "${n}", 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 "${n}", found "${null===e?"null":typeof e}".`)}const r={},s={},i=((e,t)=>(n,r,s,i,o)=>{const c=n.key,a=n.pk(s,i,o);c in e||(e[c]={});const u=e[c][a];if(e[c][a]=u?n.merge(u,r):r,Array.isArray(n.indexes)){const r=e[c][a];c in t||(t[c]={});for(const e of n.indexes){e in t[c]||(t[c][e]={});const n=t[c][e];u&&delete n[u[e]],e in r?n[r[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(r,void 0,2)}`)}}})(r,s);return{entities:r,indexes:s,result:g(e,e,void 0,t,i,{})}},e.schema=O,Object.defineProperty(e,"__esModule",{value:!0})})); | ||
define(["exports"],(function(e){"use strict";function t(e){return!(!e||"function"!=typeof e.hasOwnProperty||!(Object.hasOwnProperty.call(e,"__ownerID")||e._map&&Object.hasOwnProperty.call(e._map,"__ownerID")))}function n(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]}class r{constructor(e,t){t&&(this._schemaAttribute="string"==typeof t?e=>e[t]:t),this.define(e)}get isSingleSchema(){return!this._schemaAttribute}define(e){this.schema=e}getSchemaAttribute(e,t,n){return!this.isSingleSchema&&this._schemaAttribute(e,t,n)}inferSchema(e,t,n){if(this.isSingleSchema)return this.schema;const r=this.getSchemaAttribute(e,t,n);return this.schema[r]}normalizeValue(e,t,n,r,i,s){const o=this.inferSchema(e,t,n);if(!o)return e;const c=r(e,t,n,o,i,s);return this.isSingleSchema||null==c?c:{id:c,schema:this.getSchemaAttribute(e,t,n)}}denormalizeValue(e,n){const r=t(e)?e.get("schema"):e.schema;if(!this.isSingleSchema&&!r)return[e,!0,!0];return n((this.isSingleSchema?void 0:t(e)?e.get("id"):e.id)||e,this.isSingleSchema?this.schema:this.schema[r])}}const i=Symbol("ENTITY WAS DELETED"),s=e=>{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]},o=e=>Array.isArray(e)?e:Object.keys(e).map(t=>e[t]),c=([,e,t])=>e&&!t,a=(e,t,n,r,i,c,a)=>{e=s(e);return o(t).map((t,s)=>i(t,n,r,e,c,a))},u=(e,t,n)=>{e=s(e);let r=!1,i=!0;return void 0===t&&e&&([,i,r]=n(void 0,e)),[t&&t.map?t.map(t=>n(t,e)).filter(c).map(([e])=>e):t,i,r]};const h=(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},l=(e,r,i)=>{if(t(r))return n(e,r,i);const s=Object.assign({},r);let o=!0,c=!1;return Object.keys(e).forEach(t=>{const[n,r,a]=i(s[t],e[t]);void 0!==s[t]&&(s[t]=n),a&&(c=!0),r||(o=!1)}),[s,o,c]};const m=Symbol("Defined Members"),f=Symbol("unq");class d{toString(){return this[f]}static toJSON(){return{name:this.name,schema:this.schema}}static fromJS(e={},t,n){const r=new this(e);return e instanceof d&&(e=e.constructor.toObjectDefined(e)),Object.assign(r,e),Object.defineProperty(r,m,{value:Object.keys(e),writable:!1}),Object.defineProperty(r,f,{value:""+Math.random(),writable:!1}),r}static merge(e,t){const n=Object.assign(this.toObjectDefined(e),this.toObjectDefined(t));return this.fromJS(n)}static hasDefined(e,t){return e[m].includes(t)}static toObjectDefined(e){const t={};for(const n of e[m])t[n]=e[n];return t}static keysDefined(e){return e[m]}static normalize(...e){return h(this.schema,...e)}static denormalize(e,t){const n=new this,r=Object.assign({},e);let i=!1,s=!0;return Object.keys(this.schema).forEach(e=>{const[o,c,a]=t(r[e],this.schema[e]);void 0!==r[e]&&(r[e]=o),c||e in n&&!n[e]||(s=!1),!a||e in n&&!n[e]||(i=!0)}),[this.fromJS(r),s,i]}static asSchema(){return"development"===process.env.NODE_ENV&&console.error("asSchema() is deprecated - use Entity directly instead."),this}}d.schema={};class p extends d{static toJSON(){return Object.assign({},super.toJSON(),{key:this.key})}static get key(){if("production"!==process.env.NODE_ENV&&(""===this.name||"Entity"===this.name))throw new Error("Entity classes without a name must define `static get key()`");return this.name}static pk(e,t,n){return this.prototype.pk.call(e,t,n)||n}static normalize(e,t,n,r,i,s){if("string"==typeof e)return e;const o=this.fromJS(e,t,n);if("production"!==process.env.NODE_ENV){const e=new this,t=new Set(Object.keys(e)),n=this.keysDefined(o),[r,i,s]=[[],[],[]];for(const e of n)t.has(e)?r.push(e):s.push(e);for(const e of t)r.includes(e)||i.push(e);if((Math.max(n.length/2,1)<=s.length&&t.size>Math.max(s.length,2)||r.length<Math.min(1,t.size/2))&&t.size){const e=new Error(`Attempted to initialize ${this.name} with substantially different than expected keys\n\n This is likely due to a malformed response.\n Try inspecting the network response or fetch() return value.\n\n Expected keys:\n Found: ${r}\n Missing: ${i}\n Unexpected keys: ${s}\n Value: ${JSON.stringify(this.toObjectDefined(o),null,2)}`);throw e.status=400,e}}const c=o.pk(t,n);if(void 0===c||""===c){if("production"!==process.env.NODE_ENV){const t=new Error(`Missing usable resource key when normalizing response.\n\n This is likely due to a malformed response.\n Try inspecting the network response or fetch() return value.\n\n Entity: ${this.name}\n Value: ${e&&JSON.stringify(e,null,2)}\n `);throw t.status=400,t}return}const a=this.key;return a in s||(s[a]={}),c in s[a]||(s[a][c]=[]),s[a][c].some(t=>t===e)||(s[a][c].push(e),Object.keys(this.schema).forEach(e=>{if(Object.hasOwnProperty.call(o,e)){const t=this.schema[e];o[e]=r(o[e],o,e,t,i,s)}}),i(this,o,o,t,n)),c}static denormalize(e,r){if(t(e)){const[t,i,s]=n(this.schema,e,r);return[this.fromJS(t.toObject()),i,s]}const i=new this;let s=!1,o=!0;const c=e;return Object.keys(this.schema).forEach(t=>{const n=this.schema[t],a=this.hasDefined(e,t)?e[t]:void 0,[u,h,l]=r(a,n);h||t in i&&!i[t]||(o=!1),!l||t in i&&!i[t]||(s=!0),this.hasDefined(e,t)&&c[t]!==u&&(c[t]=u)}),[c,o,s]}}function y(e){return null!==e&&void 0!==e.pk}"production"!==process.env.NODE_ENV&&(p.fromJS=function(e){if(void 0===this.prototype.pk)throw new Error("cannot construct on abstract types");return d.fromJS.call(this,e)});class b extends p{static denormalize(e,t){return[e,!0,!1]}}const g=e=>{const n={},r=O(e);return[function e(s,o){if(!o)return[s,!0,!1];if(!o.denormalize||"function"!=typeof o.denormalize){if("function"==typeof o)return s instanceof o?[s,!0,!1]:[new o(s),!0,!1];if("object"==typeof o){return(Array.isArray(o)?u:l)(o,s,e)}}return null===s?[s,!0,!1]:y(o)?void 0===s?[s,!1,!1]:((e,n,r,s,o)=>{const c=s(e,n);if(c===i)return[void 0,!0,!0];if("object"!=typeof c||null===c)return[c,!1,!1];o[n.key]||(o[n.key]={});let a=!0,u=!1;if(!o[n.key][e]){const i=t(c)||c instanceof b?c:n.fromJS(c);o[n.key][e]=i,[o[n.key][e],a,u]=n.denormalize(i,r)}return[o[n.key][e],a,u]})(s,o,e,r,n):"function"==typeof o.denormalize?o.denormalize(s,e):[s,!0,!1]},n]},O=e=>{const n=t(e);return(t,r)=>{const i=r.key;return"object"==typeof t?t:n?e.getIn([i,t]):e[i]&&e[i][t]}},E=(e,t,n,r,i,s)=>{if(!e||!r||!["function","object"].includes(typeof r))return e;if(!r.normalize||"function"!=typeof r.normalize){if("function"==typeof r)return new r(e);return(Array.isArray(r)?a:h)(r,e,t,n,E,i,s)}return r.normalize(e,t,n,E,i,s)};var S=Object.freeze({__proto__:null,Union:class extends r{constructor(e,t){if(!t)throw new Error('Expected option "schemaAttribute" not found on UnionSchema.');super(e,t)}normalize(e,t,n,r,i,s){return this.normalizeValue(e,t,n,r,i,s)}denormalize(e,t){return this.denormalizeValue(e,t)}},Values:class extends r{normalize(e,t,n,r,i,s){return Object.keys(e).reduce((t,n,o)=>{const c=e[n];return null!=c?Object.assign({},t,{[n]:this.normalizeValue(c,e,n,r,i,s)}):t},{})}denormalize(e,t){let n=!0,r=!1;return[Object.keys(e).reduce((i,s)=>{const o=e[s],[c,a,u]=this.denormalizeValue(o,t);return a||(n=!1),u&&(r=!0),!a||u?i:Object.assign({},i,{[s]:c})},{}),n,r]}},Array:class extends r{normalize(e,t,n,r,i,s){return o(e).map((e,o)=>this.normalizeValue(e,t,n,r,i,s)).filter(e=>null!=e)}denormalize(e,t){let n=!1,r=!0;return void 0===e&&this.schema&&([,r,n]=t(void 0,this.schema)),[e&&e.map?e.map(e=>this.denormalizeValue(e,t)).filter(c).map(([e])=>e):e,r,n]}},Object:class{constructor(e){this.define(e)}define(e){this.schema=Object.keys(e).reduce((t,n)=>{const r=e[n];return Object.assign({},t,{[n]:r})},this.schema||{})}normalize(...e){return h(this.schema,...e)}denormalize(...e){return l(this.schema,...e)}},Delete:class{constructor(e){if("production"!==process.env.NODE_ENV&&!e)throw new Error('Expected option "entity" not found on DeleteSchema.');this._entity=e}normalize(e,t,n,r,s,o){if("string"==typeof e)return e;const c=this._entity.fromJS(e,t,n),a=c.pk(t,n);return s(this._entity,i,c,t,n),a}denormalize(e,t){return t(e,this._entity)}_denormalizeNullable(){return[]}_normalizeNullable(){return[]}merge(e,t){return t}}});e.DELETED=i,e.Entity=p,e.FlatEntity=b,e.SimpleRecord=d,e.denormalize=(e,t,n)=>{if("production"!==process.env.NODE_ENV&&void 0===t)throw new Error("schema needed");if(void 0!==e){const[r,i]=g(n);return[...r(e,t),i]}return[void 0,!1,!1,{}]},e.isEntity=y,e.normalize=(e,t)=>{const n=function(e){return["object","function"].includes(typeof e)?"object":typeof e}(t);if(null===e||typeof e!==n){if("production"!==process.env.NODE_ENV){const r=e=>{try{return"string"!=typeof JSON.parse(e)}catch(e){return!1}};throw"string"==typeof e&&r(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/docs/guides/custom-networking 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 "${n}", 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 "${n}", found "${null===e?"null":typeof e}".`)}const r={},i={},s=((e,t)=>(n,r,i,s,o)=>{const c=n.key,a=n.pk(i,s,o);c in e||(e[c]={});const u=e[c][a];if(e[c][a]=u?n.merge(u,r):r,Array.isArray(n.indexes)){const r=e[c][a];c in t||(t[c]={});for(const e of n.indexes){e in t[c]||(t[c][e]={});const n=t[c][e];u&&delete n[u[e]],e in r?n[r[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(r,void 0,2)}`)}}})(r,i);return{entities:r,indexes:i,result:E(e,e,void 0,t,s,{})}},e.schema=S,Object.defineProperty(e,"__esModule",{value:!0})})); |
@@ -32,2 +32,3 @@ var rest_hooks_normalizr = (function (exports) { | ||
let found = true; | ||
let deleted = false; | ||
return [Object.keys(schema).reduce((object, key) => { | ||
@@ -37,3 +38,3 @@ // Immutable maps cast keys to strings on write so we need to ensure | ||
const stringKey = `${key}`; | ||
const [item, foundItem] = unvisit(object.get(stringKey), schema[stringKey]); | ||
const [item, foundItem, deletedItem] = unvisit(object.get(stringKey), schema[stringKey]); | ||
@@ -44,2 +45,6 @@ if (!foundItem) { | ||
if (deletedItem) { | ||
deleted = true; | ||
} | ||
if (object.has(stringKey)) { | ||
@@ -50,3 +55,3 @@ return object.set(stringKey, item); | ||
} | ||
}, input), found]; | ||
}, input), found, deleted]; | ||
} | ||
@@ -102,3 +107,3 @@ | ||
if (!this.isSingleSchema && !schemaKey) { | ||
return [value, true]; | ||
return [value, true, true]; | ||
} | ||
@@ -113,2 +118,4 @@ | ||
const DELETED = Symbol('ENTITY WAS DELETED'); | ||
const validateSchema = definition => { | ||
@@ -126,2 +133,4 @@ const isArray = Array.isArray(definition); | ||
const filterEmpty = ([, foundItem, deletedItem]) => foundItem && !deletedItem; | ||
const normalize = (schema, input, parent, key, visit, addEntity, visitedEntities) => { | ||
@@ -136,9 +145,10 @@ schema = validateSchema(schema); | ||
schema = validateSchema(schema); | ||
let deleted = false; | ||
let found = true; | ||
if (input === undefined && schema) { | ||
[, found] = unvisit(undefined, schema); | ||
[, found, deleted] = unvisit(undefined, schema); | ||
} | ||
return [input && input.map ? input.map(entityOrId => unvisit(entityOrId, schema)).filter(([, foundItem]) => foundItem).map(([value]) => value) : input, found]; | ||
return [input && input.map ? input.map(entityOrId => unvisit(entityOrId, schema)).filter(filterEmpty).map(([value]) => value) : input, found, deleted]; | ||
}; | ||
@@ -152,9 +162,10 @@ class ArraySchema extends PolymorphicSchema { | ||
denormalize(input, unvisit) { | ||
let deleted = false; | ||
let found = true; | ||
if (input === undefined && this.schema) { | ||
[, found] = unvisit(undefined, this.schema); | ||
[, found, deleted] = unvisit(undefined, this.schema); | ||
} | ||
return [input && input.map ? input.map(entityOrId => this.denormalizeValue(entityOrId, unvisit)).filter(([, foundItem]) => foundItem).map(([value]) => value) : input, found]; | ||
return [input && input.map ? input.map(entityOrId => this.denormalizeValue(entityOrId, unvisit)).filter(filterEmpty).map(([value]) => value) : input, found, deleted]; | ||
} | ||
@@ -187,4 +198,5 @@ | ||
let found = true; | ||
let deleted = false; | ||
Object.keys(schema).forEach(key => { | ||
const [item, foundItem] = unvisit(object[key], schema[key]); | ||
const [item, foundItem, deletedItem] = unvisit(object[key], schema[key]); | ||
@@ -195,2 +207,6 @@ if (object[key] !== undefined) { | ||
if (deletedItem) { | ||
deleted = true; | ||
} | ||
if (!foundItem) { | ||
@@ -200,3 +216,3 @@ found = false; | ||
}); | ||
return [object, found]; | ||
return [object, found, deleted]; | ||
}; | ||
@@ -237,2 +253,9 @@ class ObjectSchema { | ||
} | ||
static toJSON() { | ||
return { | ||
name: this.name, | ||
schema: this.schema | ||
}; | ||
} | ||
/** Defines nested entities */ | ||
@@ -309,5 +332,6 @@ | ||
}; | ||
let deleted = false; | ||
let found = true; | ||
Object.keys(this.schema).forEach(key => { | ||
const [item, foundItem] = unvisit(object[key], this.schema[key]); | ||
const [item, foundItem, deletedItem] = unvisit(object[key], this.schema[key]); | ||
@@ -323,5 +347,9 @@ if (object[key] !== undefined) { | ||
} | ||
if (deletedItem && !(key in instance && !instance[key])) { | ||
deleted = true; | ||
} | ||
}); // useDenormalized will memo based on entities, so creating a new object each time is fine | ||
return [this.fromJS(object), found]; | ||
return [this.fromJS(object), found, deleted]; | ||
} | ||
@@ -349,2 +377,7 @@ /* istanbul ignore next */ | ||
class Entity extends SimpleRecord { | ||
static toJSON() { | ||
return { ...super.toJSON(), | ||
key: this.key | ||
}; | ||
} | ||
/** | ||
@@ -357,2 +390,3 @@ * A unique identifier for each Entity | ||
/** Returns the globally unique identifier for the static Entity */ | ||
@@ -471,4 +505,4 @@ static get key() { | ||
if (isImmutable(entity)) { | ||
const [denormEntity, found] = denormalizeImmutable(this.schema, entity, unvisit); | ||
return [this.fromJS(denormEntity.toObject()), found]; | ||
const [denormEntity, found, deleted] = denormalizeImmutable(this.schema, entity, unvisit); | ||
return [this.fromJS(denormEntity.toObject()), found, deleted]; | ||
} // TODO: This creates unneeded memory pressure | ||
@@ -478,2 +512,3 @@ | ||
const instance = new this(); | ||
let deleted = false; | ||
let found = true; | ||
@@ -484,3 +519,3 @@ const denormEntity = entity; | ||
const input = this.hasDefined(entity, key) ? entity[key] : undefined; | ||
const [value, foundItem] = unvisit(input, schema); // members who default to falsy values are considered 'optional' | ||
const [value, foundItem, deletedItem] = unvisit(input, schema); // members who default to falsy values are considered 'optional' | ||
// if falsy value, and default is actually set then it is optional so pass through | ||
@@ -492,2 +527,6 @@ | ||
if (deletedItem && !(key in instance && !instance[key])) { | ||
deleted = true; | ||
} | ||
if (this.hasDefined(entity, key) && denormEntity[key] !== value) { | ||
@@ -497,7 +536,6 @@ denormEntity[key] = value; | ||
}); | ||
return [denormEntity, found]; | ||
return [denormEntity, found, deleted]; | ||
} | ||
} | ||
/* istanbul ignore next */ | ||
@@ -519,3 +557,3 @@ if (process.env.NODE_ENV !== 'production') { | ||
static denormalize(entity, unvisit) { | ||
return [entity, true]; | ||
return [entity, true, false]; | ||
} | ||
@@ -528,4 +566,8 @@ | ||
if (entity === DELETED) { | ||
return [undefined, true, true]; | ||
} | ||
if (typeof entity !== 'object' || entity === null) { | ||
return [entity, false]; | ||
return [entity, false, false]; | ||
} | ||
@@ -538,2 +580,3 @@ | ||
let found = true; | ||
let deleted = false; | ||
@@ -546,6 +589,6 @@ if (!cache[schema.key][id]) { | ||
cache[schema.key][id] = entityCopy; | ||
[cache[schema.key][id], found] = schema.denormalize(entityCopy, unvisit); | ||
[cache[schema.key][id], found, deleted] = schema.denormalize(entityCopy, unvisit); | ||
} | ||
return [cache[schema.key][id], found]; | ||
return [cache[schema.key][id], found, deleted]; | ||
}; | ||
@@ -557,8 +600,8 @@ | ||
return [function unvisit(input, schema) { | ||
if (!schema) return [input, true]; | ||
if (!schema) return [input, true, false]; | ||
if (!schema.denormalize || typeof schema.denormalize !== 'function') { | ||
if (typeof schema === 'function') { | ||
if (input instanceof schema) return [input, true]; | ||
return [new schema(input), true]; | ||
if (input instanceof schema) return [input, true, false]; | ||
return [new schema(input), true, false]; | ||
} else if (typeof schema === 'object') { | ||
@@ -572,3 +615,3 @@ const method = Array.isArray(schema) ? denormalize : denormalize$1; | ||
if (input === null) { | ||
return [input, true]; | ||
return [input, true, false]; | ||
} | ||
@@ -579,3 +622,3 @@ | ||
if (input === undefined) { | ||
return [input, false]; | ||
return [input, false, false]; | ||
} | ||
@@ -590,3 +633,3 @@ | ||
return [input, true]; | ||
return [input, true, false]; | ||
}, cache]; | ||
@@ -622,3 +665,3 @@ }; | ||
return [undefined, false, {}]; | ||
return [undefined, false, false, {}]; | ||
}; | ||
@@ -775,5 +818,6 @@ | ||
let found = true; | ||
let deleted = false; | ||
return [Object.keys(input).reduce((output, key) => { | ||
const entityOrId = input[key]; | ||
const [value, foundItem] = this.denormalizeValue(entityOrId, unvisit); | ||
const [value, foundItem, deletedItem] = this.denormalizeValue(entityOrId, unvisit); | ||
@@ -784,6 +828,11 @@ if (!foundItem) { | ||
if (deletedItem) { | ||
deleted = true; | ||
} | ||
if (!foundItem || deletedItem) return output; | ||
return { ...output, | ||
[key]: value | ||
}; | ||
}, {}), found]; | ||
}, {}), found, deleted]; | ||
} | ||
@@ -793,2 +842,47 @@ | ||
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */ | ||
class Delete { | ||
constructor(entity) { | ||
if (process.env.NODE_ENV !== 'production' && !entity) { | ||
throw new Error('Expected option "entity" not found on DeleteSchema.'); | ||
} | ||
this._entity = entity; | ||
} | ||
normalize(input, parent, key, visit, addEntity, visitedEntities) { | ||
// pass over already processed entities | ||
if (typeof input === 'string') return input; // TODO: what's store needs to be a differing type from fromJS | ||
const processedEntity = this._entity.fromJS(input, parent, key); | ||
const id = processedEntity.pk(parent, key); | ||
addEntity(this._entity, DELETED, processedEntity, parent, key); | ||
return id; | ||
} | ||
denormalize(id, unvisit) { | ||
return unvisit(id, this._entity); | ||
} | ||
/* istanbul ignore next */ | ||
_denormalizeNullable() { | ||
return []; | ||
} | ||
/* istanbul ignore next */ | ||
_normalizeNullable() { | ||
return []; | ||
} | ||
/* istanbul ignore next */ | ||
merge(existing, incoming) { | ||
return incoming; | ||
} | ||
} | ||
/* istanbul ignore file */ | ||
@@ -801,5 +895,7 @@ | ||
Array: ArraySchema, | ||
Object: ObjectSchema | ||
Object: ObjectSchema, | ||
Delete: Delete | ||
}); | ||
exports.DELETED = DELETED; | ||
exports.Entity = Entity; | ||
@@ -806,0 +902,0 @@ exports.FlatEntity = FlatEntity; |
@@ -1,1 +0,1 @@ | ||
var rest_hooks_normalizr=function(e){"use strict";function t(e){return!(!e||"function"!=typeof e.hasOwnProperty||!(Object.hasOwnProperty.call(e,"__ownerID")||e._map&&Object.hasOwnProperty.call(e._map,"__ownerID")))}function n(e,t,n){let r=!0;return[Object.keys(e).reduce((t,s)=>{const i=""+s,[o,c]=n(t.get(i),e[i]);return c||(r=!1),t.has(i)?t.set(i,o):t},t),r]}class r{constructor(e,t){t&&(this._schemaAttribute="string"==typeof t?e=>e[t]:t),this.define(e)}get isSingleSchema(){return!this._schemaAttribute}define(e){this.schema=e}getSchemaAttribute(e,t,n){return!this.isSingleSchema&&this._schemaAttribute(e,t,n)}inferSchema(e,t,n){if(this.isSingleSchema)return this.schema;const r=this.getSchemaAttribute(e,t,n);return this.schema[r]}normalizeValue(e,t,n,r,s,i){const o=this.inferSchema(e,t,n);if(!o)return e;const c=r(e,t,n,o,s,i);return this.isSingleSchema||null==c?c:{id:c,schema:this.getSchemaAttribute(e,t,n)}}denormalizeValue(e,n){const r=t(e)?e.get("schema"):e.schema;if(!this.isSingleSchema&&!r)return[e,!0];return n((this.isSingleSchema?void 0:t(e)?e.get("id"):e.id)||e,this.isSingleSchema?this.schema:this.schema[r])}}const s=e=>{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]},i=e=>Array.isArray(e)?e:Object.keys(e).map(t=>e[t]),o=(e,t,n,r,o,c,a)=>{e=s(e);return i(t).map((t,s)=>o(t,n,r,e,c,a))},c=(e,t,n)=>{e=s(e);let r=!0;return void 0===t&&e&&([,r]=n(void 0,e)),[t&&t.map?t.map(t=>n(t,e)).filter(([,e])=>e).map(([e])=>e):t,r]};const a=(e,t,n,r,s,i,o)=>{const c=Object.assign({},t);return Object.keys(e).forEach(n=>{const r=e[n],a=s(t[n],t,n,r,i,o);null==a?delete c[n]:c[n]=a}),c},u=(e,r,s)=>{if(t(r))return n(e,r,s);const i=Object.assign({},r);let o=!0;return Object.keys(e).forEach(t=>{const[n,r]=s(i[t],e[t]);void 0!==i[t]&&(i[t]=n),r||(o=!1)}),[i,o]};const h=Symbol("Defined Members"),l=Symbol("unq");class f{toString(){return this[l]}static fromJS(e={},t,n){const r=new this(e);return e instanceof f&&(e=e.constructor.toObjectDefined(e)),Object.assign(r,e),Object.defineProperty(r,h,{value:Object.keys(e),writable:!1}),Object.defineProperty(r,l,{value:""+Math.random(),writable:!1}),r}static merge(e,t){const n=Object.assign(this.toObjectDefined(e),this.toObjectDefined(t));return this.fromJS(n)}static hasDefined(e,t){return e[h].includes(t)}static toObjectDefined(e){const t={};for(const n of e[h])t[n]=e[n];return t}static keysDefined(e){return e[h]}static normalize(...e){return a(this.schema,...e)}static denormalize(e,t){const n=new this,r=Object.assign({},e);let s=!0;return Object.keys(this.schema).forEach(e=>{const[i,o]=t(r[e],this.schema[e]);void 0!==r[e]&&(r[e]=i),o||e in n&&!n[e]||(s=!1)}),[this.fromJS(r),s]}static asSchema(){return"development"===process.env.NODE_ENV&&console.error("asSchema() is deprecated - use Entity directly instead."),this}}f.schema={};class m extends f{static get key(){if("production"!==process.env.NODE_ENV&&(""===this.name||"Entity"===this.name))throw new Error("Entity classes without a name must define `static get key()`");return this.name}static pk(e,t,n){return this.prototype.pk.call(e,t,n)||n}static normalize(e,t,n,r,s,i){if("string"==typeof e)return e;const o=this.fromJS(e,t,n);if("production"!==process.env.NODE_ENV){const e=new this,t=new Set(Object.keys(e)),n=this.keysDefined(o),[r,s,i]=[[],[],[]];for(const e of n)t.has(e)?r.push(e):i.push(e);for(const e of t)r.includes(e)||s.push(e);if((Math.max(n.length/2,1)<=i.length&&t.size>Math.max(i.length,2)||r.length<Math.min(1,t.size/2))&&t.size){const e=new Error(`Attempted to initialize ${this.name} with substantially different than expected keys\n\n This is likely due to a malformed response.\n Try inspecting the network response or fetch() return value.\n\n Expected keys:\n Found: ${r}\n Missing: ${s}\n Unexpected keys: ${i}\n Value: ${JSON.stringify(this.toObjectDefined(o),null,2)}`);throw e.status=400,e}}const c=o.pk(t,n);if(void 0===c||""===c){if("production"!==process.env.NODE_ENV){const t=new Error(`Missing usable resource key when normalizing response.\n\n This is likely due to a malformed response.\n Try inspecting the network response or fetch() return value.\n\n Entity: ${this.name}\n Value: ${e&&JSON.stringify(e,null,2)}\n `);throw t.status=400,t}return}const a=this.key;return a in i||(i[a]={}),c in i[a]||(i[a][c]=[]),i[a][c].some(t=>t===e)||(i[a][c].push(e),Object.keys(this.schema).forEach(e=>{if(Object.hasOwnProperty.call(o,e)){const t=this.schema[e];o[e]=r(o[e],o,e,t,s,i)}}),s(this,o,o,t,n)),c}static denormalize(e,r){if(t(e)){const[t,s]=n(this.schema,e,r);return[this.fromJS(t.toObject()),s]}const s=new this;let i=!0;const o=e;return Object.keys(this.schema).forEach(t=>{const n=this.schema[t],c=this.hasDefined(e,t)?e[t]:void 0,[a,u]=r(c,n);u||t in s&&!s[t]||(i=!1),this.hasDefined(e,t)&&o[t]!==a&&(o[t]=a)}),[o,i]}}function d(e){return null!==e&&void 0!==e.pk}"production"!==process.env.NODE_ENV&&(m.fromJS=function(e){if(void 0===this.prototype.pk)throw new Error("cannot construct on abstract types");return f.fromJS.call(this,e)});class p extends m{static denormalize(e,t){return[e,!0]}}const y=e=>{const n={},r=b(e);return[function e(s,i){if(!i)return[s,!0];if(!i.denormalize||"function"!=typeof i.denormalize){if("function"==typeof i)return s instanceof i?[s,!0]:[new i(s),!0];if("object"==typeof i){return(Array.isArray(i)?c:u)(i,s,e)}}return null===s?[s,!0]:d(i)?void 0===s?[s,!1]:((e,n,r,s,i)=>{const o=s(e,n);if("object"!=typeof o||null===o)return[o,!1];i[n.key]||(i[n.key]={});let c=!0;if(!i[n.key][e]){const s=t(o)||o instanceof p?o:n.fromJS(o);i[n.key][e]=s,[i[n.key][e],c]=n.denormalize(s,r)}return[i[n.key][e],c]})(s,i,e,r,n):"function"==typeof i.denormalize?i.denormalize(s,e):[s,!0]},n]},b=e=>{const n=t(e);return(t,r)=>{const s=r.key;return"object"==typeof t?t:n?e.getIn([s,t]):e[s]&&e[s][t]}},g=(e,t,n,r,s,i)=>{if(!e||!r||!["function","object"].includes(typeof r))return e;if(!r.normalize||"function"!=typeof r.normalize){if("function"==typeof r)return new r(e);return(Array.isArray(r)?o:a)(r,e,t,n,g,s,i)}return r.normalize(e,t,n,g,s,i)};var O=Object.freeze({__proto__:null,Union:class extends r{constructor(e,t){if(!t)throw new Error('Expected option "schemaAttribute" not found on UnionSchema.');super(e,t)}normalize(e,t,n,r,s,i){return this.normalizeValue(e,t,n,r,s,i)}denormalize(e,t){return this.denormalizeValue(e,t)}},Values:class extends r{normalize(e,t,n,r,s,i){return Object.keys(e).reduce((t,n,o)=>{const c=e[n];return null!=c?Object.assign({},t,{[n]:this.normalizeValue(c,e,n,r,s,i)}):t},{})}denormalize(e,t){let n=!0;return[Object.keys(e).reduce((r,s)=>{const i=e[s],[o,c]=this.denormalizeValue(i,t);return c||(n=!1),Object.assign({},r,{[s]:o})},{}),n]}},Array:class extends r{normalize(e,t,n,r,s,o){return i(e).map((e,i)=>this.normalizeValue(e,t,n,r,s,o)).filter(e=>null!=e)}denormalize(e,t){let n=!0;return void 0===e&&this.schema&&([,n]=t(void 0,this.schema)),[e&&e.map?e.map(e=>this.denormalizeValue(e,t)).filter(([,e])=>e).map(([e])=>e):e,n]}},Object:class{constructor(e){this.define(e)}define(e){this.schema=Object.keys(e).reduce((t,n)=>{const r=e[n];return Object.assign({},t,{[n]:r})},this.schema||{})}normalize(...e){return a(this.schema,...e)}denormalize(...e){return u(this.schema,...e)}}});return e.Entity=m,e.FlatEntity=p,e.SimpleRecord=f,e.denormalize=(e,t,n)=>{if("production"!==process.env.NODE_ENV&&void 0===t)throw new Error("schema needed");if(void 0!==e){const[r,s]=y(n);return[...r(e,t),s]}return[void 0,!1,{}]},e.isEntity=d,e.normalize=(e,t)=>{const n=function(e){return["object","function"].includes(typeof e)?"object":typeof e}(t);if(null===e||typeof e!==n){if("production"!==process.env.NODE_ENV){const r=e=>{try{return"string"!=typeof JSON.parse(e)}catch(e){return!1}};throw"string"==typeof e&&r(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/docs/guides/custom-networking 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 "${n}", 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 "${n}", found "${null===e?"null":typeof e}".`)}const r={},s={},i=((e,t)=>(n,r,s,i,o)=>{const c=n.key,a=n.pk(s,i,o);c in e||(e[c]={});const u=e[c][a];if(e[c][a]=u?n.merge(u,r):r,Array.isArray(n.indexes)){const r=e[c][a];c in t||(t[c]={});for(const e of n.indexes){e in t[c]||(t[c][e]={});const n=t[c][e];u&&delete n[u[e]],e in r?n[r[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(r,void 0,2)}`)}}})(r,s);return{entities:r,indexes:s,result:g(e,e,void 0,t,i,{})}},e.schema=O,e}({}); | ||
var rest_hooks_normalizr=function(e){"use strict";function t(e){return!(!e||"function"!=typeof e.hasOwnProperty||!(Object.hasOwnProperty.call(e,"__ownerID")||e._map&&Object.hasOwnProperty.call(e._map,"__ownerID")))}function n(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]}class r{constructor(e,t){t&&(this._schemaAttribute="string"==typeof t?e=>e[t]:t),this.define(e)}get isSingleSchema(){return!this._schemaAttribute}define(e){this.schema=e}getSchemaAttribute(e,t,n){return!this.isSingleSchema&&this._schemaAttribute(e,t,n)}inferSchema(e,t,n){if(this.isSingleSchema)return this.schema;const r=this.getSchemaAttribute(e,t,n);return this.schema[r]}normalizeValue(e,t,n,r,i,s){const o=this.inferSchema(e,t,n);if(!o)return e;const c=r(e,t,n,o,i,s);return this.isSingleSchema||null==c?c:{id:c,schema:this.getSchemaAttribute(e,t,n)}}denormalizeValue(e,n){const r=t(e)?e.get("schema"):e.schema;if(!this.isSingleSchema&&!r)return[e,!0,!0];return n((this.isSingleSchema?void 0:t(e)?e.get("id"):e.id)||e,this.isSingleSchema?this.schema:this.schema[r])}}const i=Symbol("ENTITY WAS DELETED"),s=e=>{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]},o=e=>Array.isArray(e)?e:Object.keys(e).map(t=>e[t]),c=([,e,t])=>e&&!t,a=(e,t,n,r,i,c,a)=>{e=s(e);return o(t).map((t,s)=>i(t,n,r,e,c,a))},u=(e,t,n)=>{e=s(e);let r=!1,i=!0;return void 0===t&&e&&([,i,r]=n(void 0,e)),[t&&t.map?t.map(t=>n(t,e)).filter(c).map(([e])=>e):t,i,r]};const h=(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},l=(e,r,i)=>{if(t(r))return n(e,r,i);const s=Object.assign({},r);let o=!0,c=!1;return Object.keys(e).forEach(t=>{const[n,r,a]=i(s[t],e[t]);void 0!==s[t]&&(s[t]=n),a&&(c=!0),r||(o=!1)}),[s,o,c]};const m=Symbol("Defined Members"),f=Symbol("unq");class d{toString(){return this[f]}static toJSON(){return{name:this.name,schema:this.schema}}static fromJS(e={},t,n){const r=new this(e);return e instanceof d&&(e=e.constructor.toObjectDefined(e)),Object.assign(r,e),Object.defineProperty(r,m,{value:Object.keys(e),writable:!1}),Object.defineProperty(r,f,{value:""+Math.random(),writable:!1}),r}static merge(e,t){const n=Object.assign(this.toObjectDefined(e),this.toObjectDefined(t));return this.fromJS(n)}static hasDefined(e,t){return e[m].includes(t)}static toObjectDefined(e){const t={};for(const n of e[m])t[n]=e[n];return t}static keysDefined(e){return e[m]}static normalize(...e){return h(this.schema,...e)}static denormalize(e,t){const n=new this,r=Object.assign({},e);let i=!1,s=!0;return Object.keys(this.schema).forEach(e=>{const[o,c,a]=t(r[e],this.schema[e]);void 0!==r[e]&&(r[e]=o),c||e in n&&!n[e]||(s=!1),!a||e in n&&!n[e]||(i=!0)}),[this.fromJS(r),s,i]}static asSchema(){return"development"===process.env.NODE_ENV&&console.error("asSchema() is deprecated - use Entity directly instead."),this}}d.schema={};class p extends d{static toJSON(){return Object.assign({},super.toJSON(),{key:this.key})}static get key(){if("production"!==process.env.NODE_ENV&&(""===this.name||"Entity"===this.name))throw new Error("Entity classes without a name must define `static get key()`");return this.name}static pk(e,t,n){return this.prototype.pk.call(e,t,n)||n}static normalize(e,t,n,r,i,s){if("string"==typeof e)return e;const o=this.fromJS(e,t,n);if("production"!==process.env.NODE_ENV){const e=new this,t=new Set(Object.keys(e)),n=this.keysDefined(o),[r,i,s]=[[],[],[]];for(const e of n)t.has(e)?r.push(e):s.push(e);for(const e of t)r.includes(e)||i.push(e);if((Math.max(n.length/2,1)<=s.length&&t.size>Math.max(s.length,2)||r.length<Math.min(1,t.size/2))&&t.size){const e=new Error(`Attempted to initialize ${this.name} with substantially different than expected keys\n\n This is likely due to a malformed response.\n Try inspecting the network response or fetch() return value.\n\n Expected keys:\n Found: ${r}\n Missing: ${i}\n Unexpected keys: ${s}\n Value: ${JSON.stringify(this.toObjectDefined(o),null,2)}`);throw e.status=400,e}}const c=o.pk(t,n);if(void 0===c||""===c){if("production"!==process.env.NODE_ENV){const t=new Error(`Missing usable resource key when normalizing response.\n\n This is likely due to a malformed response.\n Try inspecting the network response or fetch() return value.\n\n Entity: ${this.name}\n Value: ${e&&JSON.stringify(e,null,2)}\n `);throw t.status=400,t}return}const a=this.key;return a in s||(s[a]={}),c in s[a]||(s[a][c]=[]),s[a][c].some(t=>t===e)||(s[a][c].push(e),Object.keys(this.schema).forEach(e=>{if(Object.hasOwnProperty.call(o,e)){const t=this.schema[e];o[e]=r(o[e],o,e,t,i,s)}}),i(this,o,o,t,n)),c}static denormalize(e,r){if(t(e)){const[t,i,s]=n(this.schema,e,r);return[this.fromJS(t.toObject()),i,s]}const i=new this;let s=!1,o=!0;const c=e;return Object.keys(this.schema).forEach(t=>{const n=this.schema[t],a=this.hasDefined(e,t)?e[t]:void 0,[u,h,l]=r(a,n);h||t in i&&!i[t]||(o=!1),!l||t in i&&!i[t]||(s=!0),this.hasDefined(e,t)&&c[t]!==u&&(c[t]=u)}),[c,o,s]}}function y(e){return null!==e&&void 0!==e.pk}"production"!==process.env.NODE_ENV&&(p.fromJS=function(e){if(void 0===this.prototype.pk)throw new Error("cannot construct on abstract types");return d.fromJS.call(this,e)});class b extends p{static denormalize(e,t){return[e,!0,!1]}}const g=e=>{const n={},r=O(e);return[function e(s,o){if(!o)return[s,!0,!1];if(!o.denormalize||"function"!=typeof o.denormalize){if("function"==typeof o)return s instanceof o?[s,!0,!1]:[new o(s),!0,!1];if("object"==typeof o){return(Array.isArray(o)?u:l)(o,s,e)}}return null===s?[s,!0,!1]:y(o)?void 0===s?[s,!1,!1]:((e,n,r,s,o)=>{const c=s(e,n);if(c===i)return[void 0,!0,!0];if("object"!=typeof c||null===c)return[c,!1,!1];o[n.key]||(o[n.key]={});let a=!0,u=!1;if(!o[n.key][e]){const i=t(c)||c instanceof b?c:n.fromJS(c);o[n.key][e]=i,[o[n.key][e],a,u]=n.denormalize(i,r)}return[o[n.key][e],a,u]})(s,o,e,r,n):"function"==typeof o.denormalize?o.denormalize(s,e):[s,!0,!1]},n]},O=e=>{const n=t(e);return(t,r)=>{const i=r.key;return"object"==typeof t?t:n?e.getIn([i,t]):e[i]&&e[i][t]}},E=(e,t,n,r,i,s)=>{if(!e||!r||!["function","object"].includes(typeof r))return e;if(!r.normalize||"function"!=typeof r.normalize){if("function"==typeof r)return new r(e);return(Array.isArray(r)?a:h)(r,e,t,n,E,i,s)}return r.normalize(e,t,n,E,i,s)};var S=Object.freeze({__proto__:null,Union:class extends r{constructor(e,t){if(!t)throw new Error('Expected option "schemaAttribute" not found on UnionSchema.');super(e,t)}normalize(e,t,n,r,i,s){return this.normalizeValue(e,t,n,r,i,s)}denormalize(e,t){return this.denormalizeValue(e,t)}},Values:class extends r{normalize(e,t,n,r,i,s){return Object.keys(e).reduce((t,n,o)=>{const c=e[n];return null!=c?Object.assign({},t,{[n]:this.normalizeValue(c,e,n,r,i,s)}):t},{})}denormalize(e,t){let n=!0,r=!1;return[Object.keys(e).reduce((i,s)=>{const o=e[s],[c,a,u]=this.denormalizeValue(o,t);return a||(n=!1),u&&(r=!0),!a||u?i:Object.assign({},i,{[s]:c})},{}),n,r]}},Array:class extends r{normalize(e,t,n,r,i,s){return o(e).map((e,o)=>this.normalizeValue(e,t,n,r,i,s)).filter(e=>null!=e)}denormalize(e,t){let n=!1,r=!0;return void 0===e&&this.schema&&([,r,n]=t(void 0,this.schema)),[e&&e.map?e.map(e=>this.denormalizeValue(e,t)).filter(c).map(([e])=>e):e,r,n]}},Object:class{constructor(e){this.define(e)}define(e){this.schema=Object.keys(e).reduce((t,n)=>{const r=e[n];return Object.assign({},t,{[n]:r})},this.schema||{})}normalize(...e){return h(this.schema,...e)}denormalize(...e){return l(this.schema,...e)}},Delete:class{constructor(e){if("production"!==process.env.NODE_ENV&&!e)throw new Error('Expected option "entity" not found on DeleteSchema.');this._entity=e}normalize(e,t,n,r,s,o){if("string"==typeof e)return e;const c=this._entity.fromJS(e,t,n),a=c.pk(t,n);return s(this._entity,i,c,t,n),a}denormalize(e,t){return t(e,this._entity)}_denormalizeNullable(){return[]}_normalizeNullable(){return[]}merge(e,t){return t}}});return e.DELETED=i,e.Entity=p,e.FlatEntity=b,e.SimpleRecord=d,e.denormalize=(e,t,n)=>{if("production"!==process.env.NODE_ENV&&void 0===t)throw new Error("schema needed");if(void 0!==e){const[r,i]=g(n);return[...r(e,t),i]}return[void 0,!1,!1,{}]},e.isEntity=y,e.normalize=(e,t)=>{const n=function(e){return["object","function"].includes(typeof e)?"object":typeof e}(t);if(null===e||typeof e!==n){if("production"!==process.env.NODE_ENV){const r=e=>{try{return"string"!=typeof JSON.parse(e)}catch(e){return!1}};throw"string"==typeof e&&r(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/docs/guides/custom-networking 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 "${n}", 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 "${n}", found "${null===e?"null":typeof e}".`)}const r={},i={},s=((e,t)=>(n,r,i,s,o)=>{const c=n.key,a=n.pk(i,s,o);c in e||(e[c]={});const u=e[c][a];if(e[c][a]=u?n.merge(u,r):r,Array.isArray(n.indexes)){const r=e[c][a];c in t||(t[c]={});for(const e of n.indexes){e in t[c]||(t[c][e]={});const n=t[c][e];u&&delete n[u[e]],e in r?n[r[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(r,void 0,2)}`)}}})(r,i);return{entities:r,indexes:i,result:E(e,e,void 0,t,s,{})}},e.schema=S,e}({}); |
@@ -29,2 +29,3 @@ /** | ||
let found = true; | ||
let deleted = false; | ||
return [Object.keys(schema).reduce((object, key) => { | ||
@@ -34,3 +35,3 @@ // Immutable maps cast keys to strings on write so we need to ensure | ||
const stringKey = `${key}`; | ||
const [item, foundItem] = unvisit(object.get(stringKey), schema[stringKey]); | ||
const [item, foundItem, deletedItem] = unvisit(object.get(stringKey), schema[stringKey]); | ||
@@ -41,2 +42,6 @@ if (!foundItem) { | ||
if (deletedItem) { | ||
deleted = true; | ||
} | ||
if (object.has(stringKey)) { | ||
@@ -47,3 +52,3 @@ return object.set(stringKey, item); | ||
} | ||
}, input), found]; | ||
}, input), found, deleted]; | ||
} | ||
@@ -99,3 +104,3 @@ | ||
if (!this.isSingleSchema && !schemaKey) { | ||
return [value, true]; | ||
return [value, true, true]; | ||
} | ||
@@ -110,2 +115,4 @@ | ||
const DELETED = Symbol('ENTITY WAS DELETED'); | ||
const validateSchema = definition => { | ||
@@ -123,2 +130,4 @@ const isArray = Array.isArray(definition); | ||
const filterEmpty = ([, foundItem, deletedItem]) => foundItem && !deletedItem; | ||
const normalize = (schema, input, parent, key, visit, addEntity, visitedEntities) => { | ||
@@ -133,9 +142,10 @@ schema = validateSchema(schema); | ||
schema = validateSchema(schema); | ||
let deleted = false; | ||
let found = true; | ||
if (input === undefined && schema) { | ||
[, found] = unvisit(undefined, schema); | ||
[, found, deleted] = unvisit(undefined, schema); | ||
} | ||
return [input && input.map ? input.map(entityOrId => unvisit(entityOrId, schema)).filter(([, foundItem]) => foundItem).map(([value]) => value) : input, found]; | ||
return [input && input.map ? input.map(entityOrId => unvisit(entityOrId, schema)).filter(filterEmpty).map(([value]) => value) : input, found, deleted]; | ||
}; | ||
@@ -149,9 +159,10 @@ class ArraySchema extends PolymorphicSchema { | ||
denormalize(input, unvisit) { | ||
let deleted = false; | ||
let found = true; | ||
if (input === undefined && this.schema) { | ||
[, found] = unvisit(undefined, this.schema); | ||
[, found, deleted] = unvisit(undefined, this.schema); | ||
} | ||
return [input && input.map ? input.map(entityOrId => this.denormalizeValue(entityOrId, unvisit)).filter(([, foundItem]) => foundItem).map(([value]) => value) : input, found]; | ||
return [input && input.map ? input.map(entityOrId => this.denormalizeValue(entityOrId, unvisit)).filter(filterEmpty).map(([value]) => value) : input, found, deleted]; | ||
} | ||
@@ -182,4 +193,5 @@ | ||
let found = true; | ||
let deleted = false; | ||
Object.keys(schema).forEach(key => { | ||
const [item, foundItem] = unvisit(object[key], schema[key]); | ||
const [item, foundItem, deletedItem] = unvisit(object[key], schema[key]); | ||
@@ -190,2 +202,6 @@ if (object[key] !== undefined) { | ||
if (deletedItem) { | ||
deleted = true; | ||
} | ||
if (!foundItem) { | ||
@@ -195,3 +211,3 @@ found = false; | ||
}); | ||
return [object, found]; | ||
return [object, found, deleted]; | ||
}; | ||
@@ -232,2 +248,9 @@ class ObjectSchema { | ||
} | ||
static toJSON() { | ||
return { | ||
name: this.name, | ||
schema: this.schema | ||
}; | ||
} | ||
/** Defines nested entities */ | ||
@@ -303,5 +326,6 @@ | ||
const object = Object.assign({}, input); | ||
let deleted = false; | ||
let found = true; | ||
Object.keys(this.schema).forEach(key => { | ||
const [item, foundItem] = unvisit(object[key], this.schema[key]); | ||
const [item, foundItem, deletedItem] = unvisit(object[key], this.schema[key]); | ||
@@ -317,5 +341,9 @@ if (object[key] !== undefined) { | ||
} | ||
if (deletedItem && !(key in instance && !instance[key])) { | ||
deleted = true; | ||
} | ||
}); // useDenormalized will memo based on entities, so creating a new object each time is fine | ||
return [this.fromJS(object), found]; | ||
return [this.fromJS(object), found, deleted]; | ||
} | ||
@@ -343,2 +371,7 @@ /* istanbul ignore next */ | ||
class Entity extends SimpleRecord { | ||
static toJSON() { | ||
return Object.assign({}, super.toJSON(), { | ||
key: this.key | ||
}); | ||
} | ||
/** | ||
@@ -351,2 +384,3 @@ * A unique identifier for each Entity | ||
/** Returns the globally unique identifier for the static Entity */ | ||
@@ -465,4 +499,4 @@ static get key() { | ||
if (isImmutable(entity)) { | ||
const [denormEntity, found] = denormalizeImmutable(this.schema, entity, unvisit); | ||
return [this.fromJS(denormEntity.toObject()), found]; | ||
const [denormEntity, found, deleted] = denormalizeImmutable(this.schema, entity, unvisit); | ||
return [this.fromJS(denormEntity.toObject()), found, deleted]; | ||
} // TODO: This creates unneeded memory pressure | ||
@@ -472,2 +506,3 @@ | ||
const instance = new this(); | ||
let deleted = false; | ||
let found = true; | ||
@@ -478,3 +513,3 @@ const denormEntity = entity; | ||
const input = this.hasDefined(entity, key) ? entity[key] : undefined; | ||
const [value, foundItem] = unvisit(input, schema); // members who default to falsy values are considered 'optional' | ||
const [value, foundItem, deletedItem] = unvisit(input, schema); // members who default to falsy values are considered 'optional' | ||
// if falsy value, and default is actually set then it is optional so pass through | ||
@@ -486,2 +521,6 @@ | ||
if (deletedItem && !(key in instance && !instance[key])) { | ||
deleted = true; | ||
} | ||
if (this.hasDefined(entity, key) && denormEntity[key] !== value) { | ||
@@ -491,7 +530,6 @@ denormEntity[key] = value; | ||
}); | ||
return [denormEntity, found]; | ||
return [denormEntity, found, deleted]; | ||
} | ||
} | ||
/* istanbul ignore next */ | ||
@@ -513,3 +551,3 @@ if (process.env.NODE_ENV !== 'production') { | ||
static denormalize(entity, unvisit) { | ||
return [entity, true]; | ||
return [entity, true, false]; | ||
} | ||
@@ -522,4 +560,8 @@ | ||
if (entity === DELETED) { | ||
return [undefined, true, true]; | ||
} | ||
if (typeof entity !== 'object' || entity === null) { | ||
return [entity, false]; | ||
return [entity, false, false]; | ||
} | ||
@@ -532,2 +574,3 @@ | ||
let found = true; | ||
let deleted = false; | ||
@@ -540,6 +583,6 @@ if (!cache[schema.key][id]) { | ||
cache[schema.key][id] = entityCopy; | ||
[cache[schema.key][id], found] = schema.denormalize(entityCopy, unvisit); | ||
[cache[schema.key][id], found, deleted] = schema.denormalize(entityCopy, unvisit); | ||
} | ||
return [cache[schema.key][id], found]; | ||
return [cache[schema.key][id], found, deleted]; | ||
}; | ||
@@ -551,8 +594,8 @@ | ||
return [function unvisit(input, schema) { | ||
if (!schema) return [input, true]; | ||
if (!schema) return [input, true, false]; | ||
if (!schema.denormalize || typeof schema.denormalize !== 'function') { | ||
if (typeof schema === 'function') { | ||
if (input instanceof schema) return [input, true]; | ||
return [new schema(input), true]; | ||
if (input instanceof schema) return [input, true, false]; | ||
return [new schema(input), true, false]; | ||
} else if (typeof schema === 'object') { | ||
@@ -566,3 +609,3 @@ const method = Array.isArray(schema) ? denormalize : denormalize$1; | ||
if (input === null) { | ||
return [input, true]; | ||
return [input, true, false]; | ||
} | ||
@@ -573,3 +616,3 @@ | ||
if (input === undefined) { | ||
return [input, false]; | ||
return [input, false, false]; | ||
} | ||
@@ -584,3 +627,3 @@ | ||
return [input, true]; | ||
return [input, true, false]; | ||
}, cache]; | ||
@@ -616,3 +659,3 @@ }; | ||
return [undefined, false, {}]; | ||
return [undefined, false, false, {}]; | ||
}; | ||
@@ -769,5 +812,6 @@ | ||
let found = true; | ||
let deleted = false; | ||
return [Object.keys(input).reduce((output, key) => { | ||
const entityOrId = input[key]; | ||
const [value, foundItem] = this.denormalizeValue(entityOrId, unvisit); | ||
const [value, foundItem, deletedItem] = this.denormalizeValue(entityOrId, unvisit); | ||
@@ -778,6 +822,11 @@ if (!foundItem) { | ||
if (deletedItem) { | ||
deleted = true; | ||
} | ||
if (!foundItem || deletedItem) return output; | ||
return Object.assign({}, output, { | ||
[key]: value | ||
}); | ||
}, {}), found]; | ||
}, {}), found, deleted]; | ||
} | ||
@@ -787,2 +836,47 @@ | ||
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */ | ||
class Delete { | ||
constructor(entity) { | ||
if (process.env.NODE_ENV !== 'production' && !entity) { | ||
throw new Error('Expected option "entity" not found on DeleteSchema.'); | ||
} | ||
this._entity = entity; | ||
} | ||
normalize(input, parent, key, visit, addEntity, visitedEntities) { | ||
// pass over already processed entities | ||
if (typeof input === 'string') return input; // TODO: what's store needs to be a differing type from fromJS | ||
const processedEntity = this._entity.fromJS(input, parent, key); | ||
const id = processedEntity.pk(parent, key); | ||
addEntity(this._entity, DELETED, processedEntity, parent, key); | ||
return id; | ||
} | ||
denormalize(id, unvisit) { | ||
return unvisit(id, this._entity); | ||
} | ||
/* istanbul ignore next */ | ||
_denormalizeNullable() { | ||
return []; | ||
} | ||
/* istanbul ignore next */ | ||
_normalizeNullable() { | ||
return []; | ||
} | ||
/* istanbul ignore next */ | ||
merge(existing, incoming) { | ||
return incoming; | ||
} | ||
} | ||
/* istanbul ignore file */ | ||
@@ -795,5 +889,6 @@ | ||
Array: ArraySchema, | ||
Object: ObjectSchema | ||
Object: ObjectSchema, | ||
Delete: Delete | ||
}); | ||
export { Entity, FlatEntity, SimpleRecord, denormalize$2 as denormalize, isEntity, normalize$2 as normalize, schema }; | ||
export { DELETED, Entity, FlatEntity, SimpleRecord, denormalize$2 as denormalize, isEntity, normalize$2 as normalize, schema }; |
@@ -1,1 +0,1 @@ | ||
function e(e){return!(!e||"function"!=typeof e.hasOwnProperty||!(Object.hasOwnProperty.call(e,"__ownerID")||e._map&&Object.hasOwnProperty.call(e._map,"__ownerID")))}function t(e,t,n){let r=!0;return[Object.keys(e).reduce((t,s)=>{const i=""+s,[o,c]=n(t.get(i),e[i]);return c||(r=!1),t.has(i)?t.set(i,o):t},t),r]}class n{constructor(e,t){t&&(this._schemaAttribute="string"==typeof t?e=>e[t]:t),this.define(e)}get isSingleSchema(){return!this._schemaAttribute}define(e){this.schema=e}getSchemaAttribute(e,t,n){return!this.isSingleSchema&&this._schemaAttribute(e,t,n)}inferSchema(e,t,n){if(this.isSingleSchema)return this.schema;const r=this.getSchemaAttribute(e,t,n);return this.schema[r]}normalizeValue(e,t,n,r,s,i){const o=this.inferSchema(e,t,n);if(!o)return e;const c=r(e,t,n,o,s,i);return this.isSingleSchema||null==c?c:{id:c,schema:this.getSchemaAttribute(e,t,n)}}denormalizeValue(t,n){const r=e(t)?t.get("schema"):t.schema;if(!this.isSingleSchema&&!r)return[t,!0];return n((this.isSingleSchema?void 0:e(t)?t.get("id"):t.id)||t,this.isSingleSchema?this.schema:this.schema[r])}}const r=e=>{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]},s=e=>Array.isArray(e)?e:Object.keys(e).map(t=>e[t]),i=(e,t,n,i,o,c,a)=>{e=r(e);return s(t).map((t,r)=>o(t,n,i,e,c,a))},o=(e,t,n)=>{e=r(e);let s=!0;return void 0===t&&e&&([,s]=n(void 0,e)),[t&&t.map?t.map(t=>n(t,e)).filter(([,e])=>e).map(([e])=>e):t,s]};const c=(e,t,n,r,s,i,o)=>{const c=Object.assign({},t);return Object.keys(e).forEach(n=>{const r=e[n],a=s(t[n],t,n,r,i,o);null==a?delete c[n]:c[n]=a}),c},a=(n,r,s)=>{if(e(r))return t(n,r,s);const i=Object.assign({},r);let o=!0;return Object.keys(n).forEach(e=>{const[t,r]=s(i[e],n[e]);void 0!==i[e]&&(i[e]=t),r||(o=!1)}),[i,o]};const u=Symbol("Defined Members"),h=Symbol("unq");class l{toString(){return this[h]}static fromJS(e={},t,n){const r=new this(e);return e instanceof l&&(e=e.constructor.toObjectDefined(e)),Object.assign(r,e),Object.defineProperty(r,u,{value:Object.keys(e),writable:!1}),Object.defineProperty(r,h,{value:""+Math.random(),writable:!1}),r}static merge(e,t){const n=Object.assign(this.toObjectDefined(e),this.toObjectDefined(t));return this.fromJS(n)}static hasDefined(e,t){return e[u].includes(t)}static toObjectDefined(e){const t={};for(const n of e[u])t[n]=e[n];return t}static keysDefined(e){return e[u]}static normalize(...e){return c(this.schema,...e)}static denormalize(e,t){const n=new this,r=Object.assign({},e);let s=!0;return Object.keys(this.schema).forEach(e=>{const[i,o]=t(r[e],this.schema[e]);void 0!==r[e]&&(r[e]=i),o||e in n&&!n[e]||(s=!1)}),[this.fromJS(r),s]}static asSchema(){return"development"===process.env.NODE_ENV&&console.error("asSchema() is deprecated - use Entity directly instead."),this}}l.schema={};class f extends l{static get key(){if("production"!==process.env.NODE_ENV&&(""===this.name||"Entity"===this.name))throw new Error("Entity classes without a name must define `static get key()`");return this.name}static pk(e,t,n){return this.prototype.pk.call(e,t,n)||n}static normalize(e,t,n,r,s,i){if("string"==typeof e)return e;const o=this.fromJS(e,t,n);if("production"!==process.env.NODE_ENV){const e=new this,t=new Set(Object.keys(e)),n=this.keysDefined(o),[r,s,i]=[[],[],[]];for(const e of n)t.has(e)?r.push(e):i.push(e);for(const e of t)r.includes(e)||s.push(e);if((Math.max(n.length/2,1)<=i.length&&t.size>Math.max(i.length,2)||r.length<Math.min(1,t.size/2))&&t.size){const e=new Error(`Attempted to initialize ${this.name} with substantially different than expected keys\n\n This is likely due to a malformed response.\n Try inspecting the network response or fetch() return value.\n\n Expected keys:\n Found: ${r}\n Missing: ${s}\n Unexpected keys: ${i}\n Value: ${JSON.stringify(this.toObjectDefined(o),null,2)}`);throw e.status=400,e}}const c=o.pk(t,n);if(void 0===c||""===c){if("production"!==process.env.NODE_ENV){const t=new Error(`Missing usable resource key when normalizing response.\n\n This is likely due to a malformed response.\n Try inspecting the network response or fetch() return value.\n\n Entity: ${this.name}\n Value: ${e&&JSON.stringify(e,null,2)}\n `);throw t.status=400,t}return}const a=this.key;return a in i||(i[a]={}),c in i[a]||(i[a][c]=[]),i[a][c].some(t=>t===e)||(i[a][c].push(e),Object.keys(this.schema).forEach(e=>{if(Object.hasOwnProperty.call(o,e)){const t=this.schema[e];o[e]=r(o[e],o,e,t,s,i)}}),s(this,o,o,t,n)),c}static denormalize(n,r){if(e(n)){const[e,s]=t(this.schema,n,r);return[this.fromJS(e.toObject()),s]}const s=new this;let i=!0;const o=n;return Object.keys(this.schema).forEach(e=>{const t=this.schema[e],c=this.hasDefined(n,e)?n[e]:void 0,[a,u]=r(c,t);u||e in s&&!s[e]||(i=!1),this.hasDefined(n,e)&&o[e]!==a&&(o[e]=a)}),[o,i]}}function m(e){return null!==e&&void 0!==e.pk}"production"!==process.env.NODE_ENV&&(f.fromJS=function(e){if(void 0===this.prototype.pk)throw new Error("cannot construct on abstract types");return l.fromJS.call(this,e)});class d extends f{static denormalize(e,t){return[e,!0]}}const p=t=>{const n={},r=y(t);return[function t(s,i){if(!i)return[s,!0];if(!i.denormalize||"function"!=typeof i.denormalize){if("function"==typeof i)return s instanceof i?[s,!0]:[new i(s),!0];if("object"==typeof i){return(Array.isArray(i)?o:a)(i,s,t)}}return null===s?[s,!0]:m(i)?void 0===s?[s,!1]:((t,n,r,s,i)=>{const o=s(t,n);if("object"!=typeof o||null===o)return[o,!1];i[n.key]||(i[n.key]={});let c=!0;if(!i[n.key][t]){const s=e(o)||o instanceof d?o:n.fromJS(o);i[n.key][t]=s,[i[n.key][t],c]=n.denormalize(s,r)}return[i[n.key][t],c]})(s,i,t,r,n):"function"==typeof i.denormalize?i.denormalize(s,t):[s,!0]},n]},y=t=>{const n=e(t);return(e,r)=>{const s=r.key;return"object"==typeof e?e:n?t.getIn([s,e]):t[s]&&t[s][e]}},b=(e,t,n)=>{if("production"!==process.env.NODE_ENV&&void 0===t)throw new Error("schema needed");if(void 0!==e){const[r,s]=p(n);return[...r(e,t),s]}return[void 0,!1,{}]},g=(e,t,n,r,s,o)=>{if(!e||!r||!["function","object"].includes(typeof r))return e;if(!r.normalize||"function"!=typeof r.normalize){if("function"==typeof r)return new r(e);return(Array.isArray(r)?i:c)(r,e,t,n,g,s,o)}return r.normalize(e,t,n,g,s,o)};const O=(e,t)=>{const n=function(e){return["object","function"].includes(typeof e)?"object":typeof e}(t);if(null===e||typeof e!==n){if("production"!==process.env.NODE_ENV){const r=e=>{try{return"string"!=typeof JSON.parse(e)}catch(e){return!1}};throw"string"==typeof e&&r(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/docs/guides/custom-networking 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 "${n}", 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 "${n}", found "${null===e?"null":typeof e}".`)}const r={},s={},i=((e,t)=>(n,r,s,i,o)=>{const c=n.key,a=n.pk(s,i,o);c in e||(e[c]={});const u=e[c][a];if(e[c][a]=u?n.merge(u,r):r,Array.isArray(n.indexes)){const r=e[c][a];c in t||(t[c]={});for(const e of n.indexes){e in t[c]||(t[c][e]={});const n=t[c][e];u&&delete n[u[e]],e in r?n[r[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(r,void 0,2)}`)}}})(r,s);return{entities:r,indexes:s,result:g(e,e,void 0,t,i,{})}};var S=Object.freeze({__proto__:null,Union:class extends n{constructor(e,t){if(!t)throw new Error('Expected option "schemaAttribute" not found on UnionSchema.');super(e,t)}normalize(e,t,n,r,s,i){return this.normalizeValue(e,t,n,r,s,i)}denormalize(e,t){return this.denormalizeValue(e,t)}},Values:class extends n{normalize(e,t,n,r,s,i){return Object.keys(e).reduce((t,n,o)=>{const c=e[n];return null!=c?Object.assign({},t,{[n]:this.normalizeValue(c,e,n,r,s,i)}):t},{})}denormalize(e,t){let n=!0;return[Object.keys(e).reduce((r,s)=>{const i=e[s],[o,c]=this.denormalizeValue(i,t);return c||(n=!1),Object.assign({},r,{[s]:o})},{}),n]}},Array:class extends n{normalize(e,t,n,r,i,o){return s(e).map((e,s)=>this.normalizeValue(e,t,n,r,i,o)).filter(e=>null!=e)}denormalize(e,t){let n=!0;return void 0===e&&this.schema&&([,n]=t(void 0,this.schema)),[e&&e.map?e.map(e=>this.denormalizeValue(e,t)).filter(([,e])=>e).map(([e])=>e):e,n]}},Object:class{constructor(e){this.define(e)}define(e){this.schema=Object.keys(e).reduce((t,n)=>{const r=e[n];return Object.assign({},t,{[n]:r})},this.schema||{})}normalize(...e){return c(this.schema,...e)}denormalize(...e){return a(this.schema,...e)}}});export{f as Entity,d as FlatEntity,l as SimpleRecord,b as denormalize,m as isEntity,O as normalize,S as schema}; | ||
function e(e){return!(!e||"function"!=typeof e.hasOwnProperty||!(Object.hasOwnProperty.call(e,"__ownerID")||e._map&&Object.hasOwnProperty.call(e._map,"__ownerID")))}function t(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]}class n{constructor(e,t){t&&(this._schemaAttribute="string"==typeof t?e=>e[t]:t),this.define(e)}get isSingleSchema(){return!this._schemaAttribute}define(e){this.schema=e}getSchemaAttribute(e,t,n){return!this.isSingleSchema&&this._schemaAttribute(e,t,n)}inferSchema(e,t,n){if(this.isSingleSchema)return this.schema;const r=this.getSchemaAttribute(e,t,n);return this.schema[r]}normalizeValue(e,t,n,r,i,s){const o=this.inferSchema(e,t,n);if(!o)return e;const c=r(e,t,n,o,i,s);return this.isSingleSchema||null==c?c:{id:c,schema:this.getSchemaAttribute(e,t,n)}}denormalizeValue(t,n){const r=e(t)?t.get("schema"):t.schema;if(!this.isSingleSchema&&!r)return[t,!0,!0];return n((this.isSingleSchema?void 0:e(t)?t.get("id"):t.id)||t,this.isSingleSchema?this.schema:this.schema[r])}}const r=Symbol("ENTITY WAS DELETED"),i=e=>{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]},s=e=>Array.isArray(e)?e:Object.keys(e).map(t=>e[t]),o=([,e,t])=>e&&!t,c=(e,t,n,r,o,c,a)=>{e=i(e);return s(t).map((t,i)=>o(t,n,r,e,c,a))},a=(e,t,n)=>{e=i(e);let r=!1,s=!0;return void 0===t&&e&&([,s,r]=n(void 0,e)),[t&&t.map?t.map(t=>n(t,e)).filter(o).map(([e])=>e):t,s,r]};const u=(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},h=(n,r,i)=>{if(e(r))return t(n,r,i);const s=Object.assign({},r);let o=!0,c=!1;return Object.keys(n).forEach(e=>{const[t,r,a]=i(s[e],n[e]);void 0!==s[e]&&(s[e]=t),a&&(c=!0),r||(o=!1)}),[s,o,c]};const l=Symbol("Defined Members"),m=Symbol("unq");class f{toString(){return this[m]}static toJSON(){return{name:this.name,schema:this.schema}}static fromJS(e={},t,n){const r=new this(e);return e instanceof f&&(e=e.constructor.toObjectDefined(e)),Object.assign(r,e),Object.defineProperty(r,l,{value:Object.keys(e),writable:!1}),Object.defineProperty(r,m,{value:""+Math.random(),writable:!1}),r}static merge(e,t){const n=Object.assign(this.toObjectDefined(e),this.toObjectDefined(t));return this.fromJS(n)}static hasDefined(e,t){return e[l].includes(t)}static toObjectDefined(e){const t={};for(const n of e[l])t[n]=e[n];return t}static keysDefined(e){return e[l]}static normalize(...e){return u(this.schema,...e)}static denormalize(e,t){const n=new this,r=Object.assign({},e);let i=!1,s=!0;return Object.keys(this.schema).forEach(e=>{const[o,c,a]=t(r[e],this.schema[e]);void 0!==r[e]&&(r[e]=o),c||e in n&&!n[e]||(s=!1),!a||e in n&&!n[e]||(i=!0)}),[this.fromJS(r),s,i]}static asSchema(){return"development"===process.env.NODE_ENV&&console.error("asSchema() is deprecated - use Entity directly instead."),this}}f.schema={};class d extends f{static toJSON(){return Object.assign({},super.toJSON(),{key:this.key})}static get key(){if("production"!==process.env.NODE_ENV&&(""===this.name||"Entity"===this.name))throw new Error("Entity classes without a name must define `static get key()`");return this.name}static pk(e,t,n){return this.prototype.pk.call(e,t,n)||n}static normalize(e,t,n,r,i,s){if("string"==typeof e)return e;const o=this.fromJS(e,t,n);if("production"!==process.env.NODE_ENV){const e=new this,t=new Set(Object.keys(e)),n=this.keysDefined(o),[r,i,s]=[[],[],[]];for(const e of n)t.has(e)?r.push(e):s.push(e);for(const e of t)r.includes(e)||i.push(e);if((Math.max(n.length/2,1)<=s.length&&t.size>Math.max(s.length,2)||r.length<Math.min(1,t.size/2))&&t.size){const e=new Error(`Attempted to initialize ${this.name} with substantially different than expected keys\n\n This is likely due to a malformed response.\n Try inspecting the network response or fetch() return value.\n\n Expected keys:\n Found: ${r}\n Missing: ${i}\n Unexpected keys: ${s}\n Value: ${JSON.stringify(this.toObjectDefined(o),null,2)}`);throw e.status=400,e}}const c=o.pk(t,n);if(void 0===c||""===c){if("production"!==process.env.NODE_ENV){const t=new Error(`Missing usable resource key when normalizing response.\n\n This is likely due to a malformed response.\n Try inspecting the network response or fetch() return value.\n\n Entity: ${this.name}\n Value: ${e&&JSON.stringify(e,null,2)}\n `);throw t.status=400,t}return}const a=this.key;return a in s||(s[a]={}),c in s[a]||(s[a][c]=[]),s[a][c].some(t=>t===e)||(s[a][c].push(e),Object.keys(this.schema).forEach(e=>{if(Object.hasOwnProperty.call(o,e)){const t=this.schema[e];o[e]=r(o[e],o,e,t,i,s)}}),i(this,o,o,t,n)),c}static denormalize(n,r){if(e(n)){const[e,i,s]=t(this.schema,n,r);return[this.fromJS(e.toObject()),i,s]}const i=new this;let s=!1,o=!0;const c=n;return Object.keys(this.schema).forEach(e=>{const t=this.schema[e],a=this.hasDefined(n,e)?n[e]:void 0,[u,h,l]=r(a,t);h||e in i&&!i[e]||(o=!1),!l||e in i&&!i[e]||(s=!0),this.hasDefined(n,e)&&c[e]!==u&&(c[e]=u)}),[c,o,s]}}function p(e){return null!==e&&void 0!==e.pk}"production"!==process.env.NODE_ENV&&(d.fromJS=function(e){if(void 0===this.prototype.pk)throw new Error("cannot construct on abstract types");return f.fromJS.call(this,e)});class y extends d{static denormalize(e,t){return[e,!0,!1]}}const b=t=>{const n={},i=g(t);return[function t(s,o){if(!o)return[s,!0,!1];if(!o.denormalize||"function"!=typeof o.denormalize){if("function"==typeof o)return s instanceof o?[s,!0,!1]:[new o(s),!0,!1];if("object"==typeof o){return(Array.isArray(o)?a:h)(o,s,t)}}return null===s?[s,!0,!1]:p(o)?void 0===s?[s,!1,!1]:((t,n,i,s,o)=>{const c=s(t,n);if(c===r)return[void 0,!0,!0];if("object"!=typeof c||null===c)return[c,!1,!1];o[n.key]||(o[n.key]={});let a=!0,u=!1;if(!o[n.key][t]){const r=e(c)||c instanceof y?c:n.fromJS(c);o[n.key][t]=r,[o[n.key][t],a,u]=n.denormalize(r,i)}return[o[n.key][t],a,u]})(s,o,t,i,n):"function"==typeof o.denormalize?o.denormalize(s,t):[s,!0,!1]},n]},g=t=>{const n=e(t);return(e,r)=>{const i=r.key;return"object"==typeof e?e:n?t.getIn([i,e]):t[i]&&t[i][e]}},O=(e,t,n)=>{if("production"!==process.env.NODE_ENV&&void 0===t)throw new Error("schema needed");if(void 0!==e){const[r,i]=b(n);return[...r(e,t),i]}return[void 0,!1,!1,{}]},S=(e,t,n,r,i,s)=>{if(!e||!r||!["function","object"].includes(typeof r))return e;if(!r.normalize||"function"!=typeof r.normalize){if("function"==typeof r)return new r(e);return(Array.isArray(r)?c:u)(r,e,t,n,S,i,s)}return r.normalize(e,t,n,S,i,s)};const E=(e,t)=>{const n=function(e){return["object","function"].includes(typeof e)?"object":typeof e}(t);if(null===e||typeof e!==n){if("production"!==process.env.NODE_ENV){const r=e=>{try{return"string"!=typeof JSON.parse(e)}catch(e){return!1}};throw"string"==typeof e&&r(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/docs/guides/custom-networking 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 "${n}", 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 "${n}", found "${null===e?"null":typeof e}".`)}const r={},i={},s=((e,t)=>(n,r,i,s,o)=>{const c=n.key,a=n.pk(i,s,o);c in e||(e[c]={});const u=e[c][a];if(e[c][a]=u?n.merge(u,r):r,Array.isArray(n.indexes)){const r=e[c][a];c in t||(t[c]={});for(const e of n.indexes){e in t[c]||(t[c][e]={});const n=t[c][e];u&&delete n[u[e]],e in r?n[r[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(r,void 0,2)}`)}}})(r,i);return{entities:r,indexes:i,result:S(e,e,void 0,t,s,{})}};var k=Object.freeze({__proto__:null,Union:class extends n{constructor(e,t){if(!t)throw new Error('Expected option "schemaAttribute" not found on UnionSchema.');super(e,t)}normalize(e,t,n,r,i,s){return this.normalizeValue(e,t,n,r,i,s)}denormalize(e,t){return this.denormalizeValue(e,t)}},Values:class extends n{normalize(e,t,n,r,i,s){return Object.keys(e).reduce((t,n,o)=>{const c=e[n];return null!=c?Object.assign({},t,{[n]:this.normalizeValue(c,e,n,r,i,s)}):t},{})}denormalize(e,t){let n=!0,r=!1;return[Object.keys(e).reduce((i,s)=>{const o=e[s],[c,a,u]=this.denormalizeValue(o,t);return a||(n=!1),u&&(r=!0),!a||u?i:Object.assign({},i,{[s]:c})},{}),n,r]}},Array:class extends n{normalize(e,t,n,r,i,o){return s(e).map((e,s)=>this.normalizeValue(e,t,n,r,i,o)).filter(e=>null!=e)}denormalize(e,t){let n=!1,r=!0;return void 0===e&&this.schema&&([,r,n]=t(void 0,this.schema)),[e&&e.map?e.map(e=>this.denormalizeValue(e,t)).filter(o).map(([e])=>e):e,r,n]}},Object:class{constructor(e){this.define(e)}define(e){this.schema=Object.keys(e).reduce((t,n)=>{const r=e[n];return Object.assign({},t,{[n]:r})},this.schema||{})}normalize(...e){return u(this.schema,...e)}denormalize(...e){return h(this.schema,...e)}},Delete:class{constructor(e){if("production"!==process.env.NODE_ENV&&!e)throw new Error('Expected option "entity" not found on DeleteSchema.');this._entity=e}normalize(e,t,n,i,s,o){if("string"==typeof e)return e;const c=this._entity.fromJS(e,t,n),a=c.pk(t,n);return s(this._entity,r,c,t,n),a}denormalize(e,t){return t(e,this._entity)}_denormalizeNullable(){return[]}_normalizeNullable(){return[]}merge(e,t){return t}}});export{r as DELETED,d as Entity,y as FlatEntity,f as SimpleRecord,O as denormalize,p as isEntity,E as normalize,k as schema}; |
@@ -33,2 +33,3 @@ 'use strict'; | ||
let found = true; | ||
let deleted = false; | ||
return [Object.keys(schema).reduce((object, key) => { | ||
@@ -38,3 +39,3 @@ // Immutable maps cast keys to strings on write so we need to ensure | ||
const stringKey = `${key}`; | ||
const [item, foundItem] = unvisit(object.get(stringKey), schema[stringKey]); | ||
const [item, foundItem, deletedItem] = unvisit(object.get(stringKey), schema[stringKey]); | ||
@@ -45,2 +46,6 @@ if (!foundItem) { | ||
if (deletedItem) { | ||
deleted = true; | ||
} | ||
if (object.has(stringKey)) { | ||
@@ -51,3 +56,3 @@ return object.set(stringKey, item); | ||
} | ||
}, input), found]; | ||
}, input), found, deleted]; | ||
} | ||
@@ -103,3 +108,3 @@ | ||
if (!this.isSingleSchema && !schemaKey) { | ||
return [value, true]; | ||
return [value, true, true]; | ||
} | ||
@@ -114,2 +119,4 @@ | ||
const DELETED = Symbol('ENTITY WAS DELETED'); | ||
const validateSchema = definition => { | ||
@@ -127,2 +134,4 @@ const isArray = Array.isArray(definition); | ||
const filterEmpty = ([, foundItem, deletedItem]) => foundItem && !deletedItem; | ||
const normalize = (schema, input, parent, key, visit, addEntity, visitedEntities) => { | ||
@@ -137,9 +146,10 @@ schema = validateSchema(schema); | ||
schema = validateSchema(schema); | ||
let deleted = false; | ||
let found = true; | ||
if (input === undefined && schema) { | ||
[, found] = unvisit(undefined, schema); | ||
[, found, deleted] = unvisit(undefined, schema); | ||
} | ||
return [input && input.map ? input.map(entityOrId => unvisit(entityOrId, schema)).filter(([, foundItem]) => foundItem).map(([value]) => value) : input, found]; | ||
return [input && input.map ? input.map(entityOrId => unvisit(entityOrId, schema)).filter(filterEmpty).map(([value]) => value) : input, found, deleted]; | ||
}; | ||
@@ -153,9 +163,10 @@ class ArraySchema extends PolymorphicSchema { | ||
denormalize(input, unvisit) { | ||
let deleted = false; | ||
let found = true; | ||
if (input === undefined && this.schema) { | ||
[, found] = unvisit(undefined, this.schema); | ||
[, found, deleted] = unvisit(undefined, this.schema); | ||
} | ||
return [input && input.map ? input.map(entityOrId => this.denormalizeValue(entityOrId, unvisit)).filter(([, foundItem]) => foundItem).map(([value]) => value) : input, found]; | ||
return [input && input.map ? input.map(entityOrId => this.denormalizeValue(entityOrId, unvisit)).filter(filterEmpty).map(([value]) => value) : input, found, deleted]; | ||
} | ||
@@ -188,4 +199,5 @@ | ||
let found = true; | ||
let deleted = false; | ||
Object.keys(schema).forEach(key => { | ||
const [item, foundItem] = unvisit(object[key], schema[key]); | ||
const [item, foundItem, deletedItem] = unvisit(object[key], schema[key]); | ||
@@ -196,2 +208,6 @@ if (object[key] !== undefined) { | ||
if (deletedItem) { | ||
deleted = true; | ||
} | ||
if (!foundItem) { | ||
@@ -201,3 +217,3 @@ found = false; | ||
}); | ||
return [object, found]; | ||
return [object, found, deleted]; | ||
}; | ||
@@ -238,2 +254,9 @@ class ObjectSchema { | ||
} | ||
static toJSON() { | ||
return { | ||
name: this.name, | ||
schema: this.schema | ||
}; | ||
} | ||
/** Defines nested entities */ | ||
@@ -310,5 +333,6 @@ | ||
}; | ||
let deleted = false; | ||
let found = true; | ||
Object.keys(this.schema).forEach(key => { | ||
const [item, foundItem] = unvisit(object[key], this.schema[key]); | ||
const [item, foundItem, deletedItem] = unvisit(object[key], this.schema[key]); | ||
@@ -324,5 +348,9 @@ if (object[key] !== undefined) { | ||
} | ||
if (deletedItem && !(key in instance && !instance[key])) { | ||
deleted = true; | ||
} | ||
}); // useDenormalized will memo based on entities, so creating a new object each time is fine | ||
return [this.fromJS(object), found]; | ||
return [this.fromJS(object), found, deleted]; | ||
} | ||
@@ -350,2 +378,7 @@ /* istanbul ignore next */ | ||
class Entity extends SimpleRecord { | ||
static toJSON() { | ||
return { ...super.toJSON(), | ||
key: this.key | ||
}; | ||
} | ||
/** | ||
@@ -358,2 +391,3 @@ * A unique identifier for each Entity | ||
/** Returns the globally unique identifier for the static Entity */ | ||
@@ -472,4 +506,4 @@ static get key() { | ||
if (isImmutable(entity)) { | ||
const [denormEntity, found] = denormalizeImmutable(this.schema, entity, unvisit); | ||
return [this.fromJS(denormEntity.toObject()), found]; | ||
const [denormEntity, found, deleted] = denormalizeImmutable(this.schema, entity, unvisit); | ||
return [this.fromJS(denormEntity.toObject()), found, deleted]; | ||
} // TODO: This creates unneeded memory pressure | ||
@@ -479,2 +513,3 @@ | ||
const instance = new this(); | ||
let deleted = false; | ||
let found = true; | ||
@@ -485,3 +520,3 @@ const denormEntity = entity; | ||
const input = this.hasDefined(entity, key) ? entity[key] : undefined; | ||
const [value, foundItem] = unvisit(input, schema); // members who default to falsy values are considered 'optional' | ||
const [value, foundItem, deletedItem] = unvisit(input, schema); // members who default to falsy values are considered 'optional' | ||
// if falsy value, and default is actually set then it is optional so pass through | ||
@@ -493,2 +528,6 @@ | ||
if (deletedItem && !(key in instance && !instance[key])) { | ||
deleted = true; | ||
} | ||
if (this.hasDefined(entity, key) && denormEntity[key] !== value) { | ||
@@ -498,7 +537,6 @@ denormEntity[key] = value; | ||
}); | ||
return [denormEntity, found]; | ||
return [denormEntity, found, deleted]; | ||
} | ||
} | ||
/* istanbul ignore next */ | ||
@@ -520,3 +558,3 @@ if (process.env.NODE_ENV !== 'production') { | ||
static denormalize(entity, unvisit) { | ||
return [entity, true]; | ||
return [entity, true, false]; | ||
} | ||
@@ -529,4 +567,8 @@ | ||
if (entity === DELETED) { | ||
return [undefined, true, true]; | ||
} | ||
if (typeof entity !== 'object' || entity === null) { | ||
return [entity, false]; | ||
return [entity, false, false]; | ||
} | ||
@@ -539,2 +581,3 @@ | ||
let found = true; | ||
let deleted = false; | ||
@@ -547,6 +590,6 @@ if (!cache[schema.key][id]) { | ||
cache[schema.key][id] = entityCopy; | ||
[cache[schema.key][id], found] = schema.denormalize(entityCopy, unvisit); | ||
[cache[schema.key][id], found, deleted] = schema.denormalize(entityCopy, unvisit); | ||
} | ||
return [cache[schema.key][id], found]; | ||
return [cache[schema.key][id], found, deleted]; | ||
}; | ||
@@ -558,8 +601,8 @@ | ||
return [function unvisit(input, schema) { | ||
if (!schema) return [input, true]; | ||
if (!schema) return [input, true, false]; | ||
if (!schema.denormalize || typeof schema.denormalize !== 'function') { | ||
if (typeof schema === 'function') { | ||
if (input instanceof schema) return [input, true]; | ||
return [new schema(input), true]; | ||
if (input instanceof schema) return [input, true, false]; | ||
return [new schema(input), true, false]; | ||
} else if (typeof schema === 'object') { | ||
@@ -573,3 +616,3 @@ const method = Array.isArray(schema) ? denormalize : denormalize$1; | ||
if (input === null) { | ||
return [input, true]; | ||
return [input, true, false]; | ||
} | ||
@@ -580,3 +623,3 @@ | ||
if (input === undefined) { | ||
return [input, false]; | ||
return [input, false, false]; | ||
} | ||
@@ -591,3 +634,3 @@ | ||
return [input, true]; | ||
return [input, true, false]; | ||
}, cache]; | ||
@@ -623,3 +666,3 @@ }; | ||
return [undefined, false, {}]; | ||
return [undefined, false, false, {}]; | ||
}; | ||
@@ -776,5 +819,6 @@ | ||
let found = true; | ||
let deleted = false; | ||
return [Object.keys(input).reduce((output, key) => { | ||
const entityOrId = input[key]; | ||
const [value, foundItem] = this.denormalizeValue(entityOrId, unvisit); | ||
const [value, foundItem, deletedItem] = this.denormalizeValue(entityOrId, unvisit); | ||
@@ -785,6 +829,11 @@ if (!foundItem) { | ||
if (deletedItem) { | ||
deleted = true; | ||
} | ||
if (!foundItem || deletedItem) return output; | ||
return { ...output, | ||
[key]: value | ||
}; | ||
}, {}), found]; | ||
}, {}), found, deleted]; | ||
} | ||
@@ -794,2 +843,47 @@ | ||
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */ | ||
class Delete { | ||
constructor(entity) { | ||
if (process.env.NODE_ENV !== 'production' && !entity) { | ||
throw new Error('Expected option "entity" not found on DeleteSchema.'); | ||
} | ||
this._entity = entity; | ||
} | ||
normalize(input, parent, key, visit, addEntity, visitedEntities) { | ||
// pass over already processed entities | ||
if (typeof input === 'string') return input; // TODO: what's store needs to be a differing type from fromJS | ||
const processedEntity = this._entity.fromJS(input, parent, key); | ||
const id = processedEntity.pk(parent, key); | ||
addEntity(this._entity, DELETED, processedEntity, parent, key); | ||
return id; | ||
} | ||
denormalize(id, unvisit) { | ||
return unvisit(id, this._entity); | ||
} | ||
/* istanbul ignore next */ | ||
_denormalizeNullable() { | ||
return []; | ||
} | ||
/* istanbul ignore next */ | ||
_normalizeNullable() { | ||
return []; | ||
} | ||
/* istanbul ignore next */ | ||
merge(existing, incoming) { | ||
return incoming; | ||
} | ||
} | ||
/* istanbul ignore file */ | ||
@@ -802,5 +896,7 @@ | ||
Array: ArraySchema, | ||
Object: ObjectSchema | ||
Object: ObjectSchema, | ||
Delete: Delete | ||
}); | ||
exports.DELETED = DELETED; | ||
exports.Entity = Entity; | ||
@@ -807,0 +903,0 @@ exports.FlatEntity = FlatEntity; |
@@ -1,1 +0,1 @@ | ||
"use strict";function e(e){return!(!e||"function"!=typeof e.hasOwnProperty||!(Object.hasOwnProperty.call(e,"__ownerID")||e._map&&Object.hasOwnProperty.call(e._map,"__ownerID")))}function t(e,t,n){let r=!0;return[Object.keys(e).reduce((t,s)=>{const i=""+s,[o,c]=n(t.get(i),e[i]);return c||(r=!1),t.has(i)?t.set(i,o):t},t),r]}Object.defineProperty(exports,"__esModule",{value:!0});class n{constructor(e,t){t&&(this._schemaAttribute="string"==typeof t?e=>e[t]:t),this.define(e)}get isSingleSchema(){return!this._schemaAttribute}define(e){this.schema=e}getSchemaAttribute(e,t,n){return!this.isSingleSchema&&this._schemaAttribute(e,t,n)}inferSchema(e,t,n){if(this.isSingleSchema)return this.schema;const r=this.getSchemaAttribute(e,t,n);return this.schema[r]}normalizeValue(e,t,n,r,s,i){const o=this.inferSchema(e,t,n);if(!o)return e;const c=r(e,t,n,o,s,i);return this.isSingleSchema||null==c?c:{id:c,schema:this.getSchemaAttribute(e,t,n)}}denormalizeValue(t,n){const r=e(t)?t.get("schema"):t.schema;if(!this.isSingleSchema&&!r)return[t,!0];return n((this.isSingleSchema?void 0:e(t)?t.get("id"):t.id)||t,this.isSingleSchema?this.schema:this.schema[r])}}const r=e=>{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]},s=e=>Array.isArray(e)?e:Object.keys(e).map(t=>e[t]),i=(e,t,n,i,o,c,a)=>{e=r(e);return s(t).map((t,r)=>o(t,n,i,e,c,a))},o=(e,t,n)=>{e=r(e);let s=!0;return void 0===t&&e&&([,s]=n(void 0,e)),[t&&t.map?t.map(t=>n(t,e)).filter(([,e])=>e).map(([e])=>e):t,s]};const c=(e,t,n,r,s,i,o)=>{const c=Object.assign({},t);return Object.keys(e).forEach(n=>{const r=e[n],a=s(t[n],t,n,r,i,o);null==a?delete c[n]:c[n]=a}),c},a=(n,r,s)=>{if(e(r))return t(n,r,s);const i=Object.assign({},r);let o=!0;return Object.keys(n).forEach(e=>{const[t,r]=s(i[e],n[e]);void 0!==i[e]&&(i[e]=t),r||(o=!1)}),[i,o]};const u=Symbol("Defined Members"),h=Symbol("unq");class l{toString(){return this[h]}static fromJS(e={},t,n){const r=new this(e);return e instanceof l&&(e=e.constructor.toObjectDefined(e)),Object.assign(r,e),Object.defineProperty(r,u,{value:Object.keys(e),writable:!1}),Object.defineProperty(r,h,{value:""+Math.random(),writable:!1}),r}static merge(e,t){const n=Object.assign(this.toObjectDefined(e),this.toObjectDefined(t));return this.fromJS(n)}static hasDefined(e,t){return e[u].includes(t)}static toObjectDefined(e){const t={};for(const n of e[u])t[n]=e[n];return t}static keysDefined(e){return e[u]}static normalize(...e){return c(this.schema,...e)}static denormalize(e,t){const n=new this,r=Object.assign({},e);let s=!0;return Object.keys(this.schema).forEach(e=>{const[i,o]=t(r[e],this.schema[e]);void 0!==r[e]&&(r[e]=i),o||e in n&&!n[e]||(s=!1)}),[this.fromJS(r),s]}static asSchema(){return"development"===process.env.NODE_ENV&&console.error("asSchema() is deprecated - use Entity directly instead."),this}}l.schema={};class f extends l{static get key(){if("production"!==process.env.NODE_ENV&&(""===this.name||"Entity"===this.name))throw new Error("Entity classes without a name must define `static get key()`");return this.name}static pk(e,t,n){return this.prototype.pk.call(e,t,n)||n}static normalize(e,t,n,r,s,i){if("string"==typeof e)return e;const o=this.fromJS(e,t,n);if("production"!==process.env.NODE_ENV){const e=new this,t=new Set(Object.keys(e)),n=this.keysDefined(o),[r,s,i]=[[],[],[]];for(const e of n)t.has(e)?r.push(e):i.push(e);for(const e of t)r.includes(e)||s.push(e);if((Math.max(n.length/2,1)<=i.length&&t.size>Math.max(i.length,2)||r.length<Math.min(1,t.size/2))&&t.size){const e=new Error(`Attempted to initialize ${this.name} with substantially different than expected keys\n\n This is likely due to a malformed response.\n Try inspecting the network response or fetch() return value.\n\n Expected keys:\n Found: ${r}\n Missing: ${s}\n Unexpected keys: ${i}\n Value: ${JSON.stringify(this.toObjectDefined(o),null,2)}`);throw e.status=400,e}}const c=o.pk(t,n);if(void 0===c||""===c){if("production"!==process.env.NODE_ENV){const t=new Error(`Missing usable resource key when normalizing response.\n\n This is likely due to a malformed response.\n Try inspecting the network response or fetch() return value.\n\n Entity: ${this.name}\n Value: ${e&&JSON.stringify(e,null,2)}\n `);throw t.status=400,t}return}const a=this.key;return a in i||(i[a]={}),c in i[a]||(i[a][c]=[]),i[a][c].some(t=>t===e)||(i[a][c].push(e),Object.keys(this.schema).forEach(e=>{if(Object.hasOwnProperty.call(o,e)){const t=this.schema[e];o[e]=r(o[e],o,e,t,s,i)}}),s(this,o,o,t,n)),c}static denormalize(n,r){if(e(n)){const[e,s]=t(this.schema,n,r);return[this.fromJS(e.toObject()),s]}const s=new this;let i=!0;const o=n;return Object.keys(this.schema).forEach(e=>{const t=this.schema[e],c=this.hasDefined(n,e)?n[e]:void 0,[a,u]=r(c,t);u||e in s&&!s[e]||(i=!1),this.hasDefined(n,e)&&o[e]!==a&&(o[e]=a)}),[o,i]}}function m(e){return null!==e&&void 0!==e.pk}"production"!==process.env.NODE_ENV&&(f.fromJS=function(e){if(void 0===this.prototype.pk)throw new Error("cannot construct on abstract types");return l.fromJS.call(this,e)});class d extends f{static denormalize(e,t){return[e,!0]}}const p=t=>{const n={},r=y(t);return[function t(s,i){if(!i)return[s,!0];if(!i.denormalize||"function"!=typeof i.denormalize){if("function"==typeof i)return s instanceof i?[s,!0]:[new i(s),!0];if("object"==typeof i){return(Array.isArray(i)?o:a)(i,s,t)}}return null===s?[s,!0]:m(i)?void 0===s?[s,!1]:((t,n,r,s,i)=>{const o=s(t,n);if("object"!=typeof o||null===o)return[o,!1];i[n.key]||(i[n.key]={});let c=!0;if(!i[n.key][t]){const s=e(o)||o instanceof d?o:n.fromJS(o);i[n.key][t]=s,[i[n.key][t],c]=n.denormalize(s,r)}return[i[n.key][t],c]})(s,i,t,r,n):"function"==typeof i.denormalize?i.denormalize(s,t):[s,!0]},n]},y=t=>{const n=e(t);return(e,r)=>{const s=r.key;return"object"==typeof e?e:n?t.getIn([s,e]):t[s]&&t[s][e]}},b=(e,t,n,r,s,o)=>{if(!e||!r||!["function","object"].includes(typeof r))return e;if(!r.normalize||"function"!=typeof r.normalize){if("function"==typeof r)return new r(e);return(Array.isArray(r)?i:c)(r,e,t,n,b,s,o)}return r.normalize(e,t,n,b,s,o)};var g=Object.freeze({__proto__:null,Union:class extends n{constructor(e,t){if(!t)throw new Error('Expected option "schemaAttribute" not found on UnionSchema.');super(e,t)}normalize(e,t,n,r,s,i){return this.normalizeValue(e,t,n,r,s,i)}denormalize(e,t){return this.denormalizeValue(e,t)}},Values:class extends n{normalize(e,t,n,r,s,i){return Object.keys(e).reduce((t,n,o)=>{const c=e[n];return null!=c?Object.assign({},t,{[n]:this.normalizeValue(c,e,n,r,s,i)}):t},{})}denormalize(e,t){let n=!0;return[Object.keys(e).reduce((r,s)=>{const i=e[s],[o,c]=this.denormalizeValue(i,t);return c||(n=!1),Object.assign({},r,{[s]:o})},{}),n]}},Array:class extends n{normalize(e,t,n,r,i,o){return s(e).map((e,s)=>this.normalizeValue(e,t,n,r,i,o)).filter(e=>null!=e)}denormalize(e,t){let n=!0;return void 0===e&&this.schema&&([,n]=t(void 0,this.schema)),[e&&e.map?e.map(e=>this.denormalizeValue(e,t)).filter(([,e])=>e).map(([e])=>e):e,n]}},Object:class{constructor(e){this.define(e)}define(e){this.schema=Object.keys(e).reduce((t,n)=>{const r=e[n];return Object.assign({},t,{[n]:r})},this.schema||{})}normalize(...e){return c(this.schema,...e)}denormalize(...e){return a(this.schema,...e)}}});exports.Entity=f,exports.FlatEntity=d,exports.SimpleRecord=l,exports.denormalize=(e,t,n)=>{if("production"!==process.env.NODE_ENV&&void 0===t)throw new Error("schema needed");if(void 0!==e){const[r,s]=p(n);return[...r(e,t),s]}return[void 0,!1,{}]},exports.isEntity=m,exports.normalize=(e,t)=>{const n=function(e){return["object","function"].includes(typeof e)?"object":typeof e}(t);if(null===e||typeof e!==n){if("production"!==process.env.NODE_ENV){const r=e=>{try{return"string"!=typeof JSON.parse(e)}catch(e){return!1}};throw"string"==typeof e&&r(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/docs/guides/custom-networking 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 "${n}", 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 "${n}", found "${null===e?"null":typeof e}".`)}const r={},s={},i=((e,t)=>(n,r,s,i,o)=>{const c=n.key,a=n.pk(s,i,o);c in e||(e[c]={});const u=e[c][a];if(e[c][a]=u?n.merge(u,r):r,Array.isArray(n.indexes)){const r=e[c][a];c in t||(t[c]={});for(const e of n.indexes){e in t[c]||(t[c][e]={});const n=t[c][e];u&&delete n[u[e]],e in r?n[r[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(r,void 0,2)}`)}}})(r,s);return{entities:r,indexes:s,result:b(e,e,void 0,t,i,{})}},exports.schema=g; | ||
"use strict";function e(e){return!(!e||"function"!=typeof e.hasOwnProperty||!(Object.hasOwnProperty.call(e,"__ownerID")||e._map&&Object.hasOwnProperty.call(e._map,"__ownerID")))}function t(e,t,n){let r=!0,s=!1;return[Object.keys(e).reduce((t,i)=>{const o=""+i,[c,a,u]=n(t.get(o),e[o]);return a||(r=!1),u&&(s=!0),t.has(o)?t.set(o,c):t},t),r,s]}Object.defineProperty(exports,"__esModule",{value:!0});class n{constructor(e,t){t&&(this._schemaAttribute="string"==typeof t?e=>e[t]:t),this.define(e)}get isSingleSchema(){return!this._schemaAttribute}define(e){this.schema=e}getSchemaAttribute(e,t,n){return!this.isSingleSchema&&this._schemaAttribute(e,t,n)}inferSchema(e,t,n){if(this.isSingleSchema)return this.schema;const r=this.getSchemaAttribute(e,t,n);return this.schema[r]}normalizeValue(e,t,n,r,s,i){const o=this.inferSchema(e,t,n);if(!o)return e;const c=r(e,t,n,o,s,i);return this.isSingleSchema||null==c?c:{id:c,schema:this.getSchemaAttribute(e,t,n)}}denormalizeValue(t,n){const r=e(t)?t.get("schema"):t.schema;if(!this.isSingleSchema&&!r)return[t,!0,!0];return n((this.isSingleSchema?void 0:e(t)?t.get("id"):t.id)||t,this.isSingleSchema?this.schema:this.schema[r])}}const r=Symbol("ENTITY WAS DELETED"),s=e=>{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]},i=e=>Array.isArray(e)?e:Object.keys(e).map(t=>e[t]),o=([,e,t])=>e&&!t,c=(e,t,n,r,o,c,a)=>{e=s(e);return i(t).map((t,s)=>o(t,n,r,e,c,a))},a=(e,t,n)=>{e=s(e);let r=!1,i=!0;return void 0===t&&e&&([,i,r]=n(void 0,e)),[t&&t.map?t.map(t=>n(t,e)).filter(o).map(([e])=>e):t,i,r]};const u=(e,t,n,r,s,i,o)=>{const c=Object.assign({},t);return Object.keys(e).forEach(n=>{const r=e[n],a=s(t[n],t,n,r,i,o);null==a?delete c[n]:c[n]=a}),c},h=(n,r,s)=>{if(e(r))return t(n,r,s);const i=Object.assign({},r);let o=!0,c=!1;return Object.keys(n).forEach(e=>{const[t,r,a]=s(i[e],n[e]);void 0!==i[e]&&(i[e]=t),a&&(c=!0),r||(o=!1)}),[i,o,c]};const l=Symbol("Defined Members"),m=Symbol("unq");class f{toString(){return this[m]}static toJSON(){return{name:this.name,schema:this.schema}}static fromJS(e={},t,n){const r=new this(e);return e instanceof f&&(e=e.constructor.toObjectDefined(e)),Object.assign(r,e),Object.defineProperty(r,l,{value:Object.keys(e),writable:!1}),Object.defineProperty(r,m,{value:""+Math.random(),writable:!1}),r}static merge(e,t){const n=Object.assign(this.toObjectDefined(e),this.toObjectDefined(t));return this.fromJS(n)}static hasDefined(e,t){return e[l].includes(t)}static toObjectDefined(e){const t={};for(const n of e[l])t[n]=e[n];return t}static keysDefined(e){return e[l]}static normalize(...e){return u(this.schema,...e)}static denormalize(e,t){const n=new this,r=Object.assign({},e);let s=!1,i=!0;return Object.keys(this.schema).forEach(e=>{const[o,c,a]=t(r[e],this.schema[e]);void 0!==r[e]&&(r[e]=o),c||e in n&&!n[e]||(i=!1),!a||e in n&&!n[e]||(s=!0)}),[this.fromJS(r),i,s]}static asSchema(){return"development"===process.env.NODE_ENV&&console.error("asSchema() is deprecated - use Entity directly instead."),this}}f.schema={};class d extends f{static toJSON(){return Object.assign({},super.toJSON(),{key:this.key})}static get key(){if("production"!==process.env.NODE_ENV&&(""===this.name||"Entity"===this.name))throw new Error("Entity classes without a name must define `static get key()`");return this.name}static pk(e,t,n){return this.prototype.pk.call(e,t,n)||n}static normalize(e,t,n,r,s,i){if("string"==typeof e)return e;const o=this.fromJS(e,t,n);if("production"!==process.env.NODE_ENV){const e=new this,t=new Set(Object.keys(e)),n=this.keysDefined(o),[r,s,i]=[[],[],[]];for(const e of n)t.has(e)?r.push(e):i.push(e);for(const e of t)r.includes(e)||s.push(e);if((Math.max(n.length/2,1)<=i.length&&t.size>Math.max(i.length,2)||r.length<Math.min(1,t.size/2))&&t.size){const e=new Error(`Attempted to initialize ${this.name} with substantially different than expected keys\n\n This is likely due to a malformed response.\n Try inspecting the network response or fetch() return value.\n\n Expected keys:\n Found: ${r}\n Missing: ${s}\n Unexpected keys: ${i}\n Value: ${JSON.stringify(this.toObjectDefined(o),null,2)}`);throw e.status=400,e}}const c=o.pk(t,n);if(void 0===c||""===c){if("production"!==process.env.NODE_ENV){const t=new Error(`Missing usable resource key when normalizing response.\n\n This is likely due to a malformed response.\n Try inspecting the network response or fetch() return value.\n\n Entity: ${this.name}\n Value: ${e&&JSON.stringify(e,null,2)}\n `);throw t.status=400,t}return}const a=this.key;return a in i||(i[a]={}),c in i[a]||(i[a][c]=[]),i[a][c].some(t=>t===e)||(i[a][c].push(e),Object.keys(this.schema).forEach(e=>{if(Object.hasOwnProperty.call(o,e)){const t=this.schema[e];o[e]=r(o[e],o,e,t,s,i)}}),s(this,o,o,t,n)),c}static denormalize(n,r){if(e(n)){const[e,s,i]=t(this.schema,n,r);return[this.fromJS(e.toObject()),s,i]}const s=new this;let i=!1,o=!0;const c=n;return Object.keys(this.schema).forEach(e=>{const t=this.schema[e],a=this.hasDefined(n,e)?n[e]:void 0,[u,h,l]=r(a,t);h||e in s&&!s[e]||(o=!1),!l||e in s&&!s[e]||(i=!0),this.hasDefined(n,e)&&c[e]!==u&&(c[e]=u)}),[c,o,i]}}function p(e){return null!==e&&void 0!==e.pk}"production"!==process.env.NODE_ENV&&(d.fromJS=function(e){if(void 0===this.prototype.pk)throw new Error("cannot construct on abstract types");return f.fromJS.call(this,e)});class y extends d{static denormalize(e,t){return[e,!0,!1]}}const b=t=>{const n={},s=g(t);return[function t(i,o){if(!o)return[i,!0,!1];if(!o.denormalize||"function"!=typeof o.denormalize){if("function"==typeof o)return i instanceof o?[i,!0,!1]:[new o(i),!0,!1];if("object"==typeof o){return(Array.isArray(o)?a:h)(o,i,t)}}return null===i?[i,!0,!1]:p(o)?void 0===i?[i,!1,!1]:((t,n,s,i,o)=>{const c=i(t,n);if(c===r)return[void 0,!0,!0];if("object"!=typeof c||null===c)return[c,!1,!1];o[n.key]||(o[n.key]={});let a=!0,u=!1;if(!o[n.key][t]){const r=e(c)||c instanceof y?c:n.fromJS(c);o[n.key][t]=r,[o[n.key][t],a,u]=n.denormalize(r,s)}return[o[n.key][t],a,u]})(i,o,t,s,n):"function"==typeof o.denormalize?o.denormalize(i,t):[i,!0,!1]},n]},g=t=>{const n=e(t);return(e,r)=>{const s=r.key;return"object"==typeof e?e:n?t.getIn([s,e]):t[s]&&t[s][e]}},O=(e,t,n,r,s,i)=>{if(!e||!r||!["function","object"].includes(typeof r))return e;if(!r.normalize||"function"!=typeof r.normalize){if("function"==typeof r)return new r(e);return(Array.isArray(r)?c:u)(r,e,t,n,O,s,i)}return r.normalize(e,t,n,O,s,i)};var E=Object.freeze({__proto__:null,Union:class extends n{constructor(e,t){if(!t)throw new Error('Expected option "schemaAttribute" not found on UnionSchema.');super(e,t)}normalize(e,t,n,r,s,i){return this.normalizeValue(e,t,n,r,s,i)}denormalize(e,t){return this.denormalizeValue(e,t)}},Values:class extends n{normalize(e,t,n,r,s,i){return Object.keys(e).reduce((t,n,o)=>{const c=e[n];return null!=c?Object.assign({},t,{[n]:this.normalizeValue(c,e,n,r,s,i)}):t},{})}denormalize(e,t){let n=!0,r=!1;return[Object.keys(e).reduce((s,i)=>{const o=e[i],[c,a,u]=this.denormalizeValue(o,t);return a||(n=!1),u&&(r=!0),!a||u?s:Object.assign({},s,{[i]:c})},{}),n,r]}},Array:class extends n{normalize(e,t,n,r,s,o){return i(e).map((e,i)=>this.normalizeValue(e,t,n,r,s,o)).filter(e=>null!=e)}denormalize(e,t){let n=!1,r=!0;return void 0===e&&this.schema&&([,r,n]=t(void 0,this.schema)),[e&&e.map?e.map(e=>this.denormalizeValue(e,t)).filter(o).map(([e])=>e):e,r,n]}},Object:class{constructor(e){this.define(e)}define(e){this.schema=Object.keys(e).reduce((t,n)=>{const r=e[n];return Object.assign({},t,{[n]:r})},this.schema||{})}normalize(...e){return u(this.schema,...e)}denormalize(...e){return h(this.schema,...e)}},Delete:class{constructor(e){if("production"!==process.env.NODE_ENV&&!e)throw new Error('Expected option "entity" not found on DeleteSchema.');this._entity=e}normalize(e,t,n,s,i,o){if("string"==typeof e)return e;const c=this._entity.fromJS(e,t,n),a=c.pk(t,n);return i(this._entity,r,c,t,n),a}denormalize(e,t){return t(e,this._entity)}_denormalizeNullable(){return[]}_normalizeNullable(){return[]}merge(e,t){return t}}});exports.DELETED=r,exports.Entity=d,exports.FlatEntity=y,exports.SimpleRecord=f,exports.denormalize=(e,t,n)=>{if("production"!==process.env.NODE_ENV&&void 0===t)throw new Error("schema needed");if(void 0!==e){const[r,s]=b(n);return[...r(e,t),s]}return[void 0,!1,!1,{}]},exports.isEntity=p,exports.normalize=(e,t)=>{const n=function(e){return["object","function"].includes(typeof e)?"object":typeof e}(t);if(null===e||typeof e!==n){if("production"!==process.env.NODE_ENV){const r=e=>{try{return"string"!=typeof JSON.parse(e)}catch(e){return!1}};throw"string"==typeof e&&r(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/docs/guides/custom-networking 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 "${n}", 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 "${n}", found "${null===e?"null":typeof e}".`)}const r={},s={},i=((e,t)=>(n,r,s,i,o)=>{const c=n.key,a=n.pk(s,i,o);c in e||(e[c]={});const u=e[c][a];if(e[c][a]=u?n.merge(u,r):r,Array.isArray(n.indexes)){const r=e[c][a];c in t||(t[c]={});for(const e of n.indexes){e in t[c]||(t[c][e]={});const n=t[c][e];u&&delete n[u[e]],e in r?n[r[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(r,void 0,2)}`)}}})(r,s);return{entities:r,indexes:s,result:O(e,e,void 0,t,i,{})}},exports.schema=E; |
@@ -35,2 +35,3 @@ (function (global, factory) { | ||
let found = true; | ||
let deleted = false; | ||
return [Object.keys(schema).reduce((object, key) => { | ||
@@ -40,3 +41,3 @@ // Immutable maps cast keys to strings on write so we need to ensure | ||
const stringKey = `${key}`; | ||
const [item, foundItem] = unvisit(object.get(stringKey), schema[stringKey]); | ||
const [item, foundItem, deletedItem] = unvisit(object.get(stringKey), schema[stringKey]); | ||
@@ -47,2 +48,6 @@ if (!foundItem) { | ||
if (deletedItem) { | ||
deleted = true; | ||
} | ||
if (object.has(stringKey)) { | ||
@@ -53,3 +58,3 @@ return object.set(stringKey, item); | ||
} | ||
}, input), found]; | ||
}, input), found, deleted]; | ||
} | ||
@@ -105,3 +110,3 @@ | ||
if (!this.isSingleSchema && !schemaKey) { | ||
return [value, true]; | ||
return [value, true, true]; | ||
} | ||
@@ -116,2 +121,4 @@ | ||
const DELETED = Symbol('ENTITY WAS DELETED'); | ||
const validateSchema = definition => { | ||
@@ -129,2 +136,4 @@ const isArray = Array.isArray(definition); | ||
const filterEmpty = ([, foundItem, deletedItem]) => foundItem && !deletedItem; | ||
const normalize = (schema, input, parent, key, visit, addEntity, visitedEntities) => { | ||
@@ -139,9 +148,10 @@ schema = validateSchema(schema); | ||
schema = validateSchema(schema); | ||
let deleted = false; | ||
let found = true; | ||
if (input === undefined && schema) { | ||
[, found] = unvisit(undefined, schema); | ||
[, found, deleted] = unvisit(undefined, schema); | ||
} | ||
return [input && input.map ? input.map(entityOrId => unvisit(entityOrId, schema)).filter(([, foundItem]) => foundItem).map(([value]) => value) : input, found]; | ||
return [input && input.map ? input.map(entityOrId => unvisit(entityOrId, schema)).filter(filterEmpty).map(([value]) => value) : input, found, deleted]; | ||
}; | ||
@@ -155,9 +165,10 @@ class ArraySchema extends PolymorphicSchema { | ||
denormalize(input, unvisit) { | ||
let deleted = false; | ||
let found = true; | ||
if (input === undefined && this.schema) { | ||
[, found] = unvisit(undefined, this.schema); | ||
[, found, deleted] = unvisit(undefined, this.schema); | ||
} | ||
return [input && input.map ? input.map(entityOrId => this.denormalizeValue(entityOrId, unvisit)).filter(([, foundItem]) => foundItem).map(([value]) => value) : input, found]; | ||
return [input && input.map ? input.map(entityOrId => this.denormalizeValue(entityOrId, unvisit)).filter(filterEmpty).map(([value]) => value) : input, found, deleted]; | ||
} | ||
@@ -190,4 +201,5 @@ | ||
let found = true; | ||
let deleted = false; | ||
Object.keys(schema).forEach(key => { | ||
const [item, foundItem] = unvisit(object[key], schema[key]); | ||
const [item, foundItem, deletedItem] = unvisit(object[key], schema[key]); | ||
@@ -198,2 +210,6 @@ if (object[key] !== undefined) { | ||
if (deletedItem) { | ||
deleted = true; | ||
} | ||
if (!foundItem) { | ||
@@ -203,3 +219,3 @@ found = false; | ||
}); | ||
return [object, found]; | ||
return [object, found, deleted]; | ||
}; | ||
@@ -240,2 +256,9 @@ class ObjectSchema { | ||
} | ||
static toJSON() { | ||
return { | ||
name: this.name, | ||
schema: this.schema | ||
}; | ||
} | ||
/** Defines nested entities */ | ||
@@ -312,5 +335,6 @@ | ||
}; | ||
let deleted = false; | ||
let found = true; | ||
Object.keys(this.schema).forEach(key => { | ||
const [item, foundItem] = unvisit(object[key], this.schema[key]); | ||
const [item, foundItem, deletedItem] = unvisit(object[key], this.schema[key]); | ||
@@ -326,5 +350,9 @@ if (object[key] !== undefined) { | ||
} | ||
if (deletedItem && !(key in instance && !instance[key])) { | ||
deleted = true; | ||
} | ||
}); // useDenormalized will memo based on entities, so creating a new object each time is fine | ||
return [this.fromJS(object), found]; | ||
return [this.fromJS(object), found, deleted]; | ||
} | ||
@@ -352,2 +380,7 @@ /* istanbul ignore next */ | ||
class Entity extends SimpleRecord { | ||
static toJSON() { | ||
return { ...super.toJSON(), | ||
key: this.key | ||
}; | ||
} | ||
/** | ||
@@ -360,2 +393,3 @@ * A unique identifier for each Entity | ||
/** Returns the globally unique identifier for the static Entity */ | ||
@@ -474,4 +508,4 @@ static get key() { | ||
if (isImmutable(entity)) { | ||
const [denormEntity, found] = denormalizeImmutable(this.schema, entity, unvisit); | ||
return [this.fromJS(denormEntity.toObject()), found]; | ||
const [denormEntity, found, deleted] = denormalizeImmutable(this.schema, entity, unvisit); | ||
return [this.fromJS(denormEntity.toObject()), found, deleted]; | ||
} // TODO: This creates unneeded memory pressure | ||
@@ -481,2 +515,3 @@ | ||
const instance = new this(); | ||
let deleted = false; | ||
let found = true; | ||
@@ -487,3 +522,3 @@ const denormEntity = entity; | ||
const input = this.hasDefined(entity, key) ? entity[key] : undefined; | ||
const [value, foundItem] = unvisit(input, schema); // members who default to falsy values are considered 'optional' | ||
const [value, foundItem, deletedItem] = unvisit(input, schema); // members who default to falsy values are considered 'optional' | ||
// if falsy value, and default is actually set then it is optional so pass through | ||
@@ -495,2 +530,6 @@ | ||
if (deletedItem && !(key in instance && !instance[key])) { | ||
deleted = true; | ||
} | ||
if (this.hasDefined(entity, key) && denormEntity[key] !== value) { | ||
@@ -500,7 +539,6 @@ denormEntity[key] = value; | ||
}); | ||
return [denormEntity, found]; | ||
return [denormEntity, found, deleted]; | ||
} | ||
} | ||
/* istanbul ignore next */ | ||
@@ -522,3 +560,3 @@ if (process.env.NODE_ENV !== 'production') { | ||
static denormalize(entity, unvisit) { | ||
return [entity, true]; | ||
return [entity, true, false]; | ||
} | ||
@@ -531,4 +569,8 @@ | ||
if (entity === DELETED) { | ||
return [undefined, true, true]; | ||
} | ||
if (typeof entity !== 'object' || entity === null) { | ||
return [entity, false]; | ||
return [entity, false, false]; | ||
} | ||
@@ -541,2 +583,3 @@ | ||
let found = true; | ||
let deleted = false; | ||
@@ -549,6 +592,6 @@ if (!cache[schema.key][id]) { | ||
cache[schema.key][id] = entityCopy; | ||
[cache[schema.key][id], found] = schema.denormalize(entityCopy, unvisit); | ||
[cache[schema.key][id], found, deleted] = schema.denormalize(entityCopy, unvisit); | ||
} | ||
return [cache[schema.key][id], found]; | ||
return [cache[schema.key][id], found, deleted]; | ||
}; | ||
@@ -560,8 +603,8 @@ | ||
return [function unvisit(input, schema) { | ||
if (!schema) return [input, true]; | ||
if (!schema) return [input, true, false]; | ||
if (!schema.denormalize || typeof schema.denormalize !== 'function') { | ||
if (typeof schema === 'function') { | ||
if (input instanceof schema) return [input, true]; | ||
return [new schema(input), true]; | ||
if (input instanceof schema) return [input, true, false]; | ||
return [new schema(input), true, false]; | ||
} else if (typeof schema === 'object') { | ||
@@ -575,3 +618,3 @@ const method = Array.isArray(schema) ? denormalize : denormalize$1; | ||
if (input === null) { | ||
return [input, true]; | ||
return [input, true, false]; | ||
} | ||
@@ -582,3 +625,3 @@ | ||
if (input === undefined) { | ||
return [input, false]; | ||
return [input, false, false]; | ||
} | ||
@@ -593,3 +636,3 @@ | ||
return [input, true]; | ||
return [input, true, false]; | ||
}, cache]; | ||
@@ -625,3 +668,3 @@ }; | ||
return [undefined, false, {}]; | ||
return [undefined, false, false, {}]; | ||
}; | ||
@@ -778,5 +821,6 @@ | ||
let found = true; | ||
let deleted = false; | ||
return [Object.keys(input).reduce((output, key) => { | ||
const entityOrId = input[key]; | ||
const [value, foundItem] = this.denormalizeValue(entityOrId, unvisit); | ||
const [value, foundItem, deletedItem] = this.denormalizeValue(entityOrId, unvisit); | ||
@@ -787,6 +831,11 @@ if (!foundItem) { | ||
if (deletedItem) { | ||
deleted = true; | ||
} | ||
if (!foundItem || deletedItem) return output; | ||
return { ...output, | ||
[key]: value | ||
}; | ||
}, {}), found]; | ||
}, {}), found, deleted]; | ||
} | ||
@@ -796,2 +845,47 @@ | ||
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */ | ||
class Delete { | ||
constructor(entity) { | ||
if (process.env.NODE_ENV !== 'production' && !entity) { | ||
throw new Error('Expected option "entity" not found on DeleteSchema.'); | ||
} | ||
this._entity = entity; | ||
} | ||
normalize(input, parent, key, visit, addEntity, visitedEntities) { | ||
// pass over already processed entities | ||
if (typeof input === 'string') return input; // TODO: what's store needs to be a differing type from fromJS | ||
const processedEntity = this._entity.fromJS(input, parent, key); | ||
const id = processedEntity.pk(parent, key); | ||
addEntity(this._entity, DELETED, processedEntity, parent, key); | ||
return id; | ||
} | ||
denormalize(id, unvisit) { | ||
return unvisit(id, this._entity); | ||
} | ||
/* istanbul ignore next */ | ||
_denormalizeNullable() { | ||
return []; | ||
} | ||
/* istanbul ignore next */ | ||
_normalizeNullable() { | ||
return []; | ||
} | ||
/* istanbul ignore next */ | ||
merge(existing, incoming) { | ||
return incoming; | ||
} | ||
} | ||
/* istanbul ignore file */ | ||
@@ -804,5 +898,7 @@ | ||
Array: ArraySchema, | ||
Object: ObjectSchema | ||
Object: ObjectSchema, | ||
Delete: Delete | ||
}); | ||
exports.DELETED = DELETED; | ||
exports.Entity = Entity; | ||
@@ -809,0 +905,0 @@ exports.FlatEntity = FlatEntity; |
@@ -1,1 +0,1 @@ | ||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e=e||self).rest_hooks_normalizr={})}(this,(function(e){"use strict";function t(e){return!(!e||"function"!=typeof e.hasOwnProperty||!(Object.hasOwnProperty.call(e,"__ownerID")||e._map&&Object.hasOwnProperty.call(e._map,"__ownerID")))}function n(e,t,n){let r=!0;return[Object.keys(e).reduce((t,i)=>{const s=""+i,[o,c]=n(t.get(s),e[s]);return c||(r=!1),t.has(s)?t.set(s,o):t},t),r]}class r{constructor(e,t){t&&(this._schemaAttribute="string"==typeof t?e=>e[t]:t),this.define(e)}get isSingleSchema(){return!this._schemaAttribute}define(e){this.schema=e}getSchemaAttribute(e,t,n){return!this.isSingleSchema&&this._schemaAttribute(e,t,n)}inferSchema(e,t,n){if(this.isSingleSchema)return this.schema;const r=this.getSchemaAttribute(e,t,n);return this.schema[r]}normalizeValue(e,t,n,r,i,s){const o=this.inferSchema(e,t,n);if(!o)return e;const c=r(e,t,n,o,i,s);return this.isSingleSchema||null==c?c:{id:c,schema:this.getSchemaAttribute(e,t,n)}}denormalizeValue(e,n){const r=t(e)?e.get("schema"):e.schema;if(!this.isSingleSchema&&!r)return[e,!0];return n((this.isSingleSchema?void 0:t(e)?e.get("id"):e.id)||e,this.isSingleSchema?this.schema:this.schema[r])}}const i=e=>{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]},s=e=>Array.isArray(e)?e:Object.keys(e).map(t=>e[t]),o=(e,t,n,r,o,c,a)=>{e=i(e);return s(t).map((t,i)=>o(t,n,r,e,c,a))},c=(e,t,n)=>{e=i(e);let r=!0;return void 0===t&&e&&([,r]=n(void 0,e)),[t&&t.map?t.map(t=>n(t,e)).filter(([,e])=>e).map(([e])=>e):t,r]};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,r,i)=>{if(t(r))return n(e,r,i);const s=Object.assign({},r);let o=!0;return Object.keys(e).forEach(t=>{const[n,r]=i(s[t],e[t]);void 0!==s[t]&&(s[t]=n),r||(o=!1)}),[s,o]};const h=Symbol("Defined Members"),l=Symbol("unq");class f{toString(){return this[l]}static fromJS(e={},t,n){const r=new this(e);return e instanceof f&&(e=e.constructor.toObjectDefined(e)),Object.assign(r,e),Object.defineProperty(r,h,{value:Object.keys(e),writable:!1}),Object.defineProperty(r,l,{value:""+Math.random(),writable:!1}),r}static merge(e,t){const n=Object.assign(this.toObjectDefined(e),this.toObjectDefined(t));return this.fromJS(n)}static hasDefined(e,t){return e[h].includes(t)}static toObjectDefined(e){const t={};for(const n of e[h])t[n]=e[n];return t}static keysDefined(e){return e[h]}static normalize(...e){return a(this.schema,...e)}static denormalize(e,t){const n=new this,r=Object.assign({},e);let i=!0;return Object.keys(this.schema).forEach(e=>{const[s,o]=t(r[e],this.schema[e]);void 0!==r[e]&&(r[e]=s),o||e in n&&!n[e]||(i=!1)}),[this.fromJS(r),i]}static asSchema(){return"development"===process.env.NODE_ENV&&console.error("asSchema() is deprecated - use Entity directly instead."),this}}f.schema={};class m extends f{static get key(){if("production"!==process.env.NODE_ENV&&(""===this.name||"Entity"===this.name))throw new Error("Entity classes without a name must define `static get key()`");return this.name}static pk(e,t,n){return this.prototype.pk.call(e,t,n)||n}static normalize(e,t,n,r,i,s){if("string"==typeof e)return e;const o=this.fromJS(e,t,n);if("production"!==process.env.NODE_ENV){const e=new this,t=new Set(Object.keys(e)),n=this.keysDefined(o),[r,i,s]=[[],[],[]];for(const e of n)t.has(e)?r.push(e):s.push(e);for(const e of t)r.includes(e)||i.push(e);if((Math.max(n.length/2,1)<=s.length&&t.size>Math.max(s.length,2)||r.length<Math.min(1,t.size/2))&&t.size){const e=new Error(`Attempted to initialize ${this.name} with substantially different than expected keys\n\n This is likely due to a malformed response.\n Try inspecting the network response or fetch() return value.\n\n Expected keys:\n Found: ${r}\n Missing: ${i}\n Unexpected keys: ${s}\n Value: ${JSON.stringify(this.toObjectDefined(o),null,2)}`);throw e.status=400,e}}const c=o.pk(t,n);if(void 0===c||""===c){if("production"!==process.env.NODE_ENV){const t=new Error(`Missing usable resource key when normalizing response.\n\n This is likely due to a malformed response.\n Try inspecting the network response or fetch() return value.\n\n Entity: ${this.name}\n Value: ${e&&JSON.stringify(e,null,2)}\n `);throw t.status=400,t}return}const a=this.key;return a in s||(s[a]={}),c in s[a]||(s[a][c]=[]),s[a][c].some(t=>t===e)||(s[a][c].push(e),Object.keys(this.schema).forEach(e=>{if(Object.hasOwnProperty.call(o,e)){const t=this.schema[e];o[e]=r(o[e],o,e,t,i,s)}}),i(this,o,o,t,n)),c}static denormalize(e,r){if(t(e)){const[t,i]=n(this.schema,e,r);return[this.fromJS(t.toObject()),i]}const i=new this;let s=!0;const o=e;return Object.keys(this.schema).forEach(t=>{const n=this.schema[t],c=this.hasDefined(e,t)?e[t]:void 0,[a,u]=r(c,n);u||t in i&&!i[t]||(s=!1),this.hasDefined(e,t)&&o[t]!==a&&(o[t]=a)}),[o,s]}}function d(e){return null!==e&&void 0!==e.pk}"production"!==process.env.NODE_ENV&&(m.fromJS=function(e){if(void 0===this.prototype.pk)throw new Error("cannot construct on abstract types");return f.fromJS.call(this,e)});class p extends m{static denormalize(e,t){return[e,!0]}}const y=e=>{const n={},r=b(e);return[function e(i,s){if(!s)return[i,!0];if(!s.denormalize||"function"!=typeof s.denormalize){if("function"==typeof s)return i instanceof s?[i,!0]:[new s(i),!0];if("object"==typeof s){return(Array.isArray(s)?c:u)(s,i,e)}}return null===i?[i,!0]:d(s)?void 0===i?[i,!1]:((e,n,r,i,s)=>{const o=i(e,n);if("object"!=typeof o||null===o)return[o,!1];s[n.key]||(s[n.key]={});let c=!0;if(!s[n.key][e]){const i=t(o)||o instanceof p?o:n.fromJS(o);s[n.key][e]=i,[s[n.key][e],c]=n.denormalize(i,r)}return[s[n.key][e],c]})(i,s,e,r,n):"function"==typeof s.denormalize?s.denormalize(i,e):[i,!0]},n]},b=e=>{const n=t(e);return(t,r)=>{const i=r.key;return"object"==typeof t?t:n?e.getIn([i,t]):e[i]&&e[i][t]}},g=(e,t,n,r,i,s)=>{if(!e||!r||!["function","object"].includes(typeof r))return e;if(!r.normalize||"function"!=typeof r.normalize){if("function"==typeof r)return new r(e);return(Array.isArray(r)?o:a)(r,e,t,n,g,i,s)}return r.normalize(e,t,n,g,i,s)};var O=Object.freeze({__proto__:null,Union:class extends r{constructor(e,t){if(!t)throw new Error('Expected option "schemaAttribute" not found on UnionSchema.');super(e,t)}normalize(e,t,n,r,i,s){return this.normalizeValue(e,t,n,r,i,s)}denormalize(e,t){return this.denormalizeValue(e,t)}},Values:class extends r{normalize(e,t,n,r,i,s){return Object.keys(e).reduce((t,n,o)=>{const c=e[n];return null!=c?Object.assign({},t,{[n]:this.normalizeValue(c,e,n,r,i,s)}):t},{})}denormalize(e,t){let n=!0;return[Object.keys(e).reduce((r,i)=>{const s=e[i],[o,c]=this.denormalizeValue(s,t);return c||(n=!1),Object.assign({},r,{[i]:o})},{}),n]}},Array:class extends r{normalize(e,t,n,r,i,o){return s(e).map((e,s)=>this.normalizeValue(e,t,n,r,i,o)).filter(e=>null!=e)}denormalize(e,t){let n=!0;return void 0===e&&this.schema&&([,n]=t(void 0,this.schema)),[e&&e.map?e.map(e=>this.denormalizeValue(e,t)).filter(([,e])=>e).map(([e])=>e):e,n]}},Object:class{constructor(e){this.define(e)}define(e){this.schema=Object.keys(e).reduce((t,n)=>{const r=e[n];return Object.assign({},t,{[n]:r})},this.schema||{})}normalize(...e){return a(this.schema,...e)}denormalize(...e){return u(this.schema,...e)}}});e.Entity=m,e.FlatEntity=p,e.SimpleRecord=f,e.denormalize=(e,t,n)=>{if("production"!==process.env.NODE_ENV&&void 0===t)throw new Error("schema needed");if(void 0!==e){const[r,i]=y(n);return[...r(e,t),i]}return[void 0,!1,{}]},e.isEntity=d,e.normalize=(e,t)=>{const n=function(e){return["object","function"].includes(typeof e)?"object":typeof e}(t);if(null===e||typeof e!==n){if("production"!==process.env.NODE_ENV){const r=e=>{try{return"string"!=typeof JSON.parse(e)}catch(e){return!1}};throw"string"==typeof e&&r(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/docs/guides/custom-networking 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 "${n}", 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 "${n}", found "${null===e?"null":typeof e}".`)}const r={},i={},s=((e,t)=>(n,r,i,s,o)=>{const c=n.key,a=n.pk(i,s,o);c in e||(e[c]={});const u=e[c][a];if(e[c][a]=u?n.merge(u,r):r,Array.isArray(n.indexes)){const r=e[c][a];c in t||(t[c]={});for(const e of n.indexes){e in t[c]||(t[c][e]={});const n=t[c][e];u&&delete n[u[e]],e in r?n[r[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(r,void 0,2)}`)}}})(r,i);return{entities:r,indexes:i,result:g(e,e,void 0,t,s,{})}},e.schema=O,Object.defineProperty(e,"__esModule",{value:!0})})); | ||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e=e||self).rest_hooks_normalizr={})}(this,(function(e){"use strict";function t(e){return!(!e||"function"!=typeof e.hasOwnProperty||!(Object.hasOwnProperty.call(e,"__ownerID")||e._map&&Object.hasOwnProperty.call(e._map,"__ownerID")))}function n(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]}class r{constructor(e,t){t&&(this._schemaAttribute="string"==typeof t?e=>e[t]:t),this.define(e)}get isSingleSchema(){return!this._schemaAttribute}define(e){this.schema=e}getSchemaAttribute(e,t,n){return!this.isSingleSchema&&this._schemaAttribute(e,t,n)}inferSchema(e,t,n){if(this.isSingleSchema)return this.schema;const r=this.getSchemaAttribute(e,t,n);return this.schema[r]}normalizeValue(e,t,n,r,i,s){const o=this.inferSchema(e,t,n);if(!o)return e;const c=r(e,t,n,o,i,s);return this.isSingleSchema||null==c?c:{id:c,schema:this.getSchemaAttribute(e,t,n)}}denormalizeValue(e,n){const r=t(e)?e.get("schema"):e.schema;if(!this.isSingleSchema&&!r)return[e,!0,!0];return n((this.isSingleSchema?void 0:t(e)?e.get("id"):e.id)||e,this.isSingleSchema?this.schema:this.schema[r])}}const i=Symbol("ENTITY WAS DELETED"),s=e=>{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]},o=e=>Array.isArray(e)?e:Object.keys(e).map(t=>e[t]),c=([,e,t])=>e&&!t,a=(e,t,n,r,i,c,a)=>{e=s(e);return o(t).map((t,s)=>i(t,n,r,e,c,a))},u=(e,t,n)=>{e=s(e);let r=!1,i=!0;return void 0===t&&e&&([,i,r]=n(void 0,e)),[t&&t.map?t.map(t=>n(t,e)).filter(c).map(([e])=>e):t,i,r]};const h=(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},l=(e,r,i)=>{if(t(r))return n(e,r,i);const s=Object.assign({},r);let o=!0,c=!1;return Object.keys(e).forEach(t=>{const[n,r,a]=i(s[t],e[t]);void 0!==s[t]&&(s[t]=n),a&&(c=!0),r||(o=!1)}),[s,o,c]};const f=Symbol("Defined Members"),m=Symbol("unq");class d{toString(){return this[m]}static toJSON(){return{name:this.name,schema:this.schema}}static fromJS(e={},t,n){const r=new this(e);return e instanceof d&&(e=e.constructor.toObjectDefined(e)),Object.assign(r,e),Object.defineProperty(r,f,{value:Object.keys(e),writable:!1}),Object.defineProperty(r,m,{value:""+Math.random(),writable:!1}),r}static merge(e,t){const n=Object.assign(this.toObjectDefined(e),this.toObjectDefined(t));return this.fromJS(n)}static hasDefined(e,t){return e[f].includes(t)}static toObjectDefined(e){const t={};for(const n of e[f])t[n]=e[n];return t}static keysDefined(e){return e[f]}static normalize(...e){return h(this.schema,...e)}static denormalize(e,t){const n=new this,r=Object.assign({},e);let i=!1,s=!0;return Object.keys(this.schema).forEach(e=>{const[o,c,a]=t(r[e],this.schema[e]);void 0!==r[e]&&(r[e]=o),c||e in n&&!n[e]||(s=!1),!a||e in n&&!n[e]||(i=!0)}),[this.fromJS(r),s,i]}static asSchema(){return"development"===process.env.NODE_ENV&&console.error("asSchema() is deprecated - use Entity directly instead."),this}}d.schema={};class p extends d{static toJSON(){return Object.assign({},super.toJSON(),{key:this.key})}static get key(){if("production"!==process.env.NODE_ENV&&(""===this.name||"Entity"===this.name))throw new Error("Entity classes without a name must define `static get key()`");return this.name}static pk(e,t,n){return this.prototype.pk.call(e,t,n)||n}static normalize(e,t,n,r,i,s){if("string"==typeof e)return e;const o=this.fromJS(e,t,n);if("production"!==process.env.NODE_ENV){const e=new this,t=new Set(Object.keys(e)),n=this.keysDefined(o),[r,i,s]=[[],[],[]];for(const e of n)t.has(e)?r.push(e):s.push(e);for(const e of t)r.includes(e)||i.push(e);if((Math.max(n.length/2,1)<=s.length&&t.size>Math.max(s.length,2)||r.length<Math.min(1,t.size/2))&&t.size){const e=new Error(`Attempted to initialize ${this.name} with substantially different than expected keys\n\n This is likely due to a malformed response.\n Try inspecting the network response or fetch() return value.\n\n Expected keys:\n Found: ${r}\n Missing: ${i}\n Unexpected keys: ${s}\n Value: ${JSON.stringify(this.toObjectDefined(o),null,2)}`);throw e.status=400,e}}const c=o.pk(t,n);if(void 0===c||""===c){if("production"!==process.env.NODE_ENV){const t=new Error(`Missing usable resource key when normalizing response.\n\n This is likely due to a malformed response.\n Try inspecting the network response or fetch() return value.\n\n Entity: ${this.name}\n Value: ${e&&JSON.stringify(e,null,2)}\n `);throw t.status=400,t}return}const a=this.key;return a in s||(s[a]={}),c in s[a]||(s[a][c]=[]),s[a][c].some(t=>t===e)||(s[a][c].push(e),Object.keys(this.schema).forEach(e=>{if(Object.hasOwnProperty.call(o,e)){const t=this.schema[e];o[e]=r(o[e],o,e,t,i,s)}}),i(this,o,o,t,n)),c}static denormalize(e,r){if(t(e)){const[t,i,s]=n(this.schema,e,r);return[this.fromJS(t.toObject()),i,s]}const i=new this;let s=!1,o=!0;const c=e;return Object.keys(this.schema).forEach(t=>{const n=this.schema[t],a=this.hasDefined(e,t)?e[t]:void 0,[u,h,l]=r(a,n);h||t in i&&!i[t]||(o=!1),!l||t in i&&!i[t]||(s=!0),this.hasDefined(e,t)&&c[t]!==u&&(c[t]=u)}),[c,o,s]}}function y(e){return null!==e&&void 0!==e.pk}"production"!==process.env.NODE_ENV&&(p.fromJS=function(e){if(void 0===this.prototype.pk)throw new Error("cannot construct on abstract types");return d.fromJS.call(this,e)});class b extends p{static denormalize(e,t){return[e,!0,!1]}}const g=e=>{const n={},r=O(e);return[function e(s,o){if(!o)return[s,!0,!1];if(!o.denormalize||"function"!=typeof o.denormalize){if("function"==typeof o)return s instanceof o?[s,!0,!1]:[new o(s),!0,!1];if("object"==typeof o){return(Array.isArray(o)?u:l)(o,s,e)}}return null===s?[s,!0,!1]:y(o)?void 0===s?[s,!1,!1]:((e,n,r,s,o)=>{const c=s(e,n);if(c===i)return[void 0,!0,!0];if("object"!=typeof c||null===c)return[c,!1,!1];o[n.key]||(o[n.key]={});let a=!0,u=!1;if(!o[n.key][e]){const i=t(c)||c instanceof b?c:n.fromJS(c);o[n.key][e]=i,[o[n.key][e],a,u]=n.denormalize(i,r)}return[o[n.key][e],a,u]})(s,o,e,r,n):"function"==typeof o.denormalize?o.denormalize(s,e):[s,!0,!1]},n]},O=e=>{const n=t(e);return(t,r)=>{const i=r.key;return"object"==typeof t?t:n?e.getIn([i,t]):e[i]&&e[i][t]}},E=(e,t,n,r,i,s)=>{if(!e||!r||!["function","object"].includes(typeof r))return e;if(!r.normalize||"function"!=typeof r.normalize){if("function"==typeof r)return new r(e);return(Array.isArray(r)?a:h)(r,e,t,n,E,i,s)}return r.normalize(e,t,n,E,i,s)};var S=Object.freeze({__proto__:null,Union:class extends r{constructor(e,t){if(!t)throw new Error('Expected option "schemaAttribute" not found on UnionSchema.');super(e,t)}normalize(e,t,n,r,i,s){return this.normalizeValue(e,t,n,r,i,s)}denormalize(e,t){return this.denormalizeValue(e,t)}},Values:class extends r{normalize(e,t,n,r,i,s){return Object.keys(e).reduce((t,n,o)=>{const c=e[n];return null!=c?Object.assign({},t,{[n]:this.normalizeValue(c,e,n,r,i,s)}):t},{})}denormalize(e,t){let n=!0,r=!1;return[Object.keys(e).reduce((i,s)=>{const o=e[s],[c,a,u]=this.denormalizeValue(o,t);return a||(n=!1),u&&(r=!0),!a||u?i:Object.assign({},i,{[s]:c})},{}),n,r]}},Array:class extends r{normalize(e,t,n,r,i,s){return o(e).map((e,o)=>this.normalizeValue(e,t,n,r,i,s)).filter(e=>null!=e)}denormalize(e,t){let n=!1,r=!0;return void 0===e&&this.schema&&([,r,n]=t(void 0,this.schema)),[e&&e.map?e.map(e=>this.denormalizeValue(e,t)).filter(c).map(([e])=>e):e,r,n]}},Object:class{constructor(e){this.define(e)}define(e){this.schema=Object.keys(e).reduce((t,n)=>{const r=e[n];return Object.assign({},t,{[n]:r})},this.schema||{})}normalize(...e){return h(this.schema,...e)}denormalize(...e){return l(this.schema,...e)}},Delete:class{constructor(e){if("production"!==process.env.NODE_ENV&&!e)throw new Error('Expected option "entity" not found on DeleteSchema.');this._entity=e}normalize(e,t,n,r,s,o){if("string"==typeof e)return e;const c=this._entity.fromJS(e,t,n),a=c.pk(t,n);return s(this._entity,i,c,t,n),a}denormalize(e,t){return t(e,this._entity)}_denormalizeNullable(){return[]}_normalizeNullable(){return[]}merge(e,t){return t}}});e.DELETED=i,e.Entity=p,e.FlatEntity=b,e.SimpleRecord=d,e.denormalize=(e,t,n)=>{if("production"!==process.env.NODE_ENV&&void 0===t)throw new Error("schema needed");if(void 0!==e){const[r,i]=g(n);return[...r(e,t),i]}return[void 0,!1,!1,{}]},e.isEntity=y,e.normalize=(e,t)=>{const n=function(e){return["object","function"].includes(typeof e)?"object":typeof e}(t);if(null===e||typeof e!==n){if("production"!==process.env.NODE_ENV){const r=e=>{try{return"string"!=typeof JSON.parse(e)}catch(e){return!1}};throw"string"==typeof e&&r(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/docs/guides/custom-networking 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 "${n}", 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 "${n}", found "${null===e?"null":typeof e}".`)}const r={},i={},s=((e,t)=>(n,r,i,s,o)=>{const c=n.key,a=n.pk(i,s,o);c in e||(e[c]={});const u=e[c][a];if(e[c][a]=u?n.merge(u,r):r,Array.isArray(n.indexes)){const r=e[c][a];c in t||(t[c]={});for(const e of n.indexes){e in t[c]||(t[c][e]={});const n=t[c][e];u&&delete n[u[e]],e in r?n[r[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(r,void 0,2)}`)}}})(r,i);return{entities:r,indexes:i,result:E(e,e,void 0,t,s,{})}},e.schema=S,Object.defineProperty(e,"__esModule",{value:!0})})); |
@@ -13,3 +13,6 @@ import { | ||
} from './types'; | ||
import { default as Delete } from './schemas/Delete'; | ||
export { Delete }; | ||
export type StrategyFunction<T> = (value: any, parent: any, key: string) => T; | ||
@@ -28,3 +31,6 @@ export type SchemaFunction<K = string> = ( | ||
export type EntityMap<T = any> = Record<string, EntityInterface<T>>; | ||
export type UnvisitFunction = (input: any, schema: any) => [any, boolean]; | ||
export type UnvisitFunction = ( | ||
input: any, | ||
schema: any, | ||
) => [any, boolean, boolean]; | ||
export type UnionResult<Choices extends EntityMap> = { | ||
@@ -50,3 +56,3 @@ id: string; | ||
): any; | ||
denormalize(input: any, unvisit: UnvisitFunction): [any, boolean]; | ||
denormalize(input: any, unvisit: UnvisitFunction): [any, boolean, boolean]; | ||
} | ||
@@ -58,6 +64,6 @@ | ||
// this is not an actual member, but is needed for the recursive DenormalizeNullable<> type algo | ||
_denormalizeNullable(): [any, boolean]; | ||
_denormalizeNullable(): [any, boolean, boolean]; | ||
} | ||
interface EntityInterface<T = any> extends SchemaSimple { | ||
export interface EntityInterface<T = any> extends SchemaSimple { | ||
pk(params: any, parent?: any, key?: string): string | undefined; | ||
@@ -88,5 +94,5 @@ readonly key: string; | ||
unvisit: UnvisitFunction, | ||
): [Denormalize<S>[], boolean]; | ||
): [Denormalize<S>[], boolean, boolean]; | ||
_denormalizeNullable(): [Denormalize<S>[] | undefined, false]; | ||
_denormalizeNullable(): [Denormalize<S>[] | undefined, false, boolean]; | ||
} | ||
@@ -113,5 +119,5 @@ | ||
unvisit: UnvisitFunction, | ||
): [DenormalizeObject<O>, boolean]; | ||
): [DenormalizeObject<O>, boolean, boolean]; | ||
_denormalizeNullable(): [DenormalizeNullableObject<O>, false]; | ||
_denormalizeNullable(): [DenormalizeNullableObject<O>, false, boolean]; | ||
} | ||
@@ -145,3 +151,3 @@ | ||
unvisit: UnvisitFunction, | ||
): [AbstractInstanceType<Choices[keyof Choices]>, boolean]; | ||
): [AbstractInstanceType<Choices[keyof Choices]>, boolean, boolean]; | ||
@@ -151,2 +157,3 @@ _denormalizeNullable(): [ | ||
false, | ||
boolean, | ||
]; | ||
@@ -204,2 +211,3 @@ } | ||
boolean, | ||
boolean, | ||
]; | ||
@@ -215,3 +223,4 @@ | ||
false, | ||
boolean, | ||
]; | ||
} |
@@ -35,3 +35,3 @@ import type { default as schema, EntityInterface } from './schema'; | ||
}; | ||
export declare type DenormalizeReturnType<T> = T extends (input: any, unvisit: any) => [infer R, any] ? R : never; | ||
export declare type DenormalizeReturnType<T> = T extends (input: any, unvisit: any) => [infer R, any, any] ? R : never; | ||
export declare type NormalizeReturnType<T> = T extends (...args: any) => infer R ? R : never; | ||
@@ -38,0 +38,0 @@ export declare type Denormalize<S> = S extends EntityInterface<infer U> ? U : S extends RecordClass ? AbstractInstanceType<S> : S extends schema.SchemaClass ? DenormalizeReturnType<S['denormalize']> : S extends schema.Serializable<infer T> ? T : S extends Array<infer F> ? Denormalize<F>[] : S extends { |
{ | ||
"name": "@rest-hooks/normalizr", | ||
"version": "6.0.0-gamma.2", | ||
"version": "6.0.0-h.0", | ||
"description": "Normalizes and denormalizes JSON according to schema for Redux and Flux applications", | ||
@@ -60,5 +60,5 @@ "homepage": "https://github.com/coinbase/rest-hooks/tree/master/packages/normalizr#readme", | ||
"dependencies": { | ||
"@babel/runtime": "^7.7.0" | ||
"@babel/runtime": "^7.10.4" | ||
}, | ||
"gitHead": "a113dc269751e02516659d2b187e41496aad3a42" | ||
"gitHead": "c0fb0d84e41cf81ee78840532645b3b6f17753e0" | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
232622
35
3999
Updated@babel/runtime@^7.10.4