You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This is cumbersome to use, as users have to manually provide the types and there are no compile time checks.
With the output of cds-typer many properties of the Service class can be fully typed. Therefore, I suggest making the Service class generic where the generic parameter is the output of cds-typer for a service. Alternatively, define a new TypedService type if no changes shall be made to the Service class. This concept is already used for adding handlers to actions and functions of a service.
The type ServiceDefinition shall describe the output of cds-typer for a service, much like CdsFunction describes the output of cds-typer for a service operation
importtype*asOrderServiceTypesfrom"@cds-models/OrderService"constorderService : Service<typeofOrderServiceTypes>=cds.services["OrderService"];// Error: param `orderID` missingawaitorderService.emit("orderCanceled",{});// auto-completion and compile time checksawaitorderService.cancelOrder({orderID : "1"});awaitorderService.send("cancelOrder",{orderID : "2"});
In my projects I usually define the TypedService class which looks something like this for the emit method. This is far from perfect and can and should be improved.
// the `kind` property is currently missing in `CdsFunction`typeActionFunctionDef=CdsFunction&{kind: "action"|"function";};/** * Definition of a service as generated by cds-typer */exporttypeServiceDefinition={[key: string]:
|ActionFunctionDef|EventDef|EntityDefinition|EntitySetDefinition<any>|unknown;};typeActionFunctionDef={__returns: any;__parameters: any;(...args: any): any;kind: "action"|"function";};exporttypeServiceActionsFunctions<TextendsServiceDefinition>={[keyinkeyofTasT[key]extendsActionFunctionDef
? key
: never]: T[key]extendsActionFunctionDef ? T[key] : never;};typeEventDef=new()=>Record<string,any>;/** * Definition of a single entity (row in a table) as generated by cds-typer */exporttypeEntityDefinition={new(...args: any[]): any;readonlyactions: Record<any,any>};/** * Definition of an entity set as generated by cds-typer */exporttypeEntitySetDefinition<TextendsInstanceType<EntityDefinition>>={new(...args: any[]): Array<T>;};/** * Resolves to `true` if `T` is an EventDef */typeIsEventDef<T>=TextendsEntityDefinition
? false
: TextendsEntitySetDefinition<infer _>
? false
: TextendsEventDef
? true
: false;/** * Available events in a service */exporttypeServiceEvents<TextendsServiceDefinition>={[keyinkeyofTasIsEventDef<T[key]>extendstrue
? key
: never]: T[key]extendsnew()=> infer U ? U : never;};/** * Available entity sets of a service */exporttypeServiceEntitySets<TextendsServiceDefinition>={[KinkeyofTasT[K]extendsEntitySetDefinition<infer U>
? K
: never]: T[K]extendsEntitySetDefinition<infer U> ? EntitySetDefinition<U> : never;};// module augmentationclassApplicationService<TextendsServiceDefinition>extendsService{emit: {<EextendskeyofServiceEvents<T>>(details: {event: E;data?: ServiceEvents<T>[E];headers?: object;}): Promise<T>;<EextendskeyofServiceEvents<T>>(event: E,data?: ServiceEvents<T>[E],headers?: object): Promise<T>;};}
The text was updated successfully, but these errors were encountered:
thank you for your suggestion! I think in principle, this could be a nice addition to our types. The problem I am seeing here is how services are currently emitted by cds-typer. As you are probably aware, each service will be reflected by their own directory with two files, index.js and index.ts, in it.
So you'd get a directory:
Therefore, the service is represented by the directory structure. For your suggestion to work, we'd actually need to have an artefact, be it some class or type, representing the service, too.
In fact, that has been introduced recently, but it already causes problems when you have a service Foo that also contains an entity Foo.
So we'd end up with:
.
└── @cds-models/
└── OrderServiceTypes/
├── index.js
└── index.ts/
├── class Foo <- this is the entity
└── class Foo <- this is the service, so you now have Foo.Foo
So right now, we are looking into getting rid of this artificial service class inside the file that is already representing the service.
Long story short: while I like the idea in general, I'm afraid I don't see a proper implementation with the structure that is currently emitted by cds-typer.
The
Service
class is currently not generic but has some generic methods, e.g.emit
:This is cumbersome to use, as users have to manually provide the types and there are no compile time checks.
With the output of
cds-typer
many properties of theService
class can be fully typed. Therefore, I suggest making theService
class generic where the generic parameter is the output ofcds-typer
for a service. Alternatively, define a newTypedService
type if no changes shall be made to theService
class. This concept is already used for adding handlers to actions and functions of a service.The type
ServiceDefinition
shall describe the output ofcds-typer
for a service, much likeCdsFunction
describes the output ofcds-typer
for a service operationExample usage:
In my projects I usually define the
TypedService
class which looks something like this for the emit method. This is far from perfect and can and should be improved.The text was updated successfully, but these errors were encountered: