@data-client/normalizr
Version:
Normalizes and denormalizes JSON according to schema for Redux and Flux applications
146 lines (138 loc) • 18.1 kB
JavaScript
import _extends from "@babel/runtime/helpers/esm/extends";
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 (_unused) {
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 = _extends({}, 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,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJnZXRWaXNpdCIsIkltbU5vcm1hbGl6ZURlbGVnYXRlIiwibm9ybWFsaXplIiwic2NoZW1hIiwiaW5wdXQiLCJhcmdzIiwiZW50aXRpZXMiLCJpbmRleGVzIiwiZW50aXRpZXNNZXRhIiwiZW1wdHlTdG9yZSIsIm1ldGEiLCJmZXRjaGVkQXQiLCJkYXRlIiwiRGF0ZSIsIm5vdyIsImV4cGlyZXNBdCIsIkluZmluaXR5IiwidW5kZWZpbmVkIiwicmVzdWx0Iiwic2NoZW1hVHlwZSIsImV4cGVjdGVkU2NoZW1hVHlwZSIsImtleSIsInBrIiwicHJvY2VzcyIsImVudiIsIk5PREVfRU5WIiwicGFyc2VXb3JrcyIsIkpTT04iLCJwYXJzZSIsIl91bnVzZWQiLCJFcnJvciIsInN0cmluZ2lmeSIsImRlbGVnYXRlIiwidmlzaXQiLCJpbmNsdWRlcyIsImVtcHR5SW1tdXRhYmxlTGlrZSIsImdldCIsImdldEluIiwic2V0SW4iLCJrIiwidmFsdWUiLCJfZXh0ZW5kcyIsImN1cnJlbnQiLCJpIiwibGVuZ3RoIiwiY3JlYXRlTmVzdGVkSW1tdXRhYmxlIiwib2JqIiwicGF0aCIsImRlZXBDbG9uZSIsIkFycmF5IiwiaXNBcnJheSIsIm1hcCJdLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9ub3JtYWxpemUvbm9ybWFsaXplLmltbS50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBnZXRWaXNpdCB9IGZyb20gJy4vZ2V0VmlzaXQuanMnO1xuaW1wb3J0IHR5cGUgeyBTY2hlbWEgfSBmcm9tICcuLi9pbnRlcmZhY2UuanMnO1xuaW1wb3J0IHR5cGUgeyBOb3JtYWxpemVNZXRhLCBOb3JtYWxpemVOdWxsYWJsZSB9IGZyb20gJy4uL3R5cGVzLmpzJztcbmltcG9ydCB7XG4gIEltbU5vcm1hbGl6ZURlbGVnYXRlLFxuICBJbW11dGFibGVKU011dGFibGVUYWJsZSxcbn0gZnJvbSAnLi9Ob3JtYWxpemVEZWxlZ2F0ZS5pbW0uanMnO1xuXG4vKiogSW1tdXRhYmxlSlMgc3RvcmUgZGF0YSBzdHJ1Y3R1cmUgKi9cbmV4cG9ydCBpbnRlcmZhY2UgSW1tdXRhYmxlU3RvcmVEYXRhIHtcbiAgZW50aXRpZXM6IEltbXV0YWJsZUpTTXV0YWJsZVRhYmxlO1xuICBpbmRleGVzOiBJbW11dGFibGVKU011dGFibGVUYWJsZTtcbiAgZW50aXRpZXNNZXRhOiBJbW11dGFibGVKU011dGFibGVUYWJsZTtcbn1cblxuLyoqIFJlc3VsdCBvZiBub3JtYWxpemluZyBpbnRvIEltbXV0YWJsZUpTIHN0YXRlICovXG5leHBvcnQgaW50ZXJmYWNlIEltbXV0YWJsZU5vcm1hbGl6ZWRTY2hlbWE8Uj4ge1xuICBlbnRpdGllczogSW1tdXRhYmxlSlNNdXRhYmxlVGFibGU7XG4gIHJlc3VsdDogUjtcbiAgaW5kZXhlczogSW1tdXRhYmxlSlNNdXRhYmxlVGFibGU7XG4gIGVudGl0aWVzTWV0YTogSW1tdXRhYmxlSlNNdXRhYmxlVGFibGU7XG59XG5cbmV4cG9ydCBjb25zdCBub3JtYWxpemUgPSA8UyBleHRlbmRzIFNjaGVtYSA9IFNjaGVtYSwgUiA9IE5vcm1hbGl6ZU51bGxhYmxlPFM+PihcbiAgc2NoZW1hOiBTIHwgdW5kZWZpbmVkLFxuICBpbnB1dDogYW55LFxuICBhcmdzOiByZWFkb25seSBhbnlbXSA9IFtdLFxuICB7IGVudGl0aWVzLCBpbmRleGVzLCBlbnRpdGllc01ldGEgfTogSW1tdXRhYmxlU3RvcmVEYXRhID0gZW1wdHlTdG9yZSxcbiAgbWV0YTogTm9ybWFsaXplTWV0YSA9IHsgZmV0Y2hlZEF0OiAwLCBkYXRlOiBEYXRlLm5vdygpLCBleHBpcmVzQXQ6IEluZmluaXR5IH0sXG4pOiBJbW11dGFibGVOb3JtYWxpemVkU2NoZW1hPFI+ID0+IHtcbiAgLy8gbm8gc2NoZW1hIG1lYW5zIHdlIGRvbid0IHByb2Nlc3MgYXQgYWxsXG4gIGlmIChzY2hlbWEgPT09IHVuZGVmaW5lZCB8fCBzY2hlbWEgPT09IG51bGwpXG4gICAgcmV0dXJuIHtcbiAgICAgIHJlc3VsdDogaW5wdXQsXG4gICAgICBlbnRpdGllcyxcbiAgICAgIGluZGV4ZXMsXG4gICAgICBlbnRpdGllc01ldGEsXG4gICAgfTtcblxuICBjb25zdCBzY2hlbWFUeXBlID0gZXhwZWN0ZWRTY2hlbWFUeXBlKHNjaGVtYSk7XG4gIGlmIChcbiAgICBpbnB1dCA9PT0gbnVsbCB8fFxuICAgICh0eXBlb2YgaW5wdXQgIT09IHNjaGVtYVR5cGUgJiZcbiAgICAgIC8vIHdlIHdpbGwgYWxsb3cgYSBJbnZhbGlkYXRlIHNjaGVtYSB0byBiZSBhIHN0cmluZyBvciBvYmplY3RcbiAgICAgICEoXG4gICAgICAgIChzY2hlbWEgYXMgYW55KS5rZXkgIT09IHVuZGVmaW5lZCAmJlxuICAgICAgICAoc2NoZW1hIGFzIGFueSkucGsgPT09IHVuZGVmaW5lZCAmJlxuICAgICAgICB0eXBlb2YgaW5wdXQgPT09ICdzdHJpbmcnXG4gICAgICApKVxuICApIHtcbiAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgZWxzZSAqL1xuICAgIGlmIChwcm9jZXNzLmVudi5OT0RFX0VOViAhPT0gJ3Byb2R1Y3Rpb24nKSB7XG4gICAgICBjb25zdCBwYXJzZVdvcmtzID0gKGlucHV0OiBzdHJpbmcpID0+IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICByZXR1cm4gdHlwZW9mIEpTT04ucGFyc2UoaW5wdXQpICE9PSAnc3RyaW5nJztcbiAgICAgICAgfSBjYXRjaCB7XG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICB9O1xuICAgICAgaWYgKHR5cGVvZiBpbnB1dCA9PT0gJ3N0cmluZycgJiYgcGFyc2VXb3JrcyhpbnB1dCkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBOb3JtYWxpemluZyBhIHN0cmluZywgYnV0IHRoaXMgZG9lcyBtYXRjaCBzY2hlbWEuXG5cblBhcnNpbmcgdGhpcyBpbnB1dCBzdHJpbmcgYXMgSlNPTiB3b3JrZWQuIFRoaXMgbGlrZWx5IGluZGljYXRlcyBmZXRjaCBmdW5jdGlvbiBkaWQgbm90IHBhcnNlXG50aGUgSlNPTi4gQnkgZGVmYXVsdCwgdGhpcyBvbmx5IGhhcHBlbnMgaWYgXCJjb250ZW50LXR5cGVcIiBoZWFkZXIgaW5jbHVkZXMgXCJqc29uXCIuXG5TZWUgaHR0cHM6Ly9kYXRhY2xpZW50LmlvL3Jlc3QvYXBpL1Jlc3RFbmRwb2ludCNwYXJzZVJlc3BvbnNlIGZvciBtb3JlIGluZm9ybWF0aW9uXG5cbiAgU2NoZW1hOiAke0pTT04uc3RyaW5naWZ5KHNjaGVtYSwgdW5kZWZpbmVkLCAyKX1cbiAgSW5wdXQ6IFwiJHtpbnB1dH1cImApO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgIGBVbmV4cGVjdGVkIGlucHV0IGdpdmVuIHRvIG5vcm1hbGl6ZS4gRXhwZWN0ZWQgdHlwZSB0byBiZSBcIiR7c2NoZW1hVHlwZX1cIiwgZm91bmQgXCIke1xuICAgICAgICAgICAgaW5wdXQgPT09IG51bGwgPyAnbnVsbCcgOiB0eXBlb2YgaW5wdXRcbiAgICAgICAgICB9XCIuXG5cbiAgICAgICAgICBTY2hlbWE6ICR7SlNPTi5zdHJpbmdpZnkoc2NoZW1hLCB1bmRlZmluZWQsIDIpfVxuICAgICAgICAgIElucHV0OiBcIiR7aW5wdXR9XCJgLFxuICAgICAgICApO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBVbmV4cGVjdGVkIGlucHV0IGdpdmVuIHRvIG5vcm1hbGl6ZS4gRXhwZWN0ZWQgdHlwZSB0byBiZSBcIiR7c2NoZW1hVHlwZX1cIiwgZm91bmQgXCIke1xuICAgICAgICAgIGlucHV0ID09PSBudWxsID8gJ251bGwnIDogdHlwZW9mIGlucHV0XG4gICAgICAgIH1cIi5gLFxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICBjb25zdCBkZWxlZ2F0ZSA9IG5ldyBJbW1Ob3JtYWxpemVEZWxlZ2F0ZShcbiAgICB7IGVudGl0aWVzLCBpbmRleGVzLCBlbnRpdGllc01ldGEgfSxcbiAgICBtZXRhLFxuICApO1xuICBjb25zdCB2aXNpdCA9IGdldFZpc2l0KGRlbGVnYXRlKTtcbiAgY29uc3QgcmVzdWx0ID0gdmlzaXQoc2NoZW1hLCBpbnB1dCwgaW5wdXQsIHVuZGVmaW5lZCwgYXJncyk7XG5cbiAgcmV0dXJuIHtcbiAgICByZXN1bHQsXG4gICAgZW50aXRpZXM6IGRlbGVnYXRlLmVudGl0aWVzLFxuICAgIGluZGV4ZXM6IGRlbGVnYXRlLmluZGV4ZXMsXG4gICAgZW50aXRpZXNNZXRhOiBkZWxlZ2F0ZS5lbnRpdGllc01ldGEsXG4gIH07XG59O1xuXG5mdW5jdGlvbiBleHBlY3RlZFNjaGVtYVR5cGUoc2NoZW1hOiBTY2hlbWEpIHtcbiAgcmV0dXJuIFsnb2JqZWN0JywgJ2Z1bmN0aW9uJ10uaW5jbHVkZXModHlwZW9mIHNjaGVtYSkgPyAnb2JqZWN0JyA6IChcbiAgICAgIHR5cGVvZiBzY2hlbWFcbiAgICApO1xufVxuXG4vLyBEZWZhdWx0IGVtcHR5IEltbXV0YWJsZUpTLWxpa2Ugc3RvcmVcbi8vIFVzZXJzIHNob3VsZCBwcm92aWRlIHRoZWlyIG93biBJbW11dGFibGUuTWFwIGluc3RhbmNlc1xuY29uc3QgZW1wdHlJbW11dGFibGVMaWtlOiBJbW11dGFibGVKU011dGFibGVUYWJsZSA9IHtcbiAgZ2V0KCkge1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH0sXG4gIGdldEluKCkge1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH0sXG4gIHNldEluKGs6IHJlYWRvbmx5IHN0cmluZ1tdLCB2YWx1ZTogYW55KSB7XG4gICAgLy8gQ3JlYXRlIGEgc2ltcGxlIG5lc3RlZCBzdHJ1Y3R1cmUgZm9yIHRoZSBlbXB0eSBjYXNlXG4gICAgLy8gVGhpcyBpcyBhIG1pbmltYWwgaW1wbGVtZW50YXRpb24gZm9yIGRlZmF1bHQgZW1wdHkgc3RhdGVcbiAgICBjb25zdCByZXN1bHQgPSB7IC4uLnRoaXMgfSBhcyBhbnk7XG4gICAgbGV0IGN1cnJlbnQgPSByZXN1bHQ7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBrLmxlbmd0aCAtIDE7IGkrKykge1xuICAgICAgaWYgKCFjdXJyZW50W2tbaV1dKSB7XG4gICAgICAgIGN1cnJlbnRba1tpXV0gPSB7fTtcbiAgICAgIH1cbiAgICAgIGN1cnJlbnQgPSBjdXJyZW50W2tbaV1dO1xuICAgIH1cbiAgICBjdXJyZW50W2tbay5sZW5ndGggLSAxXV0gPSB2YWx1ZTtcblxuICAgIC8vIFJldHVybiBhIHByb3BlciBJbW11dGFibGVKUy1saWtlIG9iamVjdFxuICAgIHJldHVybiBjcmVhdGVOZXN0ZWRJbW11dGFibGUocmVzdWx0KTtcbiAgfSxcbn07XG5cbmZ1bmN0aW9uIGNyZWF0ZU5lc3RlZEltbXV0YWJsZShvYmo6IGFueSk6IEltbXV0YWJsZUpTTXV0YWJsZVRhYmxlIHtcbiAgcmV0dXJuIHtcbiAgICBnZXQoa2V5OiBzdHJpbmcpIHtcbiAgICAgIGNvbnN0IHZhbHVlID0gb2JqW2tleV07XG4gICAgICBpZiAodmFsdWUgJiYgdHlwZW9mIHZhbHVlID09PSAnb2JqZWN0Jykge1xuICAgICAgICByZXR1cm4gY3JlYXRlTmVzdGVkSW1tdXRhYmxlKHZhbHVlKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiB2YWx1ZTtcbiAgICB9LFxuICAgIGdldEluKHBhdGg6IHJlYWRvbmx5IHN0cmluZ1tdKSB7XG4gICAgICBsZXQgY3VycmVudCA9IG9iajtcbiAgICAgIGZvciAoY29uc3Qga2V5IG9mIHBhdGgpIHtcbiAgICAgICAgaWYgKGN1cnJlbnQgPT09IHVuZGVmaW5lZCB8fCBjdXJyZW50ID09PSBudWxsKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgICBjdXJyZW50ID0gY3VycmVudFtrZXldO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGN1cnJlbnQ7XG4gICAgfSxcbiAgICBzZXRJbihwYXRoOiByZWFkb25seSBzdHJpbmdbXSwgdmFsdWU6IGFueSkge1xuICAgICAgY29uc3QgcmVzdWx0ID0gZGVlcENsb25lKG9iaik7XG4gICAgICBsZXQgY3VycmVudCA9IHJlc3VsdDtcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcGF0aC5sZW5ndGggLSAxOyBpKyspIHtcbiAgICAgICAgaWYgKCFjdXJyZW50W3BhdGhbaV1dKSB7XG4gICAgICAgICAgY3VycmVudFtwYXRoW2ldXSA9IHt9O1xuICAgICAgICB9XG4gICAgICAgIGN1cnJlbnQgPSBjdXJyZW50W3BhdGhbaV1dO1xuICAgICAgfVxuICAgICAgY3VycmVudFtwYXRoW3BhdGgubGVuZ3RoIC0gMV1dID0gdmFsdWU7XG4gICAgICByZXR1cm4gY3JlYXRlTmVzdGVkSW1tdXRhYmxlKHJlc3VsdCk7XG4gICAgfSxcbiAgfTtcbn1cblxuZnVuY3Rpb24gZGVlcENsb25lKG9iajogYW55KTogYW55IHtcbiAgaWYgKG9iaiA9PT0gbnVsbCB8fCB0eXBlb2Ygb2JqICE9PSAnb2JqZWN0JykgcmV0dXJuIG9iajtcbiAgaWYgKEFycmF5LmlzQXJyYXkob2JqKSkgcmV0dXJuIG9iai5tYXAoZGVlcENsb25lKTtcbiAgY29uc3QgcmVzdWx0OiBhbnkgPSB7fTtcbiAgZm9yIChjb25zdCBrZXkgaW4gb2JqKSB7XG4gICAgcmVzdWx0W2tleV0gPSBkZWVwQ2xvbmUob2JqW2tleV0pO1xuICB9XG4gIHJldHVybiByZXN1bHQ7XG59XG5cbmNvbnN0IGVtcHR5U3RvcmU6IEltbXV0YWJsZVN0b3JlRGF0YSA9IHtcbiAgZW50aXRpZXM6IGVtcHR5SW1tdXRhYmxlTGlrZSxcbiAgaW5kZXhlczogZW1wdHlJbW11dGFibGVMaWtlLFxuICBlbnRpdGllc01ldGE6IGVtcHR5SW1tdXRhYmxlTGlrZSxcbn07XG4iXSwibWFwcGluZ3MiOiI7QUFBQSxTQUFTQSxRQUFRLFFBQVEsZUFBZTtBQUd4QyxTQUNFQyxvQkFBb0IsUUFFZiw0QkFBNEI7O0FBRW5DOztBQU9BOztBQVFBLE9BQU8sTUFBTUMsU0FBUyxHQUFHQSxDQUN2QkMsTUFBcUIsRUFDckJDLEtBQVUsRUFDVkMsSUFBb0IsR0FBRyxFQUFFLEVBQ3pCO0VBQUVDLFFBQVE7RUFBRUMsT0FB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