UNPKG

@data-client/normalizr

Version:

Normalizes and denormalizes JSON according to schema for Redux and Flux applications

147 lines (139 loc) 18 kB
import { getVisit } from './getVisit.js'; import { ImmNormalizeDelegate } from './NormalizeDelegate.imm.js'; /** ImmutableJS store data structure */ /** Result of normalizing into ImmutableJS state */ export const normalize = (schema, input, args = [], { entities, indexes, entitiesMeta } = emptyStore, meta = { fetchedAt: 0, date: Date.now(), expiresAt: Infinity }) => { // no schema means we don't process at all if (schema === undefined || schema === null) return { result: input, entities, indexes, entitiesMeta }; const schemaType = expectedSchemaType(schema); if (input === null || typeof input !== schemaType && // we will allow a Invalidate schema to be a string or object !(schema.key !== undefined && schema.pk === undefined && typeof input === 'string')) { /* istanbul ignore else */ if (process.env.NODE_ENV !== 'production') { const parseWorks = input => { try { return typeof JSON.parse(input) !== 'string'; } catch { return false; } }; if (typeof input === 'string' && parseWorks(input)) { throw new Error(`Normalizing a string, but this does match schema. Parsing this input string as JSON worked. This likely indicates fetch function did not parse the JSON. By default, this only happens if "content-type" header includes "json". See https://dataclient.io/rest/api/RestEndpoint#parseResponse for more information Schema: ${JSON.stringify(schema, undefined, 2)} Input: "${input}"`); } else { throw new Error(`Unexpected input given to normalize. Expected type to be "${schemaType}", found "${input === null ? 'null' : typeof input}". Schema: ${JSON.stringify(schema, undefined, 2)} Input: "${input}"`); } } else { throw new Error(`Unexpected input given to normalize. Expected type to be "${schemaType}", found "${input === null ? 'null' : typeof input}".`); } } const delegate = new ImmNormalizeDelegate({ entities, indexes, entitiesMeta }, meta); const visit = getVisit(delegate); const result = visit(schema, input, input, undefined, args); return { result, entities: delegate.entities, indexes: delegate.indexes, entitiesMeta: delegate.entitiesMeta }; }; function expectedSchemaType(schema) { return ['object', 'function'].includes(typeof schema) ? 'object' : typeof schema; } // Default empty ImmutableJS-like store // Users should provide their own Immutable.Map instances const emptyImmutableLike = { get() { return undefined; }, getIn() { return undefined; }, setIn(k, value) { // Create a simple nested structure for the empty case // This is a minimal implementation for default empty state const result = { ...this }; let current = result; for (let i = 0; i < k.length - 1; i++) { if (!current[k[i]]) { current[k[i]] = {}; } current = current[k[i]]; } current[k[k.length - 1]] = value; // Return a proper ImmutableJS-like object return createNestedImmutable(result); } }; function createNestedImmutable(obj) { return { get(key) { const value = obj[key]; if (value && typeof value === 'object') { return createNestedImmutable(value); } return value; }, getIn(path) { let current = obj; for (const key of path) { if (current === undefined || current === null) return undefined; current = current[key]; } return current; }, setIn(path, value) { const result = deepClone(obj); let current = result; for (let i = 0; i < path.length - 1; i++) { if (!current[path[i]]) { current[path[i]] = {}; } current = current[path[i]]; } current[path[path.length - 1]] = value; return createNestedImmutable(result); } }; } function deepClone(obj) { if (obj === null || typeof obj !== 'object') return obj; if (Array.isArray(obj)) return obj.map(deepClone); const result = {}; for (const key in obj) { result[key] = deepClone(obj[key]); } return result; } const emptyStore = { entities: emptyImmutableLike, indexes: emptyImmutableLike, entitiesMeta: emptyImmutableLike }; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJnZXRWaXNpdCIsIkltbU5vcm1hbGl6ZURlbGVnYXRlIiwibm9ybWFsaXplIiwic2NoZW1hIiwiaW5wdXQiLCJhcmdzIiwiZW50aXRpZXMiLCJpbmRleGVzIiwiZW50aXRpZXNNZXRhIiwiZW1wdHlTdG9yZSIsIm1ldGEiLCJmZXRjaGVkQXQiLCJkYXRlIiwiRGF0ZSIsIm5vdyIsImV4cGlyZXNBdCIsIkluZmluaXR5IiwidW5kZWZpbmVkIiwicmVzdWx0Iiwic2NoZW1hVHlwZSIsImV4cGVjdGVkU2NoZW1hVHlwZSIsImtleSIsInBrIiwicHJvY2VzcyIsImVudiIsIk5PREVfRU5WIiwicGFyc2VXb3JrcyIsIkpTT04iLCJwYXJzZSIsIkVycm9yIiwic3RyaW5naWZ5IiwiZGVsZWdhdGUiLCJ2aXNpdCIsImluY2x1ZGVzIiwiZW1wdHlJbW11dGFibGVMaWtlIiwiZ2V0IiwiZ2V0SW4iLCJzZXRJbiIsImsiLCJ2YWx1ZSIsImN1cnJlbnQiLCJpIiwibGVuZ3RoIiwiY3JlYXRlTmVzdGVkSW1tdXRhYmxlIiwib2JqIiwicGF0aCIsImRlZXBDbG9uZSIsIkFycmF5IiwiaXNBcnJheSIsIm1hcCJdLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9ub3JtYWxpemUvbm9ybWFsaXplLmltbS50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBnZXRWaXNpdCB9IGZyb20gJy4vZ2V0VmlzaXQuanMnO1xuaW1wb3J0IHR5cGUgeyBTY2hlbWEgfSBmcm9tICcuLi9pbnRlcmZhY2UuanMnO1xuaW1wb3J0IHR5cGUgeyBOb3JtYWxpemVNZXRhLCBOb3JtYWxpemVOdWxsYWJsZSB9IGZyb20gJy4uL3R5cGVzLmpzJztcbmltcG9ydCB7XG4gIEltbU5vcm1hbGl6ZURlbGVnYXRlLFxuICBJbW11dGFibGVKU011dGFibGVUYWJsZSxcbn0gZnJvbSAnLi9Ob3JtYWxpemVEZWxlZ2F0ZS5pbW0uanMnO1xuXG4vKiogSW1tdXRhYmxlSlMgc3RvcmUgZGF0YSBzdHJ1Y3R1cmUgKi9cbmV4cG9ydCBpbnRlcmZhY2UgSW1tdXRhYmxlU3RvcmVEYXRhIHtcbiAgZW50aXRpZXM6IEltbXV0YWJsZUpTTXV0YWJsZVRhYmxlO1xuICBpbmRleGVzOiBJbW11dGFibGVKU011dGFibGVUYWJsZTtcbiAgZW50aXRpZXNNZXRhOiBJbW11dGFibGVKU011dGFibGVUYWJsZTtcbn1cblxuLyoqIFJlc3VsdCBvZiBub3JtYWxpemluZyBpbnRvIEltbXV0YWJsZUpTIHN0YXRlICovXG5leHBvcnQgaW50ZXJmYWNlIEltbXV0YWJsZU5vcm1hbGl6ZWRTY2hlbWE8Uj4ge1xuICBlbnRpdGllczogSW1tdXRhYmxlSlNNdXRhYmxlVGFibGU7XG4gIHJlc3VsdDogUjtcbiAgaW5kZXhlczogSW1tdXRhYmxlSlNNdXRhYmxlVGFibGU7XG4gIGVudGl0aWVzTWV0YTogSW1tdXRhYmxlSlNNdXRhYmxlVGFibGU7XG59XG5cbmV4cG9ydCBjb25zdCBub3JtYWxpemUgPSA8UyBleHRlbmRzIFNjaGVtYSA9IFNjaGVtYSwgUiA9IE5vcm1hbGl6ZU51bGxhYmxlPFM+PihcbiAgc2NoZW1hOiBTIHwgdW5kZWZpbmVkLFxuICBpbnB1dDogYW55LFxuICBhcmdzOiByZWFkb25seSBhbnlbXSA9IFtdLFxuICB7IGVudGl0aWVzLCBpbmRleGVzLCBlbnRpdGllc01ldGEgfTogSW1tdXRhYmxlU3RvcmVEYXRhID0gZW1wdHlTdG9yZSxcbiAgbWV0YTogTm9ybWFsaXplTWV0YSA9IHsgZmV0Y2hlZEF0OiAwLCBkYXRlOiBEYXRlLm5vdygpLCBleHBpcmVzQXQ6IEluZmluaXR5IH0sXG4pOiBJbW11dGFibGVOb3JtYWxpemVkU2NoZW1hPFI+ID0+IHtcbiAgLy8gbm8gc2NoZW1hIG1lYW5zIHdlIGRvbid0IHByb2Nlc3MgYXQgYWxsXG4gIGlmIChzY2hlbWEgPT09IHVuZGVmaW5lZCB8fCBzY2hlbWEgPT09IG51bGwpXG4gICAgcmV0dXJuIHtcbiAgICAgIHJlc3VsdDogaW5wdXQsXG4gICAgICBlbnRpdGllcyxcbiAgICAgIGluZGV4ZXMsXG4gICAgICBlbnRpdGllc01ldGEsXG4gICAgfTtcblxuICBjb25zdCBzY2hlbWFUeXBlID0gZXhwZWN0ZWRTY2hlbWFUeXBlKHNjaGVtYSk7XG4gIGlmIChcbiAgICBpbnB1dCA9PT0gbnVsbCB8fFxuICAgICh0eXBlb2YgaW5wdXQgIT09IHNjaGVtYVR5cGUgJiZcbiAgICAgIC8vIHdlIHdpbGwgYWxsb3cgYSBJbnZhbGlkYXRlIHNjaGVtYSB0byBiZSBhIHN0cmluZyBvciBvYmplY3RcbiAgICAgICEoXG4gICAgICAgIChzY2hlbWEgYXMgYW55KS5rZXkgIT09IHVuZGVmaW5lZCAmJlxuICAgICAgICAoc2NoZW1hIGFzIGFueSkucGsgPT09IHVuZGVmaW5lZCAmJlxuICAgICAgICB0eXBlb2YgaW5wdXQgPT09ICdzdHJpbmcnXG4gICAgICApKVxuICApIHtcbiAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgZWxzZSAqL1xuICAgIGlmIChwcm9jZXNzLmVudi5OT0RFX0VOViAhPT0gJ3Byb2R1Y3Rpb24nKSB7XG4gICAgICBjb25zdCBwYXJzZVdvcmtzID0gKGlucHV0OiBzdHJpbmcpID0+IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICByZXR1cm4gdHlwZW9mIEpTT04ucGFyc2UoaW5wdXQpICE9PSAnc3RyaW5nJztcbiAgICAgICAgfSBjYXRjaCB7XG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICB9O1xuICAgICAgaWYgKHR5cGVvZiBpbnB1dCA9PT0gJ3N0cmluZycgJiYgcGFyc2VXb3JrcyhpbnB1dCkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBOb3JtYWxpemluZyBhIHN0cmluZywgYnV0IHRoaXMgZG9lcyBtYXRjaCBzY2hlbWEuXG5cblBhcnNpbmcgdGhpcyBpbnB1dCBzdHJpbmcgYXMgSlNPTiB3b3JrZWQuIFRoaXMgbGlrZWx5IGluZGljYXRlcyBmZXRjaCBmdW5jdGlvbiBkaWQgbm90IHBhcnNlXG50aGUgSlNPTi4gQnkgZGVmYXVsdCwgdGhpcyBvbmx5IGhhcHBlbnMgaWYgXCJjb250ZW50LXR5cGVcIiBoZWFkZXIgaW5jbHVkZXMgXCJqc29uXCIuXG5TZWUgaHR0cHM6Ly9kYXRhY2xpZW50LmlvL3Jlc3QvYXBpL1Jlc3RFbmRwb2ludCNwYXJzZVJlc3BvbnNlIGZvciBtb3JlIGluZm9ybWF0aW9uXG5cbiAgU2NoZW1hOiAke0pTT04uc3RyaW5naWZ5KHNjaGVtYSwgdW5kZWZpbmVkLCAyKX1cbiAgSW5wdXQ6IFwiJHtpbnB1dH1cImApO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgIGBVbmV4cGVjdGVkIGlucHV0IGdpdmVuIHRvIG5vcm1hbGl6ZS4gRXhwZWN0ZWQgdHlwZSB0byBiZSBcIiR7c2NoZW1hVHlwZX1cIiwgZm91bmQgXCIke1xuICAgICAgICAgICAgaW5wdXQgPT09IG51bGwgPyAnbnVsbCcgOiB0eXBlb2YgaW5wdXRcbiAgICAgICAgICB9XCIuXG5cbiAgICAgICAgICBTY2hlbWE6ICR7SlNPTi5zdHJpbmdpZnkoc2NoZW1hLCB1bmRlZmluZWQsIDIpfVxuICAgICAgICAgIElucHV0OiBcIiR7aW5wdXR9XCJgLFxuICAgICAgICApO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBVbmV4cGVjdGVkIGlucHV0IGdpdmVuIHRvIG5vcm1hbGl6ZS4gRXhwZWN0ZWQgdHlwZSB0byBiZSBcIiR7c2NoZW1hVHlwZX1cIiwgZm91bmQgXCIke1xuICAgICAgICAgIGlucHV0ID09PSBudWxsID8gJ251bGwnIDogdHlwZW9mIGlucHV0XG4gICAgICAgIH1cIi5gLFxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICBjb25zdCBkZWxlZ2F0ZSA9IG5ldyBJbW1Ob3JtYWxpemVEZWxlZ2F0ZShcbiAgICB7IGVudGl0aWVzLCBpbmRleGVzLCBlbnRpdGllc01ldGEgfSxcbiAgICBtZXRhLFxuICApO1xuICBjb25zdCB2aXNpdCA9IGdldFZpc2l0KGRlbGVnYXRlKTtcbiAgY29uc3QgcmVzdWx0ID0gdmlzaXQoc2NoZW1hLCBpbnB1dCwgaW5wdXQsIHVuZGVmaW5lZCwgYXJncyk7XG5cbiAgcmV0dXJuIHtcbiAgICByZXN1bHQsXG4gICAgZW50aXRpZXM6IGRlbGVnYXRlLmVudGl0aWVzLFxuICAgIGluZGV4ZXM6IGRlbGVnYXRlLmluZGV4ZXMsXG4gICAgZW50aXRpZXNNZXRhOiBkZWxlZ2F0ZS5lbnRpdGllc01ldGEsXG4gIH07XG59O1xuXG5mdW5jdGlvbiBleHBlY3RlZFNjaGVtYVR5cGUoc2NoZW1hOiBTY2hlbWEpIHtcbiAgcmV0dXJuIFsnb2JqZWN0JywgJ2Z1bmN0aW9uJ10uaW5jbHVkZXModHlwZW9mIHNjaGVtYSkgPyAnb2JqZWN0JyA6IChcbiAgICAgIHR5cGVvZiBzY2hlbWFcbiAgICApO1xufVxuXG4vLyBEZWZhdWx0IGVtcHR5IEltbXV0YWJsZUpTLWxpa2Ugc3RvcmVcbi8vIFVzZXJzIHNob3VsZCBwcm92aWRlIHRoZWlyIG93biBJbW11dGFibGUuTWFwIGluc3RhbmNlc1xuY29uc3QgZW1wdHlJbW11dGFibGVMaWtlOiBJbW11dGFibGVKU011dGFibGVUYWJsZSA9IHtcbiAgZ2V0KCkge1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH0sXG4gIGdldEluKCkge1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH0sXG4gIHNldEluKGs6IHJlYWRvbmx5IHN0cmluZ1tdLCB2YWx1ZTogYW55KSB7XG4gICAgLy8gQ3JlYXRlIGEgc2ltcGxlIG5lc3RlZCBzdHJ1Y3R1cmUgZm9yIHRoZSBlbXB0eSBjYXNlXG4gICAgLy8gVGhpcyBpcyBhIG1pbmltYWwgaW1wbGVtZW50YXRpb24gZm9yIGRlZmF1bHQgZW1wdHkgc3RhdGVcbiAgICBjb25zdCByZXN1bHQgPSB7IC4uLnRoaXMgfSBhcyBhbnk7XG4gICAgbGV0IGN1cnJlbnQgPSByZXN1bHQ7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBrLmxlbmd0aCAtIDE7IGkrKykge1xuICAgICAgaWYgKCFjdXJyZW50W2tbaV1dKSB7XG4gICAgICAgIGN1cnJlbnRba1tpXV0gPSB7fTtcbiAgICAgIH1cbiAgICAgIGN1cnJlbnQgPSBjdXJyZW50W2tbaV1dO1xuICAgIH1cbiAgICBjdXJyZW50W2tbay5sZW5ndGggLSAxXV0gPSB2YWx1ZTtcblxuICAgIC8vIFJldHVybiBhIHByb3BlciBJbW11dGFibGVKUy1saWtlIG9iamVjdFxuICAgIHJldHVybiBjcmVhdGVOZXN0ZWRJbW11dGFibGUocmVzdWx0KTtcbiAgfSxcbn07XG5cbmZ1bmN0aW9uIGNyZWF0ZU5lc3RlZEltbXV0YWJsZShvYmo6IGFueSk6IEltbXV0YWJsZUpTTXV0YWJsZVRhYmxlIHtcbiAgcmV0dXJuIHtcbiAgICBnZXQoa2V5OiBzdHJpbmcpIHtcbiAgICAgIGNvbnN0IHZhbHVlID0gb2JqW2tleV07XG4gICAgICBpZiAodmFsdWUgJiYgdHlwZW9mIHZhbHVlID09PSAnb2JqZWN0Jykge1xuICAgICAgICByZXR1cm4gY3JlYXRlTmVzdGVkSW1tdXRhYmxlKHZhbHVlKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiB2YWx1ZTtcbiAgICB9LFxuICAgIGdldEluKHBhdGg6IHJlYWRvbmx5IHN0cmluZ1tdKSB7XG4gICAgICBsZXQgY3VycmVudCA9IG9iajtcbiAgICAgIGZvciAoY29uc3Qga2V5IG9mIHBhdGgpIHtcbiAgICAgICAgaWYgKGN1cnJlbnQgPT09IHVuZGVmaW5lZCB8fCBjdXJyZW50ID09PSBudWxsKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgICBjdXJyZW50ID0gY3VycmVudFtrZXldO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGN1cnJlbnQ7XG4gICAgfSxcbiAgICBzZXRJbihwYXRoOiByZWFkb25seSBzdHJpbmdbXSwgdmFsdWU6IGFueSkge1xuICAgICAgY29uc3QgcmVzdWx0ID0gZGVlcENsb25lKG9iaik7XG4gICAgICBsZXQgY3VycmVudCA9IHJlc3VsdDtcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcGF0aC5sZW5ndGggLSAxOyBpKyspIHtcbiAgICAgICAgaWYgKCFjdXJyZW50W3BhdGhbaV1dKSB7XG4gICAgICAgICAgY3VycmVudFtwYXRoW2ldXSA9IHt9O1xuICAgICAgICB9XG4gICAgICAgIGN1cnJlbnQgPSBjdXJyZW50W3BhdGhbaV1dO1xuICAgICAgfVxuICAgICAgY3VycmVudFtwYXRoW3BhdGgubGVuZ3RoIC0gMV1dID0gdmFsdWU7XG4gICAgICByZXR1cm4gY3JlYXRlTmVzdGVkSW1tdXRhYmxlKHJlc3VsdCk7XG4gICAgfSxcbiAgfTtcbn1cblxuZnVuY3Rpb24gZGVlcENsb25lKG9iajogYW55KTogYW55IHtcbiAgaWYgKG9iaiA9PT0gbnVsbCB8fCB0eXBlb2Ygb2JqICE9PSAnb2JqZWN0JykgcmV0dXJuIG9iajtcbiAgaWYgKEFycmF5LmlzQXJyYXkob2JqKSkgcmV0dXJuIG9iai5tYXAoZGVlcENsb25lKTtcbiAgY29uc3QgcmVzdWx0OiBhbnkgPSB7fTtcbiAgZm9yIChjb25zdCBrZXkgaW4gb2JqKSB7XG4gICAgcmVzdWx0W2tleV0gPSBkZWVwQ2xvbmUob2JqW2tleV0pO1xuICB9XG4gIHJldHVybiByZXN1bHQ7XG59XG5cbmNvbnN0IGVtcHR5U3RvcmU6IEltbXV0YWJsZVN0b3JlRGF0YSA9IHtcbiAgZW50aXRpZXM6IGVtcHR5SW1tdXRhYmxlTGlrZSxcbiAgaW5kZXhlczogZW1wdHlJbW11dGFibGVMaWtlLFxuICBlbnRpdGllc01ldGE6IGVtcHR5SW1tdXRhYmxlTGlrZSxcbn07XG4iXSwibWFwcGluZ3MiOiJBQUFBLFNBQVNBLFFBQVEsUUFBUSxlQUFlO0FBR3hDLFNBQ0VDLG9CQUFvQixRQUVmLDRCQUE0Qjs7QUFFbkM7O0FBT0E7O0FBUUEsT0FBTyxNQUFNQyxTQUFTLEdBQUdBLENBQ3ZCQyxNQUFxQixFQUNyQkMsS0FBVSxFQUNWQyxJQUFvQixHQUFHLEVBQUUsRUFDekI7RUFBRUMsUUFBUTtFQUFFQyxPQUFPO0VBQUVDO0FBQWlDLENBQUMsR0FB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