Skip to content

Commit

Permalink
Re-hydrate cached metadata in JavaScriptMetadataProvider
Browse files Browse the repository at this point in the history
- this fixes missing onUpdate handler as it was lost when serializing to JSON cache
  • Loading branch information
Martin Adamek committed Feb 28, 2019
1 parent bc0a8c8 commit 9fc4454
Show file tree
Hide file tree
Showing 7 changed files with 49 additions and 14 deletions.
2 changes: 1 addition & 1 deletion lib/cache/CacheAdapter.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
export interface CacheAdapter {

get(name: string, origin: string): any;
get(name: string): any;

set(name: string, data: any, origin: string): void;

Expand Down
26 changes: 23 additions & 3 deletions lib/metadata/JavaScriptMetadataProvider.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,41 @@
import { MetadataProvider } from './MetadataProvider';
import { Cascade, EntityMetadata, EntityProperty, ReferenceType } from '../decorators/Entity';
import { Utils } from '../utils/Utils';

export class JavaScriptMetadataProvider extends MetadataProvider {

discover(meta: EntityMetadata, name: string): void {
discoverEntity(meta: EntityMetadata, name: string): void {
const { schema } = require(meta.path);
Object.entries(schema.properties).forEach(([name, prop]) => {
if (typeof schema.properties[name] === 'string') {
if (typeof prop === 'string') {
schema.properties[name] = { type: prop };
}
});
Object.assign(meta, schema);

Utils.merge(meta, schema);
Object.entries(meta.properties).forEach(([name, prop]) => {
this.initProperty(prop, name);
});
}

/**
* Re-hydrates missing attributes like `onUpdate` (functions are lost when caching to JSON)
*/
loadFromCache(meta: EntityMetadata, cache: EntityMetadata): void {
Utils.merge(meta, cache);
const { schema } = require(meta.path);

Object.entries(schema.properties).forEach(([name, prop]) => {
if (Utils.isObject(prop)) {
Object.entries(prop).forEach(([attribute, value]) => {
if (!(attribute in meta.properties[name])) {
meta.properties[name][attribute as keyof EntityProperty] = value;
}
});
}
});
}

private initProperty(prop: EntityProperty, propName: string): void {
prop.name = propName;

Expand Down
7 changes: 6 additions & 1 deletion lib/metadata/MetadataProvider.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
import { EntityMetadata } from '../decorators/Entity';
import { MikroORMOptions } from '../MikroORM';
import { Utils } from '../utils/Utils';

export abstract class MetadataProvider {

constructor(protected readonly options: MikroORMOptions) { }

abstract discover(meta: EntityMetadata, name: string): void;
abstract discoverEntity(meta: EntityMetadata, name: string): void;

loadFromCache(meta: EntityMetadata, cache: EntityMetadata): void {
Utils.merge(meta, cache);
}

}
9 changes: 4 additions & 5 deletions lib/metadata/MetadataStorage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,8 @@ export class MetadataStorage {
const path = `${this.options.baseDir}/${basePath}/${file}`;
const target = require(path)[name]; // include the file to trigger loading of metadata
const meta = MetadataStorage.getMetadata(name);
const cache = this.cache.get(name, path);
const cache = this.cache.get(name);
meta.prototype = target.prototype;

// skip already discovered entities
if (Utils.isEntity(target.prototype)) {
Expand All @@ -99,15 +100,13 @@ export class MetadataStorage {

if (cache) {
this.logger.debug(`- using cached metadata for entity ${name}`);
Utils.merge(meta, cache);
meta.prototype = target.prototype;
this.metadataProvider.loadFromCache(meta, cache);

return meta;
}

meta.path = path;
meta.prototype = target.prototype;
this.metadataProvider.discover(meta, name);
this.metadataProvider.discoverEntity(meta, name);

if (!meta.collection && meta.name) {
meta.collection = this.namingStrategy.classToTableName(meta.name);
Expand Down
2 changes: 1 addition & 1 deletion lib/metadata/TypeScriptMetadataProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export class TypeScriptMetadataProvider extends MetadataProvider {
this.sources = this.project.addExistingSourceFiles(dirs);
}

discover(meta: EntityMetadata, name: string): void {
discoverEntity(meta: EntityMetadata, name: string): void {
const file = meta.path.match(/\/[^\/]+$/)![0].replace(/\.js$/, '.ts');
const source = this.sources.find(s => !!s.getFilePath().match(file));
const properties = source!.getClass(name)!.getInstanceProperties();
Expand Down
14 changes: 13 additions & 1 deletion tests/EntityManager.sqlite.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { unlinkSync } from 'fs';
import { Collection, EntityManager, MikroORM } from '../lib';
import { Collection, EntityManager, JavaScriptMetadataProvider, MikroORM } from '../lib';
import { initORMSqlite, wipeDatabaseSqlite } from './bootstrap';
import { Utils } from '../lib/utils/Utils';
import { SqliteDriver } from '../lib/drivers/SqliteDriver';
import { Logger } from '../lib/utils/Logger';
import { EntityMetadata } from '../lib/decorators/Entity';
import { FileCacheAdapter } from '../lib/cache/FileCacheAdapter';

const { Author3 } = require('./entities-js/Author3');
const { Book3 } = require('./entities-js/Book3');
Expand All @@ -29,6 +31,16 @@ describe('EntityManagerSqlite', () => {
expect(await orm.isConnected()).toBe(true);
});

test('onUpdate should be re-hydrated when loading metadata from cache', async () => {
const provider = new JavaScriptMetadataProvider(orm.options);
const cacheAdapter = new FileCacheAdapter(orm.options.cache.options as any);
const cache = cacheAdapter.get('Author3');
const meta = {} as EntityMetadata;
provider.loadFromCache(meta, cache);
expect(meta.properties['updatedAt'].onUpdate).toBeDefined();
expect(meta.properties['updatedAt'].onUpdate!()).toBeInstanceOf(Date);
});

test('should return sqlite driver', async () => {
const driver = orm.em.getDriver<SqliteDriver>();
expect(driver instanceof SqliteDriver).toBe(true);
Expand Down
3 changes: 1 addition & 2 deletions tests/entities/Book.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { ObjectID } from 'mongodb';
import { Collection, Entity, ManyToMany, ManyToOne, PrimaryKey, Property } from '../../lib';
import { Collection, Cascade, Entity, ManyToMany, ManyToOne, PrimaryKey, Property } from '../../lib';
import { Publisher } from './Publisher';
import { Author } from './Author';
import { BookTag } from './book-tag';
import { BaseEntity3 } from './BaseEntity3';
import { Cascade } from '../../lib/decorators/Entity';

@Entity({ collection: 'books-table' })
export class Book extends BaseEntity3 {
Expand Down

0 comments on commit 9fc4454

Please sign in to comment.