ecyrbe / zodios

typescript http client and server with zod validation
https://www.zodios.org/
MIT License
1.71k stars 46 forks source link

Allow more patterns to attach plugins and skip them #312

Closed ecyrbe closed 1 year ago

ecyrbe commented 1 year ago

Today we allow plugins to be attached to any endpoint or one specific endpoint. This may not be enough for complex use cases where you want to enable a plugin for all endpoint but one or two. So we may need to improve layers of plugins and have better control over ordering. To do so, we can add custom filter for each matching

for exemple :

// today
client.use(myPlugin); // attach plugin to all endpoints
client.use('get', '/users', myPlugin); // attach plugin to one endpoint by path
client.use('getUsers', myPlugin); // attach plugin to one endpoint by alias

// proposal addition
client.use({
  method: (method) => ['get', 'post'].includes(method),
  path: (path) => /^\/users/.test(path);  // match any endpoint that starts with '/users'
  alias: ()=> true, // optional, since default for matching is always true
}, myPlugin);

// this will also work
client.use({
  // no method or alias filter provided, will match all methods or aliases that match the filter for path,
  path: /^\/users/;  // pass a regexp directly
}, myPlugin);

// and this
client.use({
  alias: 'getUsers'; // you can path a string to only match one endpoint, like today but with object syntax
}, myPlugin);

we will also allow to cusomize priority (last parameter of use):

client.use(myPlugin, 'high'); // priority high plugins are executed first (low, normal, high are available)

Plugins with same priority are executed in order of declaration for requests and in reverse order for responses/error.

The plugin will be applied to an endpoint if all filter patterns return true

lucas-santosP commented 1 year ago

That's a great idea and would improve many use cases like this one https://github.com/ecyrbe/zodios/issues/280, but now instead of removing the header from some endpoints, we will be able to apply the header only to the required endpoints. For example:

client.use(
  {
    method: () => true,
    path: (path) => path.test(/^\/admin/), // match any endpoint that starts with '/admin'
  },
  pluginToken({ getToken: async () => localStorage.getItem("admin-auth") })
);

I would suggest making the method function optional as well, so it will match all methods by default. Because in my opinion that's going to fit in the majority of the use cases.

And just to be clear, the alias function will receive the alias as a param too right?

ecyrbe commented 1 year ago

Yes, method, path and alias will be optional and default to return true and so match anything. method, path and alias functions will get passed the corresponding endpoint definition method, path and alias. I'm also planning to support passing a string and a regex to match in addition to the functions to simplify common use cases I'll share the interface here as soon as possible

ecyrbe commented 1 year ago

Available in beta 17 of

stale[bot] commented 1 year ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.