Skip to content

Commit

Permalink
feat(core): add onlyOwnProperties option to assign helper (#5330)
Browse files Browse the repository at this point in the history
add option, ignore entities but allow primary keys

Closes #5327
  • Loading branch information
acrosett committed Mar 13, 2024
1 parent 9217bb3 commit a081bea
Show file tree
Hide file tree
Showing 2 changed files with 158 additions and 0 deletions.
11 changes: 11 additions & 0 deletions packages/core/src/entity/EntityAssigner.ts
Expand Up @@ -71,6 +71,16 @@ export class EntityAssigner {
let value = data[propName];
const prop = { ...props[propName], name: propName } as EntityProperty<T>;

if (prop && options.onlyOwnProperties) {
if ([ReferenceKind.MANY_TO_MANY, ReferenceKind.ONE_TO_MANY].includes(prop.kind)) {
return;
}

if ([ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind)) {
value = Utils.extractPK(value, prop.targetMeta);
}
}

if (propName in props && !prop.nullable && value == null) {
throw new Error(`You must pass a non-${value} value to the property ${propName} of entity ${(entity as Dictionary).constructor.name}.`);
}
Expand Down Expand Up @@ -294,6 +304,7 @@ export interface AssignOptions {
updateNestedEntities?: boolean;
updateByPrimaryKey?: boolean;
onlyProperties?: boolean;
onlyOwnProperties?: boolean;
convertCustomTypes?: boolean;
mergeObjectProperties?: boolean;
merge?: boolean;
Expand Down
147 changes: 147 additions & 0 deletions tests/features/entity-assigner/EntityAssigner.mongo.test.ts
Expand Up @@ -119,6 +119,153 @@ describe('EntityAssignerMongo', () => {
});
});

test('#assign() should ignore nested entities when onlyOwnProperties : true (#5327)', async () => {
const jon = new Author('Jon SnowOwn', 'snowown@wall.st');
const book = new Book('Book2', jon);
book._id = new ObjectId();
assign<any>(jon, { books: [book], name: 'Jon SnowOwn2' }, { onlyOwnProperties: true });
expect((jon as any).books.length).toBe(0);
expect(jon.name).toBe('Jon SnowOwn2');
await orm.em.persistAndFlush(jon);
const em = orm.em.fork();
const dbBook = await em.findOne(Book, { _id: book._id });
expect(dbBook).toBeNull();
});

test('#assign() should ignore nested entities when onlyOwnProperties : true (reference) (#5327)', async () => {
const jon = new Author('Jon SnowOwn', 'snowown@wall.st');
const em = orm.em.fork();
await em.persistAndFlush(jon);
const ref = orm.em.getReference(Author, jon._id);
const book = new Book('Book2', jon);
book._id = new ObjectId();
assign<any>(ref, { books: [book], name: 'Jon SnowOwn2' }, { em: orm.em, onlyOwnProperties: true });
expect((ref as any).books).toBeUndefined();
expect(ref.name).toBe('Jon SnowOwn2');
await orm.em.persistAndFlush(ref);
const em2 = orm.em.fork();
const dbBook = await em2.findOne(Book, { _id: book._id });
expect(dbBook).toBeNull();
});

test('#assign() should not allow new 1:1 when onlyOwnProperties : true (#5327)', async () => {
const jon = new Author('Jon SnowOwn', 'snowown@wall.st');
const book = new Book('Book2');
expect(() => assign<any>(book, { author: jon, title: 'GreatBook' }, { em: orm.em, onlyOwnProperties: true }))
.toThrow();
});

test('#assign() should not create nested owned entity when onlyOwnProperties : true (#5327)', async () => {
const book = new Book('Book2', new Author('Temp Author', 'tempmail@wall.st'));

const jon = new Author('Jon SnowOwn', 'snowown@wall.st');
jon._id = new ObjectId();
assign<any>(book, { author: jon, title: 'GreatBook' }, { em: orm.em, onlyOwnProperties: true });
expect(book.title).toBe('GreatBook');
await orm.em.persistAndFlush(book);

const em2 = orm.em.fork();
const dbJon = await em2.findOne(Author, { _id: jon._id });
expect(dbJon).toBeNull();

});

test('#assign() should not create nested owned entity when onlyOwnProperties : true (reference) (#5327)', async () => {
const book = new Book('Book2', new Author('Temp Author', 'tempmail@wall.st'));
book._id = new ObjectId();
const em = orm.em.fork();
await em.persistAndFlush(book);

const ref = orm.em.getReference(Book, book._id);
const jon = new Author('Jon SnowOwn', 'snowown@wall.st');
jon._id = new ObjectId();
assign<any>(ref, { author: jon, title: 'GreatBook' }, { em: orm.em, onlyOwnProperties: true });
expect(ref.title).toBe('GreatBook');
await orm.em.persistAndFlush(ref);

const em2 = orm.em.fork();
const dbJon = await em2.findOne(Author, { _id: jon._id });
expect(dbJon).toBeNull();

});

test('#assign() should not update nested owned entity when onlyOwnProperties : true (#5327)', async () => {

const em = orm.em.fork();
const jon = new Author('Jon SnowOwn', 'snowown@wall.st');
jon._id = new ObjectId();
await em.persistAndFlush([jon]);

expect(jon.termsAccepted).toBe(false);


const payloadJon = {
_id: jon._id,
termsAccepted: true,
};

const book = new Book('Book2', new Author('Temp Author', 'tempmail@wall.st'));
book._id = new ObjectId();

assign<any>(book, { author: payloadJon, title: 'GreatBook' }, { em: orm.em, onlyOwnProperties: true });
expect(book.title).toBe('GreatBook');
await orm.em.persistAndFlush(book);

const em2 = orm.em.fork();
const dbJon = await em2.findOne(Author, { _id: jon._id });
expect(dbJon).toBeTruthy();
expect(dbJon?.termsAccepted).toBe(false);
});

test('#assign() should not update nested owned entity when onlyOwnProperties : true (reference) (#5327)', async () => {
const book = new Book('Book2', new Author('Temp Author', 'tempmail@wall.st'));
book._id = new ObjectId();
const em = orm.em.fork();
const jon = new Author('Jon SnowOwn', 'snowown@wall.st');
jon._id = new ObjectId();
await em.persistAndFlush([book, jon]);

expect(jon.termsAccepted).toBe(false);

const ref = orm.em.getReference(Book, book._id);

const payloadJon = {
_id: jon._id,
termsAccepted: true,
};

assign<any>(ref, { author: payloadJon, title: 'GreatBook' }, { em: orm.em, onlyOwnProperties: true });
expect(ref.title).toBe('GreatBook');
await orm.em.persistAndFlush(ref);

const em2 = orm.em.fork();
const dbJon = await em2.findOne(Author, { _id: jon._id });
expect(dbJon).toBeTruthy();
expect(dbJon?.termsAccepted).toBe(false);
});

test('#assign() should add nested PrimaryKey when onlyOwnProperties : true (#5327)', async () => {
const jon = new Author('Jon SnowOwn', 'snowown@wall.st');
jon._id = new ObjectId();
const em = orm.em.fork();
await em.persistAndFlush(jon);
const book = new Book('Book2');
assign<any>(book, { author: jon._id }, { em: orm.em, onlyOwnProperties: true });
expect(book.author).toBeTruthy();
});

test('#assign() should add nested PrimaryKey when onlyOwnProperties : true (reference) (#5327)', async () => {
const jon = new Author('Jon SnowOwn', 'snowown@wall.st');
const book = new Book('Book2', new Author('Temp Author', 'tempmail@wall.st'));
book._id = new ObjectId();
jon._id = new ObjectId();
const em = orm.em.fork();
await em.persistAndFlush([jon, book]);
const ref = orm.em.getReference(Book, book._id);
assign<any>(ref, { author: jon._id }, { em: orm.em, onlyOwnProperties: true });
expect(ref.author).toBeTruthy();
});

afterAll(async () => orm.close(true));

});

0 comments on commit a081bea

Please sign in to comment.