@jhendrixMSFT mentioned something about a "flavor" option that was intended for client emitters we might want to use e.g., "azure", "unbranded", or - now (maybe new?) - "server".
The idea is to use that new option to make subtle changes to the emitter without duplicating (too much) code or making drastic changes that make the code harder to maintain.
The end result is that we want to generate all model structs and supporting implementations from TypeSpec for both serde::{Deserialize, Serialize} - both because the service will need to serialize and deserialize both unlike the client that might just need one or the other sometimes - and generate traits instead of structs for clients but only the functions (in the trait(s)) for operations. No constructors or endpoint() accessor. We also wouldn't want a ClientOptions or ClientMethodOptions parameter anywhere (or a type that contains one), though we still probably want to pass a Context<'_> because it comes in handy. For consistency, it should probably be second after the &self parameter.
One idea to avoid changing code a lot is that after we generate the function signature, we could break out of the emitter function to avoid generating a body or even curly braces.
A service trait when the end up looking like:
pub trait FooService { // Use "Service" suffix instead of "Client"
async fn get(&self, ctx: Context<'_>, p1: &str, body: GetFooModel, parameters: FooServiceGetParameters) -> Result<FooModel>;
}
We'd still want a <Name>Service<Method>Parameters for optional headers and query parameters. We'd have body request parameters as needed as well. Basically, all the same as the clients but using "Service" instead of "Client" where appropriate.
@jhendrixMSFT mentioned something about a "flavor" option that was intended for client emitters we might want to use e.g., "azure", "unbranded", or - now (maybe new?) - "server".
The idea is to use that new option to make subtle changes to the emitter without duplicating (too much) code or making drastic changes that make the code harder to maintain.
The end result is that we want to generate all model structs and supporting implementations from TypeSpec for both
serde::{Deserialize, Serialize}- both because the service will need to serialize and deserialize both unlike the client that might just need one or the other sometimes - and generate traits instead of structs for clients but only the functions (in the trait(s)) for operations. No constructors orendpoint()accessor. We also wouldn't want aClientOptionsorClientMethodOptionsparameter anywhere (or a type that contains one), though we still probably want to pass aContext<'_>because it comes in handy. For consistency, it should probably be second after the&selfparameter.One idea to avoid changing code a lot is that after we generate the function signature, we could break out of the emitter function to avoid generating a body or even curly braces.
A service trait when the end up looking like:
We'd still want a
<Name>Service<Method>Parametersfor optional headers and query parameters. We'd have body request parameters as needed as well. Basically, all the same as the clients but using "Service" instead of "Client" where appropriate.