dxfrontier / cds-ts-dispatcher

SAP CAP TypeScript entity handler dispatcher.
11 stars 2 forks source link

[FEATURE] `EntityHandler(ALL_ENTITIES)` decorator #58

Closed hakimio closed 3 months ago

hakimio commented 3 months ago

Description

It would be nice to have decorator to listen to entity events on all entities like with SAP srv.after('CREATE', '*', req => {...}).

Suggested solution

@EntityHandler(CDS_DISPATCHER.ALL_ENTITIES)
export class AllEntityHandler {

  @AfterCreateAll()
  @AfterUpdateAll()
  private async aMethod(
     @Result() entity: unknown, // can we be any more specific?
     @Req() request: Request
   ) {
     // ...
   }

}
dragolea commented 3 months ago

Hi, Nope, that will be unknown or any Regarding @AfterCreateAll, @AfterUpdateAll I think here we will use the normal @AfterCreate, @AfterUpdate .. so probably no need to create new decorators

hakimio commented 3 months ago

Normal @AfterCreate, @AfterUpdate decorators instead of @AfterCreateAll, @AfterUpdateAll sounds even better and it makes sense here to use unknown for the entity type initially and narrow it down later based on the request.

hakimio commented 3 months ago

Also, I was thinking if it's better to have a single CDS_DISPATCHER enum with values like ALL_EVENTS and ALL_ENTITIES or instead just have those as separate constants. @EntityHandler(ALL_ENTITIES) might look better and might take less key strokes to type. What do you think?

dragolea commented 3 months ago

@hakimio Yep, both variants are ok, I will prefer the first one which in TS is called module which is nothing that a TS file, previously they had namespaces but this is obsolete and TS suggests to use the module approach.

Using the module approach and exposing it, you instruct the developer that is the key point of the constants of this project.

export const CDS_DISPATCHER = {
  /**
   * Represents all entities. Use `CDS_DISPATCHER.ALL_ENTITIES` with the `EntityHandler` decorator to target all entities in your application.
   *
   * This is a constant, but you can also use the asterisk (`*`) instead of `CDS_DISPATCHER.ALL_ENTITIES`.
   * @example
   * "@EntityHandler(CDS_DISPATCHER.ALL_ENTITIES)"
   */
  ALL_ENTITIES: '*' as const,

  /**
   * Represents the CDS Service. Use `CDS_DISPATCHER.SRV` to inject the CDS Service into your class as a dependency.
   *
   * This is a constant, but you can also use the string `'srv'` instead of `CDS_DISPATCHER.SRV`.
   * @example
   * "@Inject(CDS_DISPATCHER.SRV) private readonly srv: Service"
   */
  SRV: 'srv' as const,
};

this will look like

CDS_DISPATCHER.ALL_ENTITIES 

Xnip2024-05-29_12-39-44

hakimio commented 3 months ago

Minor tip: you can simplify the definition the following way:

export const CDS_DISPATCHER = {
  ALL_ENTITIES: '*',
  SRV: 'srv',
} as const;

No need to put as const next to each property.

dragolea commented 3 months ago

Good point.

dragolea commented 3 months ago

Hi @hakimio, I just deployed a new version, you can use the new overload.

hakimio commented 3 months ago

Thank you, Daniel. The new functionality works great 🙂