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

Commit

Permalink
Merge c360172 into 88a25c5
Browse files Browse the repository at this point in the history
  • Loading branch information
ntucker committed Jul 12, 2019
2 parents 88a25c5 + c360172 commit 0035993
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 44 deletions.
89 changes: 46 additions & 43 deletions index.d.ts
@@ -1,63 +1,66 @@
declare namespace schema {
export type StrategyFunction = (value: any, parent: any, key: string) => any;
export type StrategyFunction<T> = (value: any, parent: any, key: string) => T;
export type SchemaFunction = (value: any, parent: any, key: string) => string;
export type MergeFunction = (entityA: any, entityB: any) => any;

export class Array {
constructor(definition: Schema, schemaAttribute?: string | SchemaFunction)
define(definition: Schema): void
export class Array<T = any> {
constructor(definition: Schema<T>, schemaAttribute?: string | SchemaFunction);
define(definition: Schema): void;
}

export interface EntityOptions {
idAttribute?: string | SchemaFunction
mergeStrategy?: MergeFunction
processStrategy?: StrategyFunction
export interface EntityOptions<T = any> {
idAttribute?: string | SchemaFunction;
mergeStrategy?: MergeFunction;
processStrategy?: StrategyFunction<T>;
}

export class Entity {
constructor(key: string | symbol, definition?: Schema, options?: EntityOptions)
define(definition: Schema): void
key: string
export class Entity<T = any> {
constructor(key: string | symbol, definition?: Schema, options?: EntityOptions<T>);
define(definition: Schema): void;
key: string;
getId: SchemaFunction;
_processStrategy: StrategyFunction<T>;
}

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

export class Union {
constructor(definition: Schema, schemaAttribute?: string | SchemaFunction)
define(definition: Schema): void
export class Union<T = any> {
constructor(definition: Schema<T>, schemaAttribute?: string | SchemaFunction);
define(definition: Schema): void;
}

export class Values {
constructor(definition: Schema, schemaAttribute?: string | SchemaFunction)
define(definition: Schema): void
export class Values<T = any> {
constructor(definition: Schema<T>, schemaAttribute?: string | SchemaFunction);
define(definition: Schema): void;
}
}

export type Schema =
schema.Array |
schema.Entity |
schema.Object |
schema.Union |
schema.Values |
schema.Array[] |
schema.Entity[] |
schema.Object[] |
schema.Union[] |
schema.Values[] |
{[key: string]: Schema | Schema[]};

export type NormalizedSchema<E, R> = { entities: E, result: R };

export function normalize<E = any, R = any>(
interface SimpleObject {
[key: string]: SimpleObject | string | number | boolean | void;
}

export type Schema<T = any> =
| schema.Entity<T>
| schema.Object<T>
| schema.Union<T>
| schema.Values<T>
| SchemaObject<T>
| SchemaArray<T>;

export interface SchemaObject<T> {
[key: string]: Schema<T> | string | number | boolean | void | SimpleObject;
}

export interface SchemaArray<T> extends Array<Schema<T>> {}

export type NormalizedSchema<E, R> = { entities: E; result: R };

export function normalize<T = any, E = { [key: string]: { [key: string]: T } }, R = any>(
data: any,
schema: Schema
schema: Schema<T>
): NormalizedSchema<E, R>;

export function denormalize(
input: any,
schema: Schema,
entities: any
): any;
export function denormalize(input: any, schema: Schema, entities: any): any;
40 changes: 40 additions & 0 deletions src/__tests__/__snapshots__/index.test.js.snap
Expand Up @@ -35,6 +35,22 @@ Object {
}
`;

exports[`denormalize denormalizes schema with extra members 1`] = `
Object {
"data": Array [
Object {
"id": 1,
"type": "foo",
},
Object {
"id": 2,
"type": "bar",
},
],
"extra": "5",
}
`;

exports[`denormalize denormalizes with function as idAttribute 1`] = `
Array [
Object {
Expand Down Expand Up @@ -178,6 +194,30 @@ Object {
}
`;

exports[`normalize normalizes schema with extra members 1`] = `
Object {
"entities": Object {
"tacos": Object {
"1": Object {
"id": 1,
"type": "foo",
},
"2": Object {
"id": 2,
"type": "bar",
},
},
},
"result": Object {
"data": Array [
1,
2,
],
"extra": "five",
},
}
`;

exports[`normalize passes over pre-normalized values 1`] = `
Object {
"entities": Object {
Expand Down
22 changes: 22 additions & 0 deletions src/__tests__/index.test.js
Expand Up @@ -18,6 +18,17 @@ describe('normalize', () => {
expect(normalize([{ id: 1, type: 'foo' }, { id: 2, type: 'bar' }], [mySchema])).toMatchSnapshot();
});

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

expect(
normalize(
{ data: [{ id: 1, type: 'foo' }, { id: 2, type: 'bar' }], extra: 'five' },
{ data: [mySchema], extra: '' }
)
).toMatchSnapshot();
});

test('normalizes entities with circular references', () => {
const user = new schema.Entity('users');
user.define({
Expand Down Expand Up @@ -179,6 +190,17 @@ describe('denormalize', () => {
expect(denormalize([1, 2], [mySchema], entities)).toMatchSnapshot();
});

test('denormalizes schema with extra members', () => {
const mySchema = new schema.Entity('tacos');
const entities = {
tacos: {
1: { id: 1, type: 'foo' },
2: { id: 2, type: 'bar' }
}
};
expect(denormalize({ data: [1, 2], extra: '5' }, { data: [mySchema], extra: '' }, entities)).toMatchSnapshot();
});

test('denormalizes nested entities', () => {
const user = new schema.Entity('users');
const comment = new schema.Entity('comments', {
Expand Down
6 changes: 5 additions & 1 deletion src/index.js
Expand Up @@ -95,7 +95,11 @@ const getUnvisit = (entities) => {
return unvisitEntity(input, schema, unvisit, getEntity, cache);
}

return schema.denormalize(input, unvisit);
if (typeof schema.denormalize === 'function') {
return schema.denormalize(input, unvisit);
}

return input;
};
};

Expand Down

0 comments on commit 0035993

Please sign in to comment.