Closed jkiyo closed 3 years ago
For those who still have some trouble to use Subscribers in vanilla, here is my solution:
I've created an utility function to apply decorators into classes:
const DecorateClass = (decorators, target) => {
decorators = Array.isArray(decorators) ? decorators : [decorators]
decorators.forEach(decorator => decorator(target))
return target
}
And then use the decorators:
const { EventSubscriber } = require('typeorm')
class EverythingSubscriber {
/**
* Returns the class of the entity to which events will listen.
* If this method is omitted, then subscriber will listen to events of all entities.
*
* listenTo?(): Function;
*/
/* afterLoad?(entity: Entity): Promise<any>|void; */
afterLoad ({ entity }) { }
/* beforeInsert?(event: InsertEvent<Entity>): Promise<any>|void; */
beforeInsert ({ connection, queryRunner, manager, entity }) { }
/* beforeUpdate?(event: UpdateEvent<Entity>): Promise<any>|void; */
beforeUpdate ({ connection, queryRunner, manager, entity, databaseEntity, updatedColumns, updatedRelations }) { }
/* beforeRemove?(event: RemoveEvent<Entity>): Promise<any>|void; */
beforeRemove ({ connection, queryRunner, manager, entity, databaseEntity, entityId }) { }
/* afterInsert?(event: InsertEvent<Entity>): Promise<any>|void; */
afterInsert ({ connection, queryRunner, manager, entity }) { }
/* afterUpdate?(event: UpdateEvent<Entity>): Promise<any>|void; */
afterUpdate ({ connection, queryRunner, manager, entity }) { }
/* afterRemove?(event: RemoveEvent<Entity>): Promise<any>|void; */
afterRemove ({ connection, queryRunner, manager, entity }) { }
}
module.exports = DecorateClass(EventSubscriber(/* Decorator params */), EverythingSubscriber)
The DecorateClass function will only work on Classes, to decorate a method the implementation must be different...
@jkiyo this feature is opened for contributions, if you are interested we can make an official solution for this problem
@pleerock I don't think that my solution is the best fit to solve the "subscribers in vanilla javascript" problem. I'm a newbie at the typeorm codebase, and I don't have much freetime to explore the code to make a contribution.
But why does the ConnectionMetadataBuilder.buildSubscribers method filters the subscribers passed by the ConnectionOptions.subscribers
and use only the ones decorated by the EventSubscriber
decorator (that stores the subscriber class at MetadataArgsStorage)?
If there is no impact, can we "skip" this filter for the subscribers provided through ConnectionOptions?
thanks @jkiyo, registering with EventSubscriber works indeed! I'm not familiar with typescript either, so it would be nice to register listeners in Schemas like
listeners: [{
type: 'after-insert',
propertyName: (e) => console.log('AFTER INSERTED entity', e)
}]
Maybe EntitySchemaTransformer.prototype.transform()
https://github.com/typeorm/typeorm/blob/efe1a5ff6e59c61056455b28cc6186e315e60b70/src/entity-schema/EntitySchemaTransformer.ts#L111
could get another block:
if(options.listeners) {
options.listeners.forEach((listener) => {
metadataArgsStorage.entityListeners.push({
target: options.target || options.name,
type: listener.type,
propertyName: listener.propertyName
});
});
}
For being executed correctly, isAllowed
could also receive the metadata.target
:
https://github.com/typeorm/typeorm/blob/efe1a5ff6e59c61056455b28cc6186e315e60b70/src/subscriber/Broadcaster.ts#L37
to being able to check for (this.entityMetadata.target === target)
:
https://github.com/typeorm/typeorm/blob/efe1a5ff6e59c61056455b28cc6186e315e60b70/src/metadata/EntityListenerMetadata.ts#L63
and finally in execute()
of that listener:
https://github.com/typeorm/typeorm/blob/efe1a5ff6e59c61056455b28cc6186e315e60b70/src/metadata/EntityListenerMetadata.ts#L70
if (typeof this.propertyName === 'function')
return this.propertyName(entity);
Do you think that works, @pleerock?
For questions, please check out the community slack or check TypeORM's documentation page on other support avenues - cheers!
Has anyone advanced this? This is a bit old but running into this issued right now for listeners and subscribers in javascript.
@jkiyo your solution will listen all entity schema, how to listen one
Issue type:
[X] question [ ] bug report [ ] feature request [ ] documentation issue
Database system/driver:
[ ]
cordova
[ ]mongodb
[ ]mssql
[ ]mysql
/mariadb
[ ]oracle
[X]postgres
[ ]sqlite
[ ]sqljs
[ ]react-native
TypeORM version:
[ ]
latest
[ ]@next
[X]0.2.6
(or put your version here)I'm trying to configure subscribers using Javascript, but the beforeInsert method on my Subscriber class never get called... Maybe I'm missing some step or configuration?
Doc: https://github.com/typeorm/typeorm/blob/master/docs/connection-options.md
My code looks like this: