@data-client/normalizr
Version:
Normalizes and denormalizes JSON according to schema for Redux and Flux applications
75 lines (72 loc) • 9.94 kB
JavaScript
import { getVisit } from './getVisit.js';
import { NormalizeDelegate } from './NormalizeDelegate.js';
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 (e) {
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 ret = {
result: '',
entities: {
...entities
},
indexes: {
...indexes
},
entitiesMeta: {
...entitiesMeta
}
};
const visit = getVisit(new NormalizeDelegate(ret, meta));
ret.result = visit(schema, input, input, undefined, args);
return ret;
};
function expectedSchemaType(schema) {
return ['object', 'function'].includes(typeof schema) ? 'object' : typeof schema;
}
const emptyStore = {
entities: {},
indexes: {},
entitiesMeta: {}
};
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJnZXRWaXNpdCIsIk5vcm1hbGl6ZURlbGVnYXRlIiwibm9ybWFsaXplIiwic2NoZW1hIiwiaW5wdXQiLCJhcmdzIiwiZW50aXRpZXMiLCJpbmRleGVzIiwiZW50aXRpZXNNZXRhIiwiZW1wdHlTdG9yZSIsIm1ldGEiLCJmZXRjaGVkQXQiLCJkYXRlIiwiRGF0ZSIsIm5vdyIsImV4cGlyZXNBdCIsIkluZmluaXR5IiwidW5kZWZpbmVkIiwicmVzdWx0Iiwic2NoZW1hVHlwZSIsImV4cGVjdGVkU2NoZW1hVHlwZSIsImtleSIsInBrIiwicHJvY2VzcyIsImVudiIsIk5PREVfRU5WIiwicGFyc2VXb3JrcyIsIkpTT04iLCJwYXJzZSIsImUiLCJFcnJvciIsInN0cmluZ2lmeSIsInJldCIsInZpc2l0IiwiaW5jbHVkZXMiXSwic291cmNlcyI6WyIuLi8uLi9zcmMvbm9ybWFsaXplL25vcm1hbGl6ZS50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBnZXRWaXNpdCB9IGZyb20gJy4vZ2V0VmlzaXQuanMnO1xuaW1wb3J0IHR5cGUgeyBTY2hlbWEgfSBmcm9tICcuLi9pbnRlcmZhY2UuanMnO1xuaW1wb3J0IHR5cGUge1xuICBOb3JtYWxpemVNZXRhLFxuICBOb3JtYWxpemVOdWxsYWJsZSxcbiAgTm9ybWFsaXplZFNjaGVtYSxcbiAgU3RvcmVEYXRhLFxufSBmcm9tICcuLi90eXBlcy5qcyc7XG5pbXBvcnQgeyBOb3JtYWxpemVEZWxlZ2F0ZSB9IGZyb20gJy4vTm9ybWFsaXplRGVsZWdhdGUuanMnO1xuXG5leHBvcnQgY29uc3Qgbm9ybWFsaXplID0gPFxuICBTIGV4dGVuZHMgU2NoZW1hID0gU2NoZW1hLFxuICBFIGV4dGVuZHMgUmVjb3JkPHN0cmluZywgUmVjb3JkPHN0cmluZywgYW55PiB8IHVuZGVmaW5lZD4gPSBSZWNvcmQ8XG4gICAgc3RyaW5nLFxuICAgIFJlY29yZDxzdHJpbmcsIGFueT5cbiAgPixcbiAgUiA9IE5vcm1hbGl6ZU51bGxhYmxlPFM+LFxuPihcbiAgc2NoZW1hOiBTIHwgdW5kZWZpbmVkLFxuICBpbnB1dDogYW55LFxuICBhcmdzOiByZWFkb25seSBhbnlbXSA9IFtdLFxuICB7IGVudGl0aWVzLCBpbmRleGVzLCBlbnRpdGllc01ldGEgfTogU3RvcmVEYXRhPEU+ID0gZW1wdHlTdG9yZSxcbiAgbWV0YTogTm9ybWFsaXplTWV0YSA9IHsgZmV0Y2hlZEF0OiAwLCBkYXRlOiBEYXRlLm5vdygpLCBleHBpcmVzQXQ6IEluZmluaXR5IH0sXG4pOiBOb3JtYWxpemVkU2NoZW1hPEUsIFI+ID0+IHtcbiAgLy8gbm8gc2NoZW1hIG1lYW5zIHdlIGRvbid0IHByb2Nlc3MgYXQgYWxsXG4gIGlmIChzY2hlbWEgPT09IHVuZGVmaW5lZCB8fCBzY2hlbWEgPT09IG51bGwpXG4gICAgcmV0dXJuIHtcbiAgICAgIHJlc3VsdDogaW5wdXQsXG4gICAgICBlbnRpdGllcyxcbiAgICAgIGluZGV4ZXMsXG4gICAgICBlbnRpdGllc01ldGEsXG4gICAgfTtcblxuICBjb25zdCBzY2hlbWFUeXBlID0gZXhwZWN0ZWRTY2hlbWFUeXBlKHNjaGVtYSk7XG4gIGlmIChcbiAgICBpbnB1dCA9PT0gbnVsbCB8fFxuICAgICh0eXBlb2YgaW5wdXQgIT09IHNjaGVtYVR5cGUgJiZcbiAgICAgIC8vIHdlIHdpbGwgYWxsb3cgYSBJbnZhbGlkYXRlIHNjaGVtYSB0byBiZSBhIHN0cmluZyBvciBvYmplY3RcbiAgICAgICEoXG4gICAgICAgIChzY2hlbWEgYXMgYW55KS5rZXkgIT09IHVuZGVmaW5lZCAmJlxuICAgICAgICAoc2NoZW1hIGFzIGFueSkucGsgPT09IHVuZGVmaW5lZCAmJlxuICAgICAgICB0eXBlb2YgaW5wdXQgPT09ICdzdHJpbmcnXG4gICAgICApKVxuICApIHtcbiAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgZWxzZSAqL1xuICAgIGlmIChwcm9jZXNzLmVudi5OT0RFX0VOViAhPT0gJ3Byb2R1Y3Rpb24nKSB7XG4gICAgICBjb25zdCBwYXJzZVdvcmtzID0gKGlucHV0OiBzdHJpbmcpID0+IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICByZXR1cm4gdHlwZW9mIEpTT04ucGFyc2UoaW5wdXQpICE9PSAnc3RyaW5nJztcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgfTtcbiAgICAgIGlmICh0eXBlb2YgaW5wdXQgPT09ICdzdHJpbmcnICYmIHBhcnNlV29ya3MoaW5wdXQpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgTm9ybWFsaXppbmcgYSBzdHJpbmcsIGJ1dCB0aGlzIGRvZXMgbWF0Y2ggc2NoZW1hLlxuXG5QYXJzaW5nIHRoaXMgaW5wdXQgc3RyaW5nIGFzIEpTT04gd29ya2VkLiBUaGlzIGxpa2VseSBpbmRpY2F0ZXMgZmV0Y2ggZnVuY3Rpb24gZGlkIG5vdCBwYXJzZVxudGhlIEpTT04uIEJ5IGRlZmF1bHQsIHRoaXMgb25seSBoYXBwZW5zIGlmIFwiY29udGVudC10eXBlXCIgaGVhZGVyIGluY2x1ZGVzIFwianNvblwiLlxuU2VlIGh0dHBzOi8vZGF0YWNsaWVudC5pby9yZXN0L2FwaS9SZXN0RW5kcG9pbnQjcGFyc2VSZXNwb25zZSBmb3IgbW9yZSBpbmZvcm1hdGlvblxuXG4gIFNjaGVtYTogJHtKU09OLnN0cmluZ2lmeShzY2hlbWEsIHVuZGVmaW5lZCwgMil9XG4gIElucHV0OiBcIiR7aW5wdXR9XCJgKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICBgVW5leHBlY3RlZCBpbnB1dCBnaXZlbiB0byBub3JtYWxpemUuIEV4cGVjdGVkIHR5cGUgdG8gYmUgXCIke3NjaGVtYVR5cGV9XCIsIGZvdW5kIFwiJHtcbiAgICAgICAgICAgIGlucHV0ID09PSBudWxsID8gJ251bGwnIDogdHlwZW9mIGlucHV0XG4gICAgICAgICAgfVwiLlxuXG4gICAgICAgICAgU2NoZW1hOiAke0pTT04uc3RyaW5naWZ5KHNjaGVtYSwgdW5kZWZpbmVkLCAyKX1cbiAgICAgICAgICBJbnB1dDogXCIke2lucHV0fVwiYCxcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgVW5leHBlY3RlZCBpbnB1dCBnaXZlbiB0byBub3JtYWxpemUuIEV4cGVjdGVkIHR5cGUgdG8gYmUgXCIke3NjaGVtYVR5cGV9XCIsIGZvdW5kIFwiJHtcbiAgICAgICAgICBpbnB1dCA9PT0gbnVsbCA/ICdudWxsJyA6IHR5cGVvZiBpbnB1dFxuICAgICAgICB9XCIuYCxcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgY29uc3QgcmV0OiBOb3JtYWxpemVkU2NoZW1hPEUsIFI+ID0ge1xuICAgIHJlc3VsdDogJycgYXMgYW55LFxuICAgIGVudGl0aWVzOiB7IC4uLmVudGl0aWVzIH0sXG4gICAgaW5kZXhlczogeyAuLi5pbmRleGVzIH0sXG4gICAgZW50aXRpZXNNZXRhOiB7IC4uLmVudGl0aWVzTWV0YSB9LFxuICB9O1xuICBjb25zdCB2aXNpdCA9IGdldFZpc2l0KG5ldyBOb3JtYWxpemVEZWxlZ2F0ZShyZXQsIG1ldGEpKTtcbiAgcmV0LnJlc3VsdCA9IHZpc2l0KHNjaGVtYSwgaW5wdXQsIGlucHV0LCB1bmRlZmluZWQsIGFyZ3MpO1xuICByZXR1cm4gcmV0O1xufTtcblxuZnVuY3Rpb24gZXhwZWN0ZWRTY2hlbWFUeXBlKHNjaGVtYTogU2NoZW1hKSB7XG4gIHJldHVybiBbJ29iamVjdCcsICdmdW5jdGlvbiddLmluY2x1ZGVzKHR5cGVvZiBzY2hlbWEpID8gJ29iamVjdCcgOiAoXG4gICAgICB0eXBlb2Ygc2NoZW1hXG4gICAgKTtcbn1cblxuY29uc3QgZW1wdHlTdG9yZTogU3RvcmVEYXRhPGFueT4gPSB7XG4gIGVudGl0aWVzOiB7fSxcbiAgaW5kZXhlczoge30sXG4gIGVudGl0aWVzTWV0YToge30sXG59O1xuIl0sIm1hcHBpbmdzIjoiQUFBQSxTQUFTQSxRQUFRLFFBQVEsZUFBZTtBQVF4QyxTQUFTQyxpQkFBaUIsUUFBUSx3QkFBd0I7QUFFMUQsT0FBTyxNQUFNQyxTQUFTLEdBQUdBLENBUXZCQyxNQUFxQixFQUNyQkMsS0FBVSxFQUNWQyxJQUFvQixHQUFHLEVBQUUsRUFDekI7RUFBRUMsUUFBUTtFQUFFQyxPQUFPO0VBQUVDO0FBQTJCLENBQUMsR0FBR0MsVUFBVSxFQUM5REMsSUFBbUIsR0FBRztFQUFFQyxTQUFTLEVBQUUsQ0FBQztFQUFFQyxJQUFJLEVBQUVDLElBQUksQ0FBQ0MsR0FBRyxDQUFDLENBQUM7RUFBRUMsU0FBUyxFQUFFQztBQUFTLENBQUMsS0FDbEQ7RUFDM0I7RUFDQSxJQUFJYixNQUFNLEtBQUtjLFNBQVMsSUFBSWQsTUFBTSxLQUFLLElBQUksRUFDekMsT0FBTztJQUNMZSxNQUFNLEVBQUVkLEtBQUs7SUFDYkUsUUFBUTtJQUNSQyxPQUFPO0lBQ1BDO0VBQ0YsQ0FBQztFQUVILE1BQU1XLFVBQVUsR0FBR0Msa0JBQWtCLENBQUNqQixNQUFNLENBQUM7RUFDN0MsSUFDRUMsS0FBSyxLQUFLLElBQUksSUFDYixPQUFPQSxLQUFLLEtBQUtlLFVBQVU7RUFDMUI7RUFDQSxFQUNHaEIsTUFBTSxDQUFTa0IsR0FBRyxLQUFLSixTQUFTLElBQ2hDZCxNQUFNLENBQVNtQixFQUFFLEtBQUtMLFNBQVMsSUFDaEMsT0FBT2IsS0FBSyxLQUFLLFFBQVEsQ0FDekIsRUFDSjtJQUNBO0lBQ0EsSUFBSW1CLE9BQU8sQ0FBQ0MsR0FBRyxDQUFDQyxRQUFRLEtBQUssWUFBWSxFQUFFO01BQ3pDLE1BQU1DLFVBQVUsR0FBSXRCLEtBQWEsSUFBSztRQUNwQyxJQUFJO1VBQ0YsT0FBTyxPQUFPdUIsSUFBSSxDQUFDQyxLQUFLLENBQUN4QixLQUFLLENBQUMsS0FBSyxRQUFRO1FBQzlDLENBQUMsQ0FBQyxPQUFPeUIsQ0FBQyxFQUFFO1VBQ1YsT0FBTyxLQUFLO1FBQ2Q7TUFDRixDQUFDO01BQ0QsSUFBSSxPQUFPekIsS0FBSyxLQUFLLFFBQVEsSUFBSXNCLFVBQVUsQ0FBQ3RCLEtBQUssQ0FBQyxFQUFFO1FBQ2xELE1BQU0sSUFBSTBCLEtBQUssQ0FBQztBQUN4QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsWUFBWUgsSUFBSSxDQUFDSSxTQUFTLENBQUM1QixNQUFNLEVBQUVjLFNBQVMsRUFBRSxDQUFDLENBQUM7QUFDaEQsWUFBWWIsS0FBSyxHQUFHLENBQUM7TUFDZixDQUFDLE1BQU07UUFDTCxNQUFNLElBQUkwQixLQUFLLENBQ2IsNkRBQTZEWCxVQUFVLGFBQ3JFZixLQUFLLEtBQUssSUFBSSxHQUFHLE1BQU0sR0FBRyxPQUFPQSxLQUFLO0FBQ2xEO0FBQ0Esb0JBQ29CdUIsSUFBSSxDQUFDSSxTQUFTLENBQUM1QixNQUFNLEVBQUVjLFNBQVMsRUFBRSxDQUFDLENBQUM7QUFDeEQsb0JBQW9CYixLQUFLLEdBQ2pCLENBQUM7TUFDSDtJQUNGLENBQUMsTUFBTTtNQUNMLE1BQU0sSUFBSTBCLEtBQUssQ0FDYiw2REFBNkRYLFVBQVUsYUFDckVmLEtBQUssS0FBSyxJQUFJLEdBQUcsTUFBTSxHQUFHLE9BQU9BLEtBQUssSUFFMUMsQ0FBQztJQUNIO0VBQ0Y7RUFFQSxNQUFNNEIsR0FBMkIsR0FBRztJQUNsQ2QsTUFBTSxFQUFFLEVBQVM7SUFDakJaLFFBQVEsRUFBRTtNQUFFLEdBQUdBO0lBQVMsQ0FBQztJQUN6QkMsT0FBTyxFQUFFO01BQUUsR0FBR0E7SUFBUSxDQUFDO0lBQ3ZCQyxZQUFZLEVBQUU7TUFBRSxHQUFHQTtJQUFhO0VBQ2xDLENBQUM7RUFDRCxNQUFNeUIsS0FBSyxHQUFHakMsUUFBUSxDQUFDLElBQUlDLGlCQUFpQixDQUFDK0IsR0FBRyxFQUFFdEIsSUFBSSxDQUFDLENBQUM7RUFDeERzQixHQUFHLENBQUNkLE1BQU0sR0FBR2UsS0FBSyxDQUFDOUIsTUFBTSxFQUFFQyxLQUFLLEVBQUVBLEtBQUssRUFBRWEsU0FBUyxFQUFFWixJQUFJLENBQUM7RUFDekQsT0FBTzJCLEdBQUc7QUFDWixDQUFDO0FBRUQsU0FBU1osa0JBQWtCQSxDQUFDakIsTUFBYyxFQUFFO0VBQzFDLE9BQU8sQ0FBQyxRQUFRLEVBQUUsVUFBVSxDQUFDLENBQUMrQixRQUFRLENBQUMsT0FBTy9CLE1BQU0sQ0FBQyxHQUFHLFFBQVEsR0FDNUQsT0FBT0EsTUFDUjtBQUNMO0FBRUEsTUFBTU0sVUFBMEIsR0FBRztFQUNqQ0gsUUFBUSxFQUFFLENBQUMsQ0FBQztFQUNaQyxPQUFPLEVBQUUsQ0FBQyxDQUFDO0VBQ1hDLFlBQVksRUFBRSxDQUFDO0FBQ2pCLENBQUMiLCJpZ25vcmVMaXN0IjpbXX0=