Skip to content
This repository has been archived by the owner on Nov 17, 2017. It is now read-only.

Support normalizr 3.0 #35

Merged
merged 1 commit into from
Feb 11, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,7 @@ node_modules
# Optional REPL history
.node_repl_history
lib

# IDE
.idea
.vscode
18 changes: 9 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,9 @@ denormalize (entity, entities, schema) -> Object|Array|Immutable.Map|Immutable.L

> An object to entities used to denormalize entity and its referred entities.

**entitySchema** `{Schema}`
**entitySchema** `{schema.Entity}`

> The normalizr Schema used to define `entity`.
> The normalizr schema used to define `entity`.

### Returns

Expand Down Expand Up @@ -86,11 +86,11 @@ where each article has a `author` field.
To normalize this response with normalizr, we can define two Schemas: `articleSchema` and `authorSchema`.

```js
import { normalize, arrayOf, Schema } from 'normalizr';
import { normalize, schema } from 'normalizr';

const articleSchema = new Schema('articles');
const authorSchema = new Schema('authors');
const articleList = arrayOf(articleSchema);
const articleSchema = new schema.Entity('articles');
const authorSchema = new schema.Entity('authors');
const articleList = new schema.Array(articleSchema);

articleSchema.define({
author: authorSchema,
Expand Down Expand Up @@ -256,9 +256,9 @@ Denormalizr can handle circular references caused by recursive schemas (see [#2]
For example, take these schemas, where articles have an author property containing a list of articles:

```js
const articleSchema = new Schema('articles');
const authorSchema = new Schema('author');
const articleList = arrayOf(articleSchema);
const articleSchema = new schema.Entity('articles');
const authorSchema = new schema.Entity('author');
const articleList = new schema.Array(articleSchema);

articleSchema.define({
author: authorSchema,
Expand Down
9 changes: 6 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "denormalizr",
"version": "0.4.1",
"version": "1.0.0",
"description": "Denormalizer for normalizr",
"main": "lib/index.js",
"files": [
Expand Down Expand Up @@ -45,10 +45,13 @@
"immutable": "^3.8.1",
"istanbul": "^1.1.0-alpha.1",
"mocha": "^3.1.0",
"normalizr": "^3.0.2",
"rimraf": "^2.5.4"
},
"dependencies": {
"lodash": "^4.16.3",
"normalizr": "^2.0.0"
"lodash": "^4.17.4"
},
"peerDependencies": {
"normalizr": "^3.0.2"
}
}
16 changes: 0 additions & 16 deletions src/ImmutableUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,19 +60,3 @@ export function setIn(object, keyPath, value) {

return object;
}

/**
* Moves the union to a property with the appropriate schema name.
*
* @param {Object, Immutable.Map, Immutable.Record} object
* @return {Any}
*/
export function moveUnionToSchema(entity) {
if (isImmutable(entity)) {
return {
[entity.get('schema')]: entity.get('id'),
};
}

return Object.assign({}, entity, { [entity.schema]: entity.id });
}
64 changes: 42 additions & 22 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,26 +1,30 @@
import IterableSchema from 'normalizr/lib/IterableSchema';
import EntitySchema from 'normalizr/lib/EntitySchema';
import UnionSchema from 'normalizr/lib/UnionSchema';
import { schema as Schema } from 'normalizr';
import merge from 'lodash/merge';
import isObject from 'lodash/isObject';
import { isImmutable, getIn, setIn, moveUnionToSchema } from './ImmutableUtils';
import { isImmutable, getIn, setIn } from './ImmutableUtils';

const EntitySchema = Schema.Entity;
const ArraySchema = Schema.Array;
const UnionSchema = Schema.Union;
const ValuesSchema = Schema.Values;

/**
* Take either an entity or id and derive the other.
*
* @param {object|Immutable.Map|number|string} entityOrId
* @param {object|Immutable.Map} entities
* @param {Schema} schema
* @param {schema.Entity} schema
* @returns {object}
*/
function resolveEntityOrId(entityOrId, entities, schema) {
const key = schema.getKey();
const key = schema.key;

let entity = entityOrId;
let id = entityOrId;

if (isObject(entityOrId)) {
id = getIn(entity, [schema.getIdAttribute()]);
const mutableEntity = isImmutable(entity) ? entity.toJS() : entity;
id = schema.getId(mutableEntity) || getIn(entity, ['id']);
} else {
entity = getIn(entities, [key, id]);
}
Expand All @@ -33,14 +37,15 @@ function resolveEntityOrId(entityOrId, entities, schema) {
*
* @param {Array|Immutable.List} items
* @param {object|Immutable.Map} entities
* @param {Schema} schema
* @param {schema.Entity} schema
* @param {object} bag
* @returns {Array|Immutable.List}
*/
function denormalizeIterable(items, entities, schema, bag) {
const itemSchema = schema.getItemSchema();
const isMappable = typeof items.map === 'function';

const itemSchema = Array.isArray(schema) ? schema[0] : schema.schema;

// Handle arrayOf iterables
if (isMappable) {
return items.map(o => denormalize(o, entities, itemSchema, bag));
Expand All @@ -57,19 +62,24 @@ function denormalizeIterable(items, entities, schema, bag) {
/**
* @param {object|Immutable.Map|number|string} entity
* @param {object|Immutable.Map} entities
* @param {Schema} schema
* @param {schema.Entity} schema
* @param {object} bag
* @returns {object|Immutable.Map}
*/
function denormalizeUnion(entity, entities, schema, bag) {
const itemSchema = schema.getItemSchema();
const denormalized = denormalize(
moveUnionToSchema(entity),
const schemaAttribute = getIn(entity, ['schema']);
const itemSchema = getIn(schema, ['schema', schemaAttribute]);
if (!itemSchema) return entity;

const mutableEntity = isImmutable(entity) ? entity.toJS() : entity;
const id = itemSchema.getId(mutableEntity) || getIn(entity, ['id']);

return denormalize(
id,
entities,
itemSchema,
bag,
);
return getIn(denormalized, [isImmutable(entity) ? entity.get('schema') : entity.schema]);
}

/**
Expand All @@ -81,19 +91,24 @@ function denormalizeUnion(entity, entities, schema, bag) {
*
* @param {object|Immutable.Map} obj
* @param {object|Immutable.Map} entities
* @param {Schema} schema
* @param {schema.Entity} schema
* @param {object} bag
* @returns {object|Immutable.Map}
*/
function denormalizeObject(obj, entities, schema, bag) {
let denormalized = obj;

Object.keys(schema)
.filter(attribute => attribute.substring(0, 1) !== '_')
const schemaDefinition = typeof schema.inferSchema === 'function'
? schema.inferSchema(obj)
: (schema.schema || schema)
;

Object.keys(schemaDefinition)
// .filter(attribute => attribute.substring(0, 1) !== '_')
.filter(attribute => typeof getIn(obj, [attribute]) !== 'undefined')
.forEach((attribute) => {
const item = getIn(obj, [attribute]);
const itemSchema = getIn(schema, [attribute]);
const itemSchema = getIn(schemaDefinition, [attribute]);

denormalized = setIn(denormalized, [attribute], denormalize(item, entities, itemSchema, bag));
});
Expand All @@ -107,12 +122,12 @@ function denormalizeObject(obj, entities, schema, bag) {
*
* @param {object|Immutable.Map|number|string} entityOrId
* @param {object|Immutable.Map} entities
* @param {Schema} schema
* @param {schema.Entity} schema
* @param {object} bag
* @returns {object|Immutable.Map}
*/
function denormalizeEntity(entityOrId, entities, schema, bag) {
const key = schema.getKey();
const key = schema.key;
const { entity, id } = resolveEntityOrId(entityOrId, entities, schema);

if (!bag.hasOwnProperty(key)) {
Expand Down Expand Up @@ -142,7 +157,7 @@ function denormalizeEntity(entityOrId, entities, schema, bag) {
*
* @param {object|Immutable.Map|array|Immutable.list|number|string} obj
* @param {object|Immutable.Map} entities
* @param {Schema} schema
* @param {schema.Entity} schema
* @param {object} bag
* @returns {object|Immutable.Map|array|Immutable.list}
*/
Expand All @@ -153,11 +168,16 @@ export function denormalize(obj, entities, schema, bag = {}) {

if (schema instanceof EntitySchema) {
return denormalizeEntity(obj, entities, schema, bag);
} else if (schema instanceof IterableSchema) {
} else if (
schema instanceof ValuesSchema ||
schema instanceof ArraySchema ||
Array.isArray(schema)
) {
return denormalizeIterable(obj, entities, schema, bag);
} else if (schema instanceof UnionSchema) {
return denormalizeUnion(obj, entities, schema, bag);
}

// Ensure we don't mutate it non-immutable objects
const entity = isImmutable(obj) ? obj : merge({}, obj);
return denormalizeObject(entity, entities, schema, bag);
Expand Down