Skip to content
This repository has been archived by the owner on Mar 20, 2022. It is now read-only.

Commit

Permalink
Merge branch 'master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
bjartebore authored Feb 20, 2020
2 parents 883cfd2 09256f6 commit 0b1a6ee
Show file tree
Hide file tree
Showing 13 changed files with 214 additions and 44 deletions.
66 changes: 37 additions & 29 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,53 1,61 @@
# v3.5.0

- **Added** ability to dynamically set nested schema type (#415)
- **Changed** Enable loose transformation for object spread operator to improve performance (#431)
- **Fixed** don't use schema to attribute mapping on singular array schemas (#387)
- **Fixed** When normalize() receives null input, don't say it is an object (#411)
- **Fixed** Improve performance of circular reference detection (#420)

# v3.4.0

* **Changed** Now built with Babel 7
* **Added** Support for circular references (gh-335)
* **Added** Symbols are valid keys for Entity keys (gh-369)
* **Added/Changed** Typescript definitions include generics for `normalize` (gh-363)
* **Fixed** denormalization skipping of falsy valued ids used in `Object` schemas (gh-345)
* **Chore** Update dev dependencies
* **Chore** Added Greenkeeper
- **Changed** Now built with Babel 7
- **Added** Support for circular references (gh-335)
- **Added** Symbols are valid keys for Entity keys (gh-369)
- **Added/Changed** Typescript definitions include generics for `normalize` (gh-363)
- **Fixed** denormalization skipping of falsy valued ids used in `Object` schemas (gh-345)
- **Chore** Update dev dependencies
- **Chore** Added Greenkeeper

# v3.3.0

* **Added** ES Module builds
* **Fixed** type error with typescript on array object shorthand (gh-322)
- **Added** ES Module builds
- **Fixed** type error with typescript on array object shorthand (gh-322)

# v3.2.0

* **Added** Support denormalizing from Immutable entities (gh-228)
* **Added** Brought back `get idAttribute()` to `schema.Entity` (gh-226)
* **Fixed** Gracefully handle missing data in `denormalize` (gh-232)
* **Fixed** Prevent infinite recursion in `denormalize` (gh-220)
- **Added** Support denormalizing from Immutable entities (gh-228)
- **Added** Brought back `get idAttribute()` to `schema.Entity` (gh-226)
- **Fixed** Gracefully handle missing data in `denormalize` (gh-232)
- **Fixed** Prevent infinite recursion in `denormalize` (gh-220)

# v3.1.0

* **Added** `denormalize`. (gh-214)
* **Changed** No longer requires all input in a polymorphic schema (`Array`, `Union`, `Values`) have a matching schema definition. (gh-208)
* **Changed** Builds do both rollup and plain babel file conversions. `"main"` property in package.json points to babel-converted files.
- **Added** `denormalize`. (gh-214)
- **Changed** No longer requires all input in a polymorphic schema (`Array`, `Union`, `Values`) have a matching schema definition. (gh-208)
- **Changed** Builds do both rollup and plain babel file conversions. `"main"` property in package.json points to babel-converted files.

# v3.0.0

The entire normalizr package has been rewritten from v2.x for this version. Please refer to the [documentation](/docs) for all changes.

## Added

* `schema.Entity`
* `processStrategy` for modifying `Entity` objects before they're moved to the `entities` stack.
* `mergeStrategy` for merging with multiple entities with the same ID.
* Added `schema.Object`, with a shorthand of `{}`
* Added `schema.Array`, with a shorthand of `[ schema ]`
- `schema.Entity`
- `processStrategy` for modifying `Entity` objects before they're moved to the `entities` stack.
- `mergeStrategy` for merging with multiple entities with the same ID.
- Added `schema.Object`, with a shorthand of `{}`
- Added `schema.Array`, with a shorthand of `[ schema ]`

## Changed

* `Schema` has been moved to a `schema` namespace, available at `schema.Entity`
* `arrayOf` has been replaced by `schema.Array` or `[]`
* `unionOf` has been replaced by `schema.Union`
* `valuesOf` has been replaced by `schema.Values`
- `Schema` has been moved to a `schema` namespace, available at `schema.Entity`
- `arrayOf` has been replaced by `schema.Array` or `[]`
- `unionOf` has been replaced by `schema.Union`
- `valuesOf` has been replaced by `schema.Values`

## Removed

* `normalize` no longer accepts an optional `options` argument. All options are assigned at the schema level.
* Entity schema no longer accepts `defaults` as an option. Use a custom `processStrategy` option to apply defaults as needed.
* `assignEntity` has been replaced by `processStrategy`
* `meta` option. See `processStrategy`
- `normalize` no longer accepts an optional `options` argument. All options are assigned at the schema level.
- Entity schema no longer accepts `defaults` as an option. Use a custom `processStrategy` option to apply defaults as needed.
- `assignEntity` has been replaced by `processStrategy`
- `meta` option. See `processStrategy`
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 1,4 @@
# normalizr [![build status](https://img.shields.io/travis/paularmstrong/normalizr/master.svg?style=flat-square)](https://travis-ci.org/paularmstrong/normalizr) [![Coverage Status](https://img.shields.io/coveralls/paularmstrong/normalizr/master.svg?style=flat-square)](https://coveralls.io/github/paularmstrong/normalizr?branch=master) [![npm version](https://img.shields.io/npm/v/normalizr.svg?style=flat-square)](https://www.npmjs.com/package/normalizr) [![npm downloads](https://img.shields.io/npm/dm/normalizr.svg?style=flat-square)](https://www.npmjs.com/package/normalizr) [![Greenkeeper badge](https://badges.greenkeeper.io/paularmstrong/normalizr.svg)](https://greenkeeper.io/)
# normalizr [![build status](https://img.shields.io/travis/paularmstrong/normalizr/master.svg?style=flat-square)](https://travis-ci.org/paularmstrong/normalizr) [![Coverage Status](https://img.shields.io/coveralls/paularmstrong/normalizr/master.svg?style=flat-square)](https://coveralls.io/github/paularmstrong/normalizr?branch=master) [![npm version](https://img.shields.io/npm/v/normalizr.svg?style=flat-square)](https://www.npmjs.com/package/normalizr) [![npm downloads](https://img.shields.io/npm/dm/normalizr.svg?style=flat-square)](https://www.npmjs.com/package/normalizr)

## Install

Expand Down
7 changes: 5 additions & 2 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 23,7 @@ declare namespace schema {
}

export class Object<T = any> {
constructor(definition: {[key: string]: Schema<T>})
constructor(definition: SchemaObject<T>)
define(definition: Schema): void
}

Expand All @@ -46,8 46,11 @@ export type Schema<T = any> =
| SchemaObject<T>
| SchemaArray<T>;

export type SchemaValueFunction<T> = (t: T) => Schema<T>;
export type SchemaValue<T> = Schema<T> | SchemaValueFunction<T>;

export interface SchemaObject<T> {
[key: string]: Schema<T>
[key: string]: SchemaValue<T>
}

export interface SchemaArray<T> extends Array<Schema<T>> {}
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 1,6 @@
{
"name": "normalizr",
"version": "3.4.1",
"version": "3.5.0",
"description": "Normalizes and denormalizes JSON according to schema for Redux and Flux applications",
"bugs": {
"url": "https://github.com/paularmstrong/normalizr/issues"
Expand Down
41 changes: 41 additions & 0 deletions src/__tests__/__snapshots__/index.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 64,47 @@ Object {
}
`;

exports[`normalize can normalize entity nested inside entity using property from parent 1`] = `
Object {
"entities": Object {
"linkables": Object {
"1": Object {
"data": 2,
"id": 1,
"module_type": "article",
"schema_type": "media",
},
},
"media": Object {
"2": Object {
"id": 2,
"url": "catimage.jpg",
},
},
},
"result": 1,
}
`;

exports[`normalize can normalize entity nested inside object using property from parent 1`] = `
Object {
"entities": Object {
"media": Object {
"2": Object {
"id": 2,
"url": "catimage.jpg",
},
},
},
"result": Object {
"data": 2,
"id": 1,
"module_type": "article",
"schema_type": "media",
},
}
`;

exports[`normalize can use fully custom entity classes 1`] = `
Object {
"entities": Object {
Expand Down
58 changes: 58 additions & 0 deletions src/__tests__/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 12,11 @@ describe('normalize', () => {
expect(() => normalize({})).toThrow();
});

test('cannot normalize with null input', () => {
const mySchema = new schema.Entity('tacos');
expect(() => normalize(null, mySchema)).toThrow(/null/);
});

test('normalizes entities', () => {
const mySchema = new schema.Entity('tacos');

Expand Down Expand Up @@ -157,6 162,59 @@ describe('normalize', () => {

expect(() => normalize(test, testEntity)).not.toThrow();
});

test('can normalize entity nested inside entity using property from parent', () => {
const linkablesSchema = new schema.Entity('linkables');
const mediaSchema = new schema.Entity('media');
const listsSchema = new schema.Entity('lists');

const schemaMap = {
media: mediaSchema,
lists: listsSchema
};

linkablesSchema.define({
data: (parent) => schemaMap[parent.schema_type]
});

const input = {
id: 1,
module_type: 'article',
schema_type: 'media',
data: {
id: 2,
url: 'catimage.jpg'
}
};

expect(normalize(input, linkablesSchema)).toMatchSnapshot();
});

test('can normalize entity nested inside object using property from parent', () => {
const mediaSchema = new schema.Entity('media');
const listsSchema = new schema.Entity('lists');

const schemaMap = {
media: mediaSchema,
lists: listsSchema
};

const linkablesSchema = {
data: (parent) => schemaMap[parent.schema_type]
};

const input = {
id: 1,
module_type: 'article',
schema_type: 'media',
data: {
id: 2,
url: 'catimage.jpg'
}
};

expect(normalize(input, linkablesSchema)).toMatchSnapshot();
});
});

describe('denormalize', () => {
Expand Down
6 changes: 5 additions & 1 deletion src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 43,11 @@ export const schema = {

export const normalize = (input, schema) => {
if (!input || typeof input !== 'object') {
throw new Error(`Unexpected input given to normalize. Expected type to be "object", found "${typeof input}".`);
throw new Error(
`Unexpected input given to normalize. Expected type to be "object", found "${
input === null ? 'null' : typeof input
}".`
);
}

const entities = {};
Expand Down
10 changes: 9 additions & 1 deletion src/schemas/Entity.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 73,15 @@ export default class EntitySchema {
Object.keys(this.schema).forEach((key) => {
if (processedEntity.hasOwnProperty(key) && typeof processedEntity[key] === 'object') {
const schema = this.schema[key];
processedEntity[key] = visit(processedEntity[key], processedEntity, key, schema, addEntity, visitedEntities);
const resolvedSchema = typeof schema === 'function' ? schema(input) : schema;
processedEntity[key] = visit(
processedEntity[key],
processedEntity,
key,
resolvedSchema,
addEntity,
visitedEntities
);
}
});

Expand Down
3 changes: 2 additions & 1 deletion src/schemas/Object.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 4,8 @@ export const normalize = (schema, input, parent, key, visit, addEntity, visitedE
const object = { ...input };
Object.keys(schema).forEach((key) => {
const localSchema = schema[key];
const value = visit(input[key], input, key, localSchema, addEntity, visitedEntities);
const resolvedLocalSchema = typeof localSchema === 'function' ? localSchema(input) : localSchema;
const value = visit(input[key], input, key, resolvedLocalSchema, addEntity, visitedEntities);
if (value === undefined || value === null) {
delete object[key];
} else {
Expand Down
2 changes: 1 addition & 1 deletion src/schemas/Polymorphic.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 45,7 @@ export default class PolymorphicSchema {
if (!this.isSingleSchema && !schemaKey) {
return value;
}
const id = isImmutable(value) ? value.get('id') : value.id;
const id = this.isSingleSchema ? undefined : isImmutable(value) ? value.get('id') : value.id;
const schema = this.isSingleSchema ? this.schema : this.schema[schemaKey];
return unvisit(id || value, schema);
}
Expand Down
12 changes: 12 additions & 0 deletions src/schemas/__tests__/Array.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -192,5 192,17 @@ describe(`${schema.Array.name} denormalization`, () => {
expect(denormalize('123', taco, entities)).toMatchSnapshot();
expect(denormalize('123', taco, fromJS(entities))).toMatchSnapshot();
});

test('does not assume mapping of schema to attribute values when schemaAttribute is not set', () => {
const cats = new schema.Entity('cats');
const catRecord = new schema.Object({
cat: cats
});
const catList = new schema.Array(catRecord);
const input = [{ cat: { id: 1 }, id: 5 }, { cat: { id: 2 }, id: 6 }];
const output = normalize(input, catList);
expect(output).toMatchSnapshot();
expect(denormalize(output.result, catList, output.entities)).toEqual(input);
});
});
});
25 changes: 25 additions & 0 deletions src/schemas/__tests__/__snapshots__/Array.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 66,31 @@ Array [
]
`;

exports[`ArraySchema denormalization Class does not assume mapping of schema to attribute values when schemaAttribute is not set 1`] = `
Object {
"entities": Object {
"cats": Object {
"1": Object {
"id": 1,
},
"2": Object {
"id": 2,
},
},
},
"result": Array [
Object {
"cat": 1,
"id": 5,
},
Object {
"cat": 2,
"id": 6,
},
],
}
`;

exports[`ArraySchema denormalization Class returns the input value if is not an array 1`] = `
Object {
"fillings": Object {},
Expand Down
24 changes: 17 additions & 7 deletions typescript-tests/object.ts
Original file line number Diff line number Diff line change
@@ -1,12 1,22 @@
import { normalize, schema } from '../index'

const data = {
/* ...*/
};
type Response = {
users: Array<{ id: string }>
}
const data: Response = { users: [ { id: 'foo' } ] };
const user = new schema.Entity('users');

const responseSchema = new schema.Object({ users: new schema.Array(user) });
const normalizedData = normalize(data, responseSchema);
{
const responseSchema = new schema.Object({ users: new schema.Array(user) });
const normalizedData = normalize(data, responseSchema);
}

const responseSchemaAlt = { users: new schema.Array(user) };
const normalizedDataAlt = normalize(data, responseSchemaAlt);
{
const responseSchema = new schema.Object<Response>({ users: (response: Response) => new schema.Array(user) });
const normalizedData = normalize(data, responseSchema);
}

{
const responseSchema = { users: new schema.Array(user) };
const normalizedData = normalize(data, responseSchema);
}

0 comments on commit 0b1a6ee

Please sign in to comment.