-
Notifications
You must be signed in to change notification settings - Fork 5
Description
Background
Currently the generated functions are exposed as static methods on a class. For example:
export class AccountService {
static CreateAccount(
this: void,
req: CreateAccountRequest,
initReq?: fm.InitReq,
): Promise<CreateAccountResponse> {
return fm.fetchRequest<CreateAccountResponse>(`/api/accounts`, {
...initReq,
method: 'POST',
body: JSON.stringify(req, fm.replacer),
});
}
}I don't know the original intent of this pattern, but you lose any benefits of having a Service instance that tracks state and you get typescript that's not very idiomatic.
import { AccountService } from './accounts.pb';
const resp = AccountService.CreateAccount(newAccount, {
pathPrefix: API_HOST,
credentials: 'include',
headers: {
'X-CSRF-Protection': 1
}
})Proposal
Introduce a flag use_static_classes which defaults to true for now. When use_static_classes is false, you simply get an exported function that maps to the method name:
export const createAccount = (
req: CreateAccountRequest,
initReq?: InitReq,
): Promise<CreateAccountResponse> => {
{
return fm.fetchRequest<CreateAccountResponse>(`/api/accounts`, {
...initReq,
method: 'POST',
body: JSON.stringify(req, fm.replacer),
});
}
};And then:
import { createAccount } from './accounts.pb';
const resp = createAccount(newAccount, {
pathPrefix: API_HOST,
credentials: 'include',
headers: {
'X-CSRF-Protection': 1
}
})Problem : conflicting function names
The main downside I see in this approach is that there could be ambiguous function names in the case where a single proto file contains multiple services with the same method. This seems unlikely in my experience, but a possible fix could be to generate multiple TS files.
For example: consider accounts.proto contains AccountService and AdminService, both with createAccount methods.
We could generate:
accounts.pb.ts→ all the message definitions.accountservice.gw.pb.ts→ functions for callingAccountServicegateway endpointsadminservice.gw.pb.ts→ functions for callingAdminServicegateway endpoints
Additional Variant
As well as exposing simple functions, we could also introduce a more classical Client. The client instance could be used to store request configuration:
export class AccountServiceClient {
constructor(initReq: InitReq) {
this.initReq = initReq;
}
createAccount(
this: void,
req: CreateAccountRequest
): Promise<CreateAccountResponse> {
return createAccount(req, this.initReq);
}
}