How to Create and Consume API Endpoints Using the Request Module in Celeris Web
To create and consume API endpoints in Celeris Web, initialize the global request configuration using HttpRequestEngine.initRequest in your application entry point, then write thin TypeScript wrapper functions that call request.get, request.post, or other HTTP methods from @celeris/request with strongly-typed parameters and response generics.
The @celeris/request package provides a centralized Axios wrapper that handles token injection, request cancellation, and global message hooks automatically. This architecture allows you to define type-safe API endpoints in dedicated files while the framework manages interceptors, error handling, and UI feedback.
Initialize Global Request Configuration with HttpRequestEngine
Before consuming any endpoints, you must configure the request module's global behavior. This one-time setup happens in your application's entry file (typically main.ts or main.js) using the HttpRequestEngine.initRequest method from packages/web/request/requestConfiguration.ts.
This initialization registers handlers for authentication, error messaging, and request lifecycle events that apply to all subsequent HTTP calls.
Configure Token Injection and Global Handlers
Pass a factory function to initRequest that returns an HttpRequestOptions object containing your global handlers:
import { createApp } from "vue";
import { HttpRequestEngine } from "@celeris/request";
import { getToken } from "@/store/modules/user";
HttpRequestEngine.initRequest(() => ({
getToken,
errorMessageHandler: (msg: string) => console.error("[API error]", msg),
successMessageHandler: (msg: string) => console.log("[API success]", msg),
unauthorizedHandler: () => router.replace({ name: "Login" }),
timeoutHandler: () => console.warn("Request timed out"),
}));
createApp(App).mount("#app");
The getToken function executes before every request to inject the Authorization header. The errorMessageHandler and successMessageHandler control global toast notifications, while unauthorizedHandler manages 401 responses. These configurations persist across the application lifecycle and merge with per-request options defined in individual endpoint wrappers.
Create Type-Safe API Endpoint Wrappers
Endpoint definitions reside in dedicated API files (conventionally under src/apis/) and import the request object from @celeris/request. Each wrapper function specifies the HTTP method, URL, parameters, and response type using TypeScript generics.
Define URL Constants and Parameter Interfaces
Organize your API URLs using a TypeScript enum to prevent hardcoded strings and enable centralized URL management:
import type { MessageMode } from "@celeris/request";
import { request } from "@celeris/request";
enum API {
Login = "/auth/login",
Logout = "/auth/logout",
UserInfo = "/user/info",
PermissionCode = "/auth/permission-code",
}
export interface LoginParams {
username: string;
password: string;
}
Implement HTTP Method Wrappers
Create exported functions that invoke the appropriate request method with type-safe generics. The first argument contains the Axios configuration (url, params, data), while the optional second argument accepts RequestOptions to override global behavior for that specific call:
export function loginApi(
params: LoginParams,
errorMessageMode: MessageMode = "dialog"
) {
return request.post<Omit<FakeUserInfo, "extraInfo">>(
{
url: API.Login,
params,
},
{ errorMessageMode }
);
}
export function logoutApi(errorMessageMode: MessageMode = "dialog") {
return request.get<void>(
{
url: API.Logout,
},
{ errorMessageMode }
);
}
export function userInfoApi(errorMessageMode: MessageMode = "none") {
return request.get<UserInfo>(
{
url: API.UserInfo,
},
{ errorMessageMode }
);
}
export { API };
The request object exposes get, post, put, and delete methods, each accepting a generic type parameter <T> that defines the return type. The second argument's errorMessageMode and successMessageMode properties control how the UI displays feedback for that specific endpoint, overriding the global handlers defined in the initialization step.
Understand the Internal Request Flow
When you call request.post<T>() or any other method, the module executes a coordinated sequence across several core files in packages/web/request/src/.
Request Processing Pipeline
-
Configuration Merge: In
HttpClient.ts(lines 61-68), per-requestRequestOptionsmerge with the globalHttpRequestConfigurationstored byinitRequest. -
Interceptor Execution: The request passes through transforms defined in
axiosTransform.ts, includingbeforeRequest(which attaches tokens viaAxiosCancelerand formats dates) and any customrequestInterceptorsdefined globally. -
HTTP Execution: The configured Axios instance dispatches the request.
-
Response Handling: The response interceptor runs
afterResponseto unwrap standard{ data, code, msg }envelopes and validate HTTP status codes. If the status indicates success,successMessageHandlerexecutes; errors triggererrorMessageHandlerorunauthorizedHandlerfor 401 responses. -
Type Resolution: The Promise resolves with the generic type
Tspecified in the wrapper function, providing full IntelliSense and compile-time type safety.
The HttpClient.ts file manages the Axios instance lifecycle, request cancellation tokens, and form-data serialization through the supportFormData utility, while types.ts defines the RequestOptions and RequestResult interfaces governing all type contracts.
Consume Endpoints in Vue Components
Import your API wrapper functions directly into Vue components or Pinia stores. The request module automatically handles loading states, token refresh, and duplicate request cancellation without additional boilerplate:
<script setup lang="ts">
import { loginApi } from "@/apis/internal/auth";
import { ref } from "vue";
const form = ref({ username: "", password: "" });
const loading = ref(false);
const error = ref("");
async function submit() {
loading.value = true;
error.value = "";
try {
const user = await loginApi(form.value);
// user is typed as Omit<FakeUserInfo, "extraInfo">
// Handle successful login (store token, redirect, etc.)
} catch (e) {
error.value = (e as Error).message;
// Error already handled by global errorMessageHandler
} finally {
loading.value = false;
}
}
</script>
The component receives a fully typed response object while the framework manages the underlying HTTP complexity, including automatic Authorization header injection from the getToken function configured during initialization.
Summary
- Initialize once: Call
HttpRequestEngine.initRequestinmain.tsto configure global token injection, error handlers, and unauthorized redirect behavior. - Create thin wrappers: Define TypeScript functions that call
request.get<T>orrequest.post<T>with strongly typed parameters and theRequestOptionsinterface for message control. - Leverage automatic handling: The
HttpClientinpackages/web/request/src/HttpClient.tsmanages interceptors, request cancellation, and form-data serialization without wrapper modifications. - Consume with type safety: Import wrapper functions into components; responses respect the generic type parameter while errors route through centralized handlers.
Frequently Asked Questions
What is the difference between HttpClient and the request export in Celeris Web?
HttpClient is the internal Axios wrapper class defined in packages/web/request/src/HttpClient.ts that manages interceptors, request cancellation, and configuration merging. The request export is a convenience facade that exposes static methods (get, post, put, delete) delegating to a singleton HttpClient instance, allowing you to invoke HTTP calls without instantiating the client manually.
How does automatic token injection work in the request module?
During initialization via HttpRequestEngine.initRequest, you provide a getToken function that returns the current authentication token. This function executes inside the beforeRequest transform in axiosTransform.ts, automatically attaching the token to the Authorization header of every outgoing request before it reaches the network layer.
Can I override global error handling for specific API calls?
Yes. Pass a RequestOptions object as the second argument to any request method call. Properties like errorMessageMode and successMessageMode accept values such as "dialog", "message", or "none" to customize feedback behavior for that specific endpoint, overriding the global errorMessageHandler configured in main.ts.
Where should I place API endpoint definitions in a Celeris Web project?
Conventionally, endpoint wrappers reside in apps/{app-name}/src/apis/ following the pattern shown in apps/admin/src/apis/internal/auth.ts. Place related endpoints in domain-specific files (e.g., auth.ts for authentication, user.ts for user management), exporting both the API URL enum and the wrapper functions for import by Vue components or state management stores.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →