Builder API - Overview
Builder API is the contact point for users when they are registering functions and components. It exposes an API that receives the user's code and uploads it to Ollie's checkout flow.
It was designed to allow for easy integration with CI/CD processes and also a CLI. It has three main endpoints for each asset (functions and components):
- List all: list all assets for a given store ID. It enables the users to retrieve all the existent functions or components for the user's store
- Get asset by id: return more data about the specific asset, enabling more complex configurations, i.e env variables for functions
- Upload code: enable users to upload the implementation for the asset
Components
- GET - List All Components Get list of all components
- GET - Components by ID Get component by id
- POST - Upload Component Upload component
Functions
- GET - List All Components Get list of all functions
- GET - Functions by ID Get function by id
- POST - Upload Function Upload function
Architecture
The Builder API is also built on top of Next.js for the same reasons mentioned in the Overview section. It uses the bearer authentication method for data access, forwarding the authorization header.
It doesn't aim to allow the CRUD operation for all fields of the asset. Quite the opposite, it only manages what is related to implementation.
Going deeper into the upload module, the core feature of this API
The endpoint accepts a strict zip file for both assets. The zip file should contain the code implementation respecting the following structure:
- Zip file: as mentioned, the file should be a zip file, which is a democratic compress type across platforms when compared to tarball and similars.
- Size: the API should have a maximum payload size of 5MB to avoid performance issues.
- Typescript: the implementation should be done in Typescript. It was chosen because brings the ease of Javascript but adds type-checking, which is a great feature for user-defined functions. The idea is to use TS to enforce user functions to be designed with the right data contract, that is, receiving for the appropriate payload and also responding with the proper schema;
- External dependencies: to avoid issues with dependencies resolution, it's the client's responsibility to upload the "node_modules" together with the code implementation if it has any external package production dependency. This decision was made because of the complexity of being responsible for resolving the dependencies and having to add another. If the system were to be responsible for dependencies, it also should be responsible for updating them, so when we give the responsibility to users, they could upload when they want with any package they want.
- Entry point: each asset has its specific entry point style, but both should ensure that it is attached to the zip with the proper contract.
- For functions, the entry point is the file "index.ts" which must export a function called handler that receives the payload according to the type of event (items, shipping, and so on) and must respond with the transformed payload after processing. The handler can also throw errors if it wants to communicate a validation failure.
- For components, the entry point is the file "index.ts" that must export as default the React component implementation. It can leverage from any package they want and it could declare "react", "react-dom" and "next" as dev dependencies, because the API already considers those packages in the main application (web app will be addressed after).
After receiving the files, the API validates the files and compiles the code, transforming them into a valid Javascript code.
Updated 7 months ago