Call operations from api
Is it possible to call operations from an api? I have a function in operations.ts for creating trips (createTrip(..)), and it'd be nice to be able to call it directly from the API, rather than calling the Prisma function contexts.entities.Trip.create()...
Is this possible?
5 Replies
Hi @Kynetix. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:
----------------------
Short answer: not directly/reliably.
- Wasp Operations (queries/actions) are designed to be called as RPCs from the frontend via wasp/client/operations, not from custom HTTP APIs. You can import and call them on the client or server code paths, but using them as regular HTTP endpoints isn’t a supported/stable pattern. [Using Actions; Declaring Actions]
- For APIs, Wasp supports custom HTTP endpoints where you get access to your Entities via context.entities. That’s the supported way to perform DB work inside APIs. [Using Entities in APIs]
Recommended approach:
- Extract your business logic into a shared function, and have both the Action (createTrip) and the API handler call that shared function. This avoids duplicating logic while keeping each interface (RPC vs HTTP) in its intended place. This mirrors guidance shared by the Wasp team. [Discord thread]
If you need a single public HTTP endpoint, prefer an API route and use context.entities.Trip.create(...) within it. [Using Entities in APIs]
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------
Sorry @Kynetix, I seem to be having a bit of trouble. Don't worry though, I've pinged my support and they will try to fix me up! :technologist:
Perhaps try again in 15mins?
@kapa.ai where would the shared function be? Would it be in the operations file or the API file? I'm thinking of something like this: For instance, if the operations function is CreateTrip(), the shared function would be
export const sharedCreateTrip = (trip)=> {
await CreateTrip(trip)
}
Let me check the knowledge base for you again. One moment! :books:
----------------------
Put the shared business-logic function in a regular module under src (e.g., src/lib/trips.ts or src/server/trips.ts), then import it from both your Action and your API handler. Don’t put it inside the Wasp operation or API file itself—keep it standalone and have both call it. This is the approach suggested by the Wasp team to avoid duplication. [Custom HTTP API; Discord thread]
Example structure:
- src/lib/trips.ts: export async function createTripCore(input, context) { /* use context.entities.Trip */ }
- src/operations.ts: export const createTrip = (args, context) => createTripCore(args, context)
- src/apis.ts: export const createTripApi = (req, context) => createTripCore(req.body, context)
This way both paths reuse the same logic while each stays in its intended interface. [Custom HTTP API; Discord thread]
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------
Sorry @Kynetix, I seem to be having a bit of trouble. Don't worry though, I've pinged my support and they will try to fix me up! :technologist:
Perhaps try again in 15mins?
@Kynetix here is a piece in docs on how to call Queries (but it is same for Actions) from the server (which is what you need): https://wasp.sh/docs/data-model/operations/queries#using-queries-on-the-server .
Queries | Wasp
We'll explain what Queries are and how to use them. If you're looking for a detailed API specification, skip ahead to the API Reference.
What kapa sugggested, which is extracting the core logic into separate function, and then calling that -> that also works. It's hard to say which approach is better, I would probably try doing it with direct call,but if that becomes complex, I would try extracting it.