@base44/sdk
Version:
JavaScript SDK for Base44 API
205 lines (204 loc) • 7.94 kB
JavaScript
import { createAxiosClient } from "./utils/axios-client.js";
import { createEntitiesModule } from "./modules/entities.js";
import { createIntegrationsModule } from "./modules/integrations.js";
import { createAuthModule } from "./modules/auth.js";
import { createSsoModule } from "./modules/sso.js";
import { createConnectorsModule } from "./modules/connectors.js";
import { getAccessToken } from "./utils/auth-utils.js";
import { createFunctionsModule } from "./modules/functions.js";
import { createAgentsModule } from "./modules/agents.js";
import { createAppLogsModule } from "./modules/app-logs.js";
import { RoomsSocket } from "./utils/socket-utils.js";
/**
* Create a Base44 client instance
* @param {Object} config - Client configuration
* @param {string} [config.serverUrl='https://base44.app'] - API server URL
* @param {string} [config.appBaseUrl] - Application base URL
* @param {string|number} config.appId - Application ID
* @param {string} [config.token] - Authentication token
* @param {string} [config.serviceToken] - Service role authentication token
* @param {boolean} [config.requiresAuth=false] - Whether the app requires authentication
* @returns {Object} Base44 client instance
*/
export function createClient(config) {
const { serverUrl = "https://base44.app", appId, token, serviceToken, requiresAuth = false, appBaseUrl, options, functionsVersion, headers: optionalHeaders, } = config;
const socketConfig = {
serverUrl,
mountPath: "/ws-user-apps/socket.io/",
transports: ["websocket"],
appId,
token,
};
const socket = RoomsSocket({
config: socketConfig,
});
const headers = {
...optionalHeaders,
"X-App-Id": String(appId),
};
const functionHeaders = functionsVersion
? {
...headers,
"Base44-Functions-Version": functionsVersion,
}
: headers;
const axiosClient = createAxiosClient({
baseURL: `${serverUrl}/api`,
headers,
token,
onError: options === null || options === void 0 ? void 0 : options.onError,
});
const functionsAxiosClient = createAxiosClient({
baseURL: `${serverUrl}/api`,
headers: functionHeaders,
token,
interceptResponses: false,
onError: options === null || options === void 0 ? void 0 : options.onError,
});
const serviceRoleAxiosClient = createAxiosClient({
baseURL: `${serverUrl}/api`,
headers,
token: serviceToken,
onError: options === null || options === void 0 ? void 0 : options.onError,
});
const serviceRoleFunctionsAxiosClient = createAxiosClient({
baseURL: `${serverUrl}/api`,
headers: functionHeaders,
token: serviceToken,
interceptResponses: false,
});
const userModules = {
entities: createEntitiesModule(axiosClient, appId),
integrations: createIntegrationsModule(axiosClient, appId),
auth: createAuthModule(axiosClient, functionsAxiosClient, appId, {
appBaseUrl,
serverUrl,
}),
functions: createFunctionsModule(functionsAxiosClient, appId),
agents: createAgentsModule({
axios: axiosClient,
socket,
appId,
serverUrl,
token,
}),
appLogs: createAppLogsModule(axiosClient, appId),
cleanup: () => {
socket.disconnect();
},
};
const serviceRoleModules = {
entities: createEntitiesModule(serviceRoleAxiosClient, appId),
integrations: createIntegrationsModule(serviceRoleAxiosClient, appId),
sso: createSsoModule(serviceRoleAxiosClient, appId, token),
connectors: createConnectorsModule(serviceRoleAxiosClient, appId),
functions: createFunctionsModule(serviceRoleFunctionsAxiosClient, appId),
agents: createAgentsModule({
axios: serviceRoleAxiosClient,
socket,
appId,
serverUrl,
token,
}),
appLogs: createAppLogsModule(serviceRoleAxiosClient, appId),
cleanup: () => {
socket.disconnect();
},
};
// Always try to get token from localStorage or URL parameters
if (typeof window !== "undefined") {
// Get token from URL or localStorage
const accessToken = token || getAccessToken();
if (accessToken) {
userModules.auth.setToken(accessToken);
}
}
// If authentication is required, verify token and redirect to login if needed
if (requiresAuth && typeof window !== "undefined") {
// We perform this check asynchronously to not block client creation
setTimeout(async () => {
try {
const isAuthenticated = await userModules.auth.isAuthenticated();
if (!isAuthenticated) {
userModules.auth.redirectToLogin(window.location.href);
}
}
catch (error) {
console.error("Authentication check failed:", error);
userModules.auth.redirectToLogin(window.location.href);
}
}, 0);
}
// Assemble and return the client
const client = {
...userModules,
/**
* Set authentication token for all requests
* @param {string} newToken - New auth token
*/
setToken(newToken) {
userModules.auth.setToken(newToken);
socket.updateConfig({
token: newToken,
});
},
/**
* Get current configuration
* @returns {Object} Current configuration
*/
getConfig() {
return {
serverUrl,
appId,
requiresAuth,
};
},
/**
* Access service role modules - throws error if no service token was provided
* @throws {Error} When accessed without a service token
*/
get asServiceRole() {
if (!serviceToken) {
throw new Error("Service token is required to use asServiceRole. Please provide a serviceToken when creating the client.");
}
return serviceRoleModules;
},
};
return client;
}
export function createClientFromRequest(request) {
const authHeader = request.headers.get("Authorization");
const serviceRoleAuthHeader = request.headers.get("Base44-Service-Authorization");
const appId = request.headers.get("Base44-App-Id");
const serverUrlHeader = request.headers.get("Base44-Api-Url");
const functionsVersion = request.headers.get("Base44-Functions-Version");
if (!appId) {
throw new Error("Base44-App-Id header is required, but is was not found on the request");
}
// Validate authorization header formats
let serviceRoleToken;
let userToken;
if (serviceRoleAuthHeader !== null) {
if (serviceRoleAuthHeader === "" ||
!serviceRoleAuthHeader.startsWith("Bearer ") ||
serviceRoleAuthHeader.split(" ").length !== 2) {
throw new Error('Invalid authorization header format. Expected "Bearer <token>"');
}
serviceRoleToken = serviceRoleAuthHeader.split(" ")[1];
}
if (authHeader !== null) {
if (authHeader === "" ||
!authHeader.startsWith("Bearer ") ||
authHeader.split(" ").length !== 2) {
throw new Error('Invalid authorization header format. Expected "Bearer <token>"');
}
userToken = authHeader.split(" ")[1];
}
return createClient({
serverUrl: serverUrlHeader || "https://base44.app",
appId,
token: userToken,
serviceToken: serviceRoleToken,
functionsVersion: functionsVersion !== null && functionsVersion !== void 0 ? functionsVersion : undefined,
});
}