Skip to content

Commit

Permalink
feat(core): provide mapped custom types into constructor with `forceE…
Browse files Browse the repository at this point in the history
…ntityConstructor`

Closes #5118
  • Loading branch information
B4nan committed Jan 13, 2024
1 parent 312f293 commit b293789
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 2 deletions.
14 changes: 13 additions & 1 deletion packages/core/src/entity/EntityFactory.ts
Expand Up @@ -384,7 +384,19 @@ export class EntityFactory {
}

if (!meta.properties[k]) {
return data;
const tmp = { ...data };

for (const prop of meta.props) {
if (prop.customType && tmp[prop.name] != null) {
tmp[prop.name] = prop.customType.convertToJSValue(tmp[prop.name], this.platform) as any;
}
}

return tmp;
}

if (meta.properties[k].customType && data[k] != null) {
return meta.properties[k].customType!.convertToJSValue(data[k], this.platform);
}

return data[k];
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/utils/Utils.ts
Expand Up @@ -480,7 +480,7 @@ export class Utils {

if (inside === 2 && token.type === 'Punctuator' && token.value === '{') {
ret.push(ObjectBindingPattern as unknown as string);
i += 2;
i = tokens.findIndex((t, idx) => idx > i + 2 && t.type === 'Punctuator' && t.value === '}');
continue;
}

Expand Down
95 changes: 95 additions & 0 deletions tests/features/custom-types/GH5118.test.ts
@@ -0,0 +1,95 @@
import { Entity, MikroORM, PrimaryKey, Property, Type } from '@mikro-orm/sqlite';

class Value {

protected readonly value: string;

toString() {
return this.value;
}

constructor(id: string) {
this.value = id;
}

}

class SimpleType extends Type<
Value | undefined,
string | undefined
> {

constructor(private classRef: new (value: any) => Value) {
super();
}

convertToDatabaseValue(
value: Value | string | null | undefined,
): string | undefined {
if (!value) {
return undefined;
}
if (typeof value === 'string') {
return value;
}
return value.toString();
}

convertToJSValue(
value: Value | string | undefined,
): Value | undefined {
if (!value) {
return undefined;
}
return new this.classRef(
typeof value === 'object' ? value.toString() : value,
);
}

}

@Entity()
class File {

@PrimaryKey({ type: new SimpleType(Value) })
readonly id: Value;

@Property({ type: new SimpleType(Value) })
readonly uri: Value;

constructor({ id, uri }: { id: Value; uri: Value }) {
this.id = id;
this.uri = uri;
}

}

let orm: MikroORM;

beforeAll(async () => {
orm = await MikroORM.init({
forceEntityConstructor: true,
entities: [File],
dbName: ':memory:',
});
await orm.schema.createSchema();
});

afterAll(async () => {
await orm.close(true);
});

test(`custom types and forceEntityConstructor`, async () => {
await orm.em.fork().persistAndFlush(
new File({
id: new Value('foo'),
uri: new Value('bar'),
}),
);

const retrieved = await orm.em.findOneOrFail(File, {
id: new Value('foo'),
});
expect(retrieved.id).toBeInstanceOf(Value);
expect(retrieved.uri).toBeInstanceOf(Value);
});

0 comments on commit b293789

Please sign in to comment.