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

Commit

Permalink
Merge pull request #35 from brunolemos/normalizr-3
Browse files Browse the repository at this point in the history
Support normalizr 3.0
  • Loading branch information
gpbl committed Feb 11, 2017
2 parents 08ede86 + 8d33a7f commit c3b4bf3
Show file tree
Hide file tree
Showing 8 changed files with 406 additions and 315 deletions.
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

0 comments on commit c3b4bf3

Please sign in to comment.