Skip to content

Commit

Permalink
fix(core): Fix bug when instantiating entity from object with getter
Browse files Browse the repository at this point in the history
Relates to #2574
  • Loading branch information
michaelbromley committed Dec 11, 2023
1 parent 82ee913 commit d09452e
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 2 deletions.
69 changes: 69 additions & 0 deletions packages/core/src/entity/base/base.entity.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { DeepPartial } from '@vendure/common/lib/shared-types';
import { describe, expect, it } from 'vitest';

import { Calculated } from '../../common/index';
import { CalculatedPropertySubscriber } from '../subscribers';

import { VendureEntity } from './base.entity';

class ChildEntity extends VendureEntity {
constructor(input?: DeepPartial<ChildEntity>) {
super(input);
}

name: string;

get nameLoud(): string {
return this.name.toUpperCase();
}
}

class ChildEntityWithCalculated extends VendureEntity {
constructor(input?: DeepPartial<ChildEntity>) {
super(input);
}

name: string;

@Calculated()
get nameLoudCalculated(): string {
return this.name.toUpperCase();
}
}

describe('VendureEntity', () => {
it('instantiating a child entity', () => {
const child = new ChildEntity({
name: 'foo',
});

expect(child.name).toBe('foo');
expect(child.nameLoud).toBe('FOO');
});

it('instantiating from existing entity with getter', () => {
const child1 = new ChildEntity({
name: 'foo',
});

const child2 = new ChildEntity(child1);

expect(child2.name).toBe('foo');
expect(child2.nameLoud).toBe('FOO');
});

it('instantiating from existing entity with calculated getter', () => {
const calculatedPropertySubscriber = new CalculatedPropertySubscriber();
const child1 = new ChildEntityWithCalculated({
name: 'foo',
});

// This is what happens to entities after being loaded from the DB
calculatedPropertySubscriber.afterLoad(child1);

const child2 = new ChildEntityWithCalculated(child1);

expect(child2.name).toBe('foo');
expect(child2.nameLoudCalculated).toBe('FOO');
});
});
10 changes: 8 additions & 2 deletions packages/core/src/entity/base/base.entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,14 @@ import { PrimaryGeneratedId } from '../entity-id.decorator';
export abstract class VendureEntity {
protected constructor(input?: DeepPartial<VendureEntity>) {
if (input) {
for (const [key, value] of Object.entries(input)) {
(this as any)[key] = value;
for (const [key, descriptor] of Object.entries(Object.getOwnPropertyDescriptors(input))) {
if (descriptor.get && !descriptor.set) {
// A getter has been moved to the entity instance
// by the CalculatedPropertySubscriber
// and cannot be copied over to the new instance.
continue;
}
(this as any)[key] = descriptor.value;
}
}
}
Expand Down

0 comments on commit d09452e

Please sign in to comment.