Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create architecture for calls to HTTP API #39

Closed
maninak opened this issue Jun 21, 2023 · 1 comment · Fixed by #72
Closed

Create architecture for calls to HTTP API #39

maninak opened this issue Jun 21, 2023 · 1 comment · Fixed by #72
Assignees
Labels
chore Tooling or infra-related, not directly affecting core product

Comments

@maninak
Copy link
Collaborator

maninak commented Jun 21, 2023

Until now we've been making snowflake, one-off, hard-coded calls and handling against the Radicle HTTP API. We should instead design and implement a properly architected abstraction for sending those requests:

@maninak maninak added this to the v0.3 - Patch Proposals milestone Jun 21, 2023
@maninak maninak added the chore Tooling or infra-related, not directly affecting core product label Jun 21, 2023
@maninak maninak self-assigned this Aug 28, 2023
@maninak
Copy link
Collaborator Author

maninak commented Aug 29, 2023

Result:

The main httpd client implementation (including examples in its JSDoc) can be seen here.

  • a single, very simple function, with auto-completable params which are designed either with sane defaults to result in declarative, clean client code and enforce/forbid further param definitions at the type level.
  • error handling is streamlined and standardized. Client-code receives strong typings which at the type level and have either the data or the error defined, but never both, resulting in neat client code.
  • different Fetch errors result in different user-facing notification copies which come with buttons for more context or direct link to specific related setting, change of which could lead to a solution
  • response.data typings are resolved automatically depending on the call params used
  • there's the option for an easy future refactoring into stricter and more explicit overloads of fetchFromHttpd() (instead of the current generic ones) if that ends up being preferable
  • solution is easily expandable with a transparent global auth layer necessary for requests needed in the future (e.g. update patch state)
  • solution already supports both Node.js and Web-browser environments which keeps future possible support for WebExtention simpler
  • we do no runtime validation of returned json keys and value types (e.g. with zod, valibot, superstruct, typia etc), which keeps our solution simple, our code short, our dependencies less, and our perf without that overhead.
    • if a field we use gets removed or renamed the app will break and there's not much better handling we can do about that with runtime validation anyway, other than get in the source code and update our typings which will in turn force us to update our implementation.
    • if a field we don't use has a breaking change, the app will keep working normally (vs if we did runtime-validation of returned types)
    • ensuring our implementation remains up to date with the returned JSON shapes will be best done via E2E tests.

Here's some client code examples:

(await fetchFromHttpd('/')).data?.service // "radicle-httpd"
const { data: projects, error } = await fetchFromHttpd('/projects')
if (error) {
  notifyUserAboutFetchError(error) // optionally
  return
}
// use `projects` ...
const { error } = await fetchFromHttpd(
  `/projects/${projectId}/patches/${patchId}`,
  'PATCH',
  { state: 'merged' },
)
if (error) {
  notifyUserAboutFetchError(error)
  return false
}
return true

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
chore Tooling or infra-related, not directly affecting core product
Projects
Archived in project
1 participant