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

feat: Create the Medusa API SDK as js-sdk package #7276

Merged
merged 1 commit into from May 16, 2024

Conversation

sradevski
Copy link
Member

@sradevski sradevski commented May 8, 2024

The format of the SDK is something I temporarily did to use in the starter, so it is open for discussion.

Few points that I would like us to decide are:

  1. Should class Medusa export the store endpoints as a flat list (how it was originally) or under a store field (how it > is now in this PR)? There are pros and cons with both approaches, so we need to decide what we prefer. Alternatively, we can export 2 separate MedusaAdmin and MedusaStore classes, and they will only contain either admin or store endpoints but not both.
  2. How should our wrapper of fetch behave? Should we convert to JSON by default? Should we throw exceptions on non-200 statuses (similar to Axios)? For now I kept the API as the standard fetch, but I do think we can provide a bit better experience than that.
  3. Anything else we would like to support as part of the SDK?

Creating as draft until we have a bit better definition of how we want our SDK to look like.

The implementation focuses on the client, and less on the Store and Admin endpoints. Those will be implemented in follow-up PRs

Copy link

vercel bot commented May 8, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
medusa-dashboard ✅ Ready (Inspect) Visit Preview 💬 Add feedback May 15, 2024 2:23pm
3 Ignored Deployments
Name Status Preview Comments Updated (UTC)
api-reference ⬜️ Ignored (Inspect) May 15, 2024 2:23pm
docs-ui ⬜️ Ignored (Inspect) Visit Preview May 15, 2024 2:23pm
medusa-docs ⬜️ Ignored (Inspect) Visit Preview May 15, 2024 2:23pm

Copy link

changeset-bot bot commented May 8, 2024

🦋 Changeset detected

Latest commit: 507a54a

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@medusajs/js-sdk Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

},
}

public product = {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think these can be extracted into their own files, rather than implementing them inline, but I'll refrain from doing that until we decide on the few points I listed in the description.

@srindom
Copy link
Collaborator

srindom commented May 8, 2024

  1. Should class Medusa export the store endpoints as a flat list (how it was originally) or under a store field (how it is now in this PR)? There are pros and cons with both approaches, so we need to decide what we prefer. Alternatively, we can export 2 separate MedusaAdmin and MedusaStore classes, and they will only contain either admin or store endpoints but not both.

Most of the time this SDK will be used for storefront implementations. I, therefore, suggest we stick to the old approach. I.e. do medusa.region -> /store/region and medusa.admin.region -> /admin/region.

  1. How should our wrapper of fetch behave? Should we convert to JSON by default? Should we throw exceptions on non-200 statuses (similar to Axios)? For now I kept the API as the standard fetch, but I do think we can provide a bit better experience than that.

JSON is probably what people want 99/100 times. So, think it makes sense to convert to JSON. That said being able to opt-out of that would be nifty.

  1. Anything else we would like to support as part of the SDK?

Three things come to mind:

  1. Built-in retries (with an Idempotency-Key header; either added by default or specified by the user). Some backed changes are needed before this works as intended, but I believe workflows will enable us to support idempotency on all operations very easily.
  2. Ability to use the SDK for sending requests to custom endpoints; could just be medusa.request(method, path, body) - important thing is that you can reuse auth and retry logic. A more advanced solution would allow you to extend the SDK (e.g., to enable medusa.myResource.list).
  3. (Maybe look into realtime things - e.g., EventSourcing from a workflow subscription) this is a future thing, but would be really cool to have eventually.

@kasperkristensen
Copy link
Contributor

  1. Should class Medusa export the store endpoints as a flat list (how it was originally) or under a store field (how it is now in this PR)? There are pros and cons with both approaches, so we need to decide what we prefer. Alternatively, we can export 2 separate MedusaAdmin and MedusaStore classes, and they will only contain either admin or store endpoints but not both.

Don't have any strong opinion this. But for the sake of getting all the arguments out there - I do agree with Seb that the majority of people will be using the SDK for storefront implementations. With that in mind returning them as a flat list is slightly easier to type out. On the other hand, I have seen a couple of issues/discord over the years of people not understanding why medusa.regions.list() was throwing a CORS error when they were building a admin application/extension. So the clarity of .store/.admin might be slightly better for readability.

  1. How should our wrapper of fetch behave? Should we convert to JSON by default? Should we throw exceptions on non-200 statuses (similar to Axios)? For now I kept the API as the standard fetch, but I do think we can provide a bit better experience than that.

I think we should convert to JSON by default, with an escape hatch if the user needs another format, since JSON conversion will be needed in 99% of cases. Also think we should do something like Axios for errors, as it makes for a better DX. We could also export a safeguard function similar to Axios' axios.isAxiosError.

+1 for allowing users to extend the SDK with their own domains, eg. medusa.invoices.list(), if you skim through old issues and requests you will see quite a few requests for this.

@sradevski
Copy link
Member Author

Hey @srindom @kasperkristensen thanks for the comments guys!

Should class Medusa export the store endpoints as a flat list (how it was originally) or under a store field (how it is now in this PR)? There are pros and cons with both approaches, so we need to decide what we prefer. Alternatively, we can export 2 separate MedusaAdmin and MedusaStore classes, and they will only contain either admin or store endpoints but not both.

I was a bit concerned about what Kasper said where people mix the two up. Do you think it would be a better UX for both admin and store builders if we export StoreClient and AdminClient with pretty much identical constructors?

So if you are building a storefront, you'll do
import {StoreClient} from "@medusajs/js-sdk" instead of import MedusaClient from "@medusajs/js-sdk"?

This would be the only thing that gets impacted, but it will solve the concern that Kasper brought up, without compromising anything really. WDYT?

Otherwise:

  1. Retries is something we will introduce, but not as part of this PR as it is just an enhancement. I will create tickets from the TODOs that are in the code of the SDK currently.
  2. You can already access the "base" fetch even now, which will automatically have all headers and other things set up.
  3. Streaming is definitely possible if the BE supports it, there are few routes we can take here but I feel like it is a discussion for another time
  4. I will modify the current "base" fetch to throw on non-200 and add convert to JSON unless opted out from it.
  5. Doesn't extending the client as class MyClient extends StoreClient { mydomain: {}} work as an interface? I can just ensure this works seamlessly

Let me know if you have any comments, but I think for now we have a consensus on how to proceed on the points I raised, except of how we should expose Admin and Store.

@olivermrbl
Copy link
Contributor

olivermrbl commented May 13, 2024

This would be the only thing that gets impacted, but it will solve the concern that Kasper brought up, without compromising anything really. WDYT?

I think I am leaning toward having:

medusa.store.regions.list()
medusa.admin.regions.list()
medusa.agents.list()
medusa.request("POST", "/agents", ...)

This is not a strong opinion, so I am keen on another approach, too. But I think this gives us a clear separation between store and admin APIs, AND it ships a single entry point, which can be nifty in case you want to wrap it in a context, similar to what we did with medusa-react. I also personally just think it's a better DX to only have a single client and then have autocompletion help you along the way.

packages/core/js-sdk/package.json Outdated Show resolved Hide resolved
packages/core/js-sdk/src/client.ts Outdated Show resolved Hide resolved
Copy link
Contributor

@olivermrbl olivermrbl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, pending a few more approvals from discussion participants

Copy link
Contributor

@kasperkristensen kasperkristensen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

Might be added later, but what are we doing with the auth namespace?

@sradevski
Copy link
Member Author

@kasperkristensen we will indeed add it later, and that can be its own scope.

But basically the Fetch Client will have a couple of methods to manage the lifecycle of authentication, I just didn't go into that yet, I want to get the basic setup in place first

@sradevski
Copy link
Member Author

@srindom I'll get this merged now, but if you have any comments please leave them and I will address them in another PR.

@sradevski sradevski merged commit 845eda4 into develop May 16, 2024
17 checks passed
@sradevski sradevski deleted the feat/introduce-js-sdk branch May 16, 2024 10:30
@github-actions github-actions bot mentioned this pull request May 16, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants