Skip to content

Commit

Permalink
chore: better implementation for the discriminator handler
Browse files Browse the repository at this point in the history
N.B: the PR should probaly be squashed so we have a proper commit # for the patch notes.
  • Loading branch information
Supamiu committed May 2, 2019
1 parent 9c307a5 commit 20aedfd
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 14 deletions.
17 changes: 9 additions & 8 deletions src/registration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,21 +20,22 @@ import { ParentOptions } from './decorator/parent-options';
* ]
* ```
*/
export interface Registration {
export interface Registration<T = any> {
/**
* The class holding the discrimination logic that should be used for this entry.
* The class that all children have to extend no matter what.
*
* It can contain the discrimination logic, but if you want to handle inheritance constraint and discriminator separately,
* you have to specify the handler class in `discriminatorHandler`
*/
parent: Class;
parent: Class<T>;
/**
* If you want to introduce discrimination logic on a class provided by an external library,
* You have to use inheritFrom in order to give the parent class that should be used for
* inheritence checks inside the serializer
* Used to define which class handles the discrimination logic, defaults to `parent`'s value.
*/
inheritFrom?: Class;
discriminatorHandler?: Class;
/**
* Possible children, by key.
*/
children: { [index: string]: Class };
children: { [index: string]: Class<T> };
}

/**
Expand Down
12 changes: 6 additions & 6 deletions src/registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,18 +79,18 @@ export class Registry {
} else {
children = reg.children;

const discriminatorHandler = reg.discriminatorHandler || reg.parent;

//Get the metadata for this parent and check if it has the @Parent decorator.
parentOptions = Reflect.getOwnMetadata(METADATA_PARENT, reg.parent);
parentOptions = Reflect.getOwnMetadata(METADATA_PARENT, discriminatorHandler);
if (parentOptions === undefined) {
throw new TypeError(`Class ${reg.parent.name} needs a @Parent decorator to be registered`);
throw new TypeError(`Class ${discriminatorHandler.name} needs a @Parent decorator to be registered`);
}
}

// Flag to know if the parent is registered among its children.
let parentHasExplicitDiscriminator = false;

const inheritFrom = reg.inheritFrom || reg.parent;

for (const value in reg.children) {
const child = reg.children[value];

Expand All @@ -103,8 +103,8 @@ export class Registry {
parentHasExplicitDiscriminator = true;
} else {
//Check if the child extends the parent
if (!(child.prototype instanceof inheritFrom)) {
throw new TypeError(`Class ${child.name} needs to extend ${inheritFrom.name} to be registered as a child`);
if (!(child.prototype instanceof reg.parent)) {
throw new TypeError(`Class ${child.name} needs to extend ${reg.parent.name} to be registered as a child`);
}
}
}
Expand Down
27 changes: 27 additions & 0 deletions test/registry.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,16 @@ class ParentWithTrackBy {
class ChildWithTrackBy extends ParentWithTrackBy {
}

@Parent({
discriminatorField: 'foo',
trackBy: (value: any) => {
return value[1];
}
})
class DiscriminatorHandler {
foo: string[];
}


describe('Registry service', () => {
let registry: Registry;
Expand Down Expand Up @@ -363,4 +373,21 @@ describe('Registry service', () => {
});
});

describe('DiscriminatorHandler tests', () => {
it('Should use discriminatorHandler field when it has been set', () => {
registry.add([
{
parent: ParentWithTrackBy,
discriminatorHandler: DiscriminatorHandler,
children: {
'valueFromTrackBy': ChildWithTrackBy
},
},
],
);

expect(registry.findClass(ParentWithTrackBy, {foo: ['nope', 'valueFromTrackBy']})).to.equal(ChildWithTrackBy);
});
});

});

0 comments on commit 20aedfd

Please sign in to comment.