farrow-js/farrow

Feature Request(farrow-client-api): custom fetcher

Closed this issue ยท 7 comments

#96 #98

At #98, We can do const myApiPipeline = createApiPipeline({ fetcher }). But we ignore another case: code generation at client. In the generated code. the pipeline has been created already, So we still can not custom fetcher at this case.

For now, we can pass the batch options when calling generated function. Could we add new option to the invoke function of api pipeline? Or is there any else way to solve this problem?

Expect

// Generated Code
export const api = {
  addTodo: (input: AddTodoInput, options?: ApiInvokeOptions) =>
    apiPipeline.invoke({ type: 'Single', path: ['addTodo'], input }, options) as Promise<AddTodoOutput>,

  removeTodo: (input: RemoveTodoInput, options?: ApiInvokeOptions) =>
    apiPipeline.invoke({ type: 'Single', path: ['removeTodo'], input }, options) as Promise<RemoveTodoOutput>,
}

// expect could call with custom fetcher
api.addTodo({/** input data */}, { fetcher: customFetcher })

api.setFetcher(fetcjer) will be ok?

Looks yes. But not functional. ๐Ÿ‘€

api.setFetcher(fetcjer)

or

api.addTodo({/** input data */}, { fetcher: customFetcher })

?

We can follow the principle of functional core, imperative shell, and ask a question 'Is it fetcher at the core or at the boundary?'

pipeline.use(middleware) is already dependent on an internal mutable shared state, it let use write many middlewares in a separate way instead of chainable style.

Use functional style in JavaScript/TypeScript is given its cost. We can gain more benefits at the core of our logic to cover the cost.

So, in my opinion, fetcher is something at the boundary, it will be ok to use imperative style rather than functional style.

Of course, an elegant functional approach solve the same problem perfectly will be the best way.

And api.addTodo({/** input data */}, { fetcher: customFetcher }) is not equal to api.setFetcher(fetcher) since it only works once.

When people want to add a specific header to a single request(calling), seems that only api.setFetcher(fetcher) can't do this. Maybe we could support both of them?

Yes, it makes sense.

options.fetcher > setFetcer(fetcher) > default fetcher