UNPKG

@base44/sdk

Version:

JavaScript SDK for Base44 API

205 lines (204 loc) 7.94 kB
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, }); }