Skip to content

Commit 2fed675

Browse files
authored
Merge branch 'main' into docs/realtime-subscribe
2 parents 2ce2005 + 3c234f1 commit 2fed675

11 files changed

Lines changed: 180 additions & 40 deletions

README.md

Lines changed: 67 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,21 @@
11
# Base44 JavaScript SDK
22

3-
The Base44 SDK provides a JavaScript interface for building apps on the Base44 platform. When Base44 generates your app, the generated code uses the SDK to authenticate users, manage your app's data, interact with AI agents, and more. You can then use the same SDK to modify and extend your app.
3+
The Base44 SDK provides a JavaScript interface for building apps on the Base44 platform.
4+
5+
You can use it in two ways:
6+
7+
- **Inside Base44 apps**: When Base44 generates your app, the SDK is already set up and ready to use.
8+
- **External apps**: Use the SDK to build your own frontend or backend that uses Base44 as a backend service.
9+
10+
## Installation
11+
12+
Install the SDK via npm:
13+
14+
```bash
15+
npm install @base44/sdk
16+
```
17+
18+
> **Note**: In Base44-generated apps, the SDK is already installed for you.
419
520
## Modules
621

@@ -12,11 +27,15 @@ The SDK provides access to Base44's functionality through the following modules:
1227
- **[`connectors`](https://docs.base44.com/sdk-docs/interfaces/connectors)**: Manage OAuth connections and access tokens for third-party services.
1328
- **[`entities`](https://docs.base44.com/sdk-docs/interfaces/entities)**: Work with your app's data entities using CRUD operations.
1429
- **[`functions`](https://docs.base44.com/sdk-docs/interfaces/functions)**: Execute backend functions.
15-
- **[`integrations`](https://docs.base44.com/sdk-docs/type-aliases/integrations)**: Pre-built server-side functions for external services.
30+
- **[`integrations`](https://docs.base44.com/sdk-docs/type-aliases/integrations)**: Pre-built integrations for external services.
1631

17-
## Example
32+
## Quick starts
1833

19-
Here's a quick look at working with data in the SDK, using the `entities` module to create, update, and list records. In this example, we're working with a custom `Task` entity:
34+
How you get started depends on your context:
35+
36+
### Inside a Base44 app
37+
38+
In Base44-generated apps, the client is pre-configured. Just import and use it:
2039

2140
```typescript
2241
import { base44 } from "@/api/base44Client";
@@ -37,6 +56,45 @@ await base44.entities.Task.update(newTask.id, {
3756
const tasks = await base44.entities.Task.list();
3857
```
3958

59+
### External apps
60+
61+
When using Base44 as a backend for your own app, create and configure the client yourself:
62+
63+
```typescript
64+
import { createClient } from '@base44/sdk';
65+
66+
// Create a client for your Base44 app
67+
const base44 = createClient({
68+
appId: 'your-app-id' // Find this in the Base44 editor URL
69+
});
70+
71+
// Read public data (anonymous access)
72+
const products = await base44.entities.Products.list();
73+
74+
// Authenticate a user (token is automatically set)
75+
await base44.auth.loginViaEmailPassword('user@example.com', 'password');
76+
77+
// Now operations use the authenticated user's permissions
78+
const userOrders = await base44.entities.Orders.list();
79+
```
80+
81+
### Service role
82+
83+
For backend code that needs admin-level access, use the service role. Service role is only available in Base44-hosted backend functions:
84+
85+
```typescript
86+
import { createClientFromRequest } from 'npm:@base44/sdk';
87+
88+
Deno.serve(async (req) => {
89+
const base44 = createClientFromRequest(req);
90+
91+
// Access all data with admin-level permissions
92+
const allOrders = await base44.asServiceRole.entities.Orders.list();
93+
94+
return Response.json({ orders: allOrders });
95+
});
96+
```
97+
4098
## Learn more
4199

42100
For complete documentation, guides, and API reference, visit the **[Base44 SDK Documentation](https://docs.base44.com/sdk-getting-started/overview)**.
@@ -45,13 +103,17 @@ For complete documentation, guides, and API reference, visit the **[Base44 SDK D
45103

46104
### Build the SDK
47105

106+
Build the SDK from source:
107+
48108
```bash
49109
npm install
50110
npm run build
51111
```
52112

53113
### Run tests
54114

115+
Run the test suite:
116+
55117
```bash
56118
# Run all tests
57119
npm test
@@ -64,6 +126,7 @@ npm run test:coverage
64126
```
65127

66128
For E2E tests, create a `tests/.env` file with:
129+
67130
```
68131
BASE44_APP_ID=your_app_id
69132
BASE44_AUTH_TOKEN=your_auth_token

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@base44/sdk",
3-
"version": "0.8.17",
3+
"version": "0.8.18",
44
"description": "JavaScript SDK for Base44 API",
55
"main": "dist/index.js",
66
"types": "dist/index.d.ts",

src/client.ts

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,14 @@ export type { Base44Client, CreateClientConfig, CreateClientOptions };
2525
*
2626
* This is the main entry point for the Base44 SDK. It creates a client that provides access to the SDK's modules, such as {@linkcode EntitiesModule | entities}, {@linkcode AuthModule | auth}, and {@linkcode FunctionsModule | functions}.
2727
*
28-
* Typically, you don't need to call this function because Base44 creates the client for you. You can then import and use the client to make API calls. The client takes care of managing authentication for you.
28+
* How you get a client depends on your context:
29+
* - **Inside a Base44 app:** The client is automatically created and configured for you. Import it from `@/api/base44Client`.
30+
* - **External app using Base44 as a backend:** Call `createClient()` directly in your code to create and configure the client.
2931
*
3032
* The client supports three authentication modes:
31-
* - **Anonymous**: Access modules anonymously without authentication using `base44.moduleName`. Operations are scoped to public data and permissions.
32-
* - **User authentication**: Access modules with user-level permissions using `base44.moduleName`. Operations are scoped to the authenticated user's data and permissions.
33-
* - **Service role authentication**: Access modules with elevated permissions using `base44.asServiceRole.moduleName`. Operations can access any data available to the app's admin. Can only be used in the backend. Typically, you create a client with service role authentication using the {@linkcode createClientFromRequest | createClientFromRequest()} function in your backend functions.
33+
* - **Anonymous**: Access modules without authentication using `base44.moduleName`. Operations are scoped to public data and permissions.
34+
* - **User authentication**: Access modules with user-level permissions using `base44.moduleName`. Operations are scoped to the authenticated user's data and permissions. Use `base44.auth.loginViaEmailPassword()` or other auth methods to get a token.
35+
* - **Service role authentication**: Access modules with elevated permissions using `base44.asServiceRole.moduleName`. Operations can access any data available to the app's admin. Only available in Base44-hosted backend functions. Create a client with service role authentication using {@linkcode createClientFromRequest | createClientFromRequest()}.
3436
*
3537
* For example, when using the {@linkcode EntitiesModule | entities} module:
3638
* - **Anonymous**: Can only read public data.
@@ -265,7 +267,7 @@ export function createClient(config: CreateClientConfig): Base44Client {
265267
/**
266268
* Provides access to service role modules.
267269
*
268-
* Service role authentication provides elevated permissions for server-side operations. Unlike user authentication, which is scoped to a specific user's permissions, service role authentication has access to the data and operations available to the app's admin.
270+
* Service role authentication provides elevated permissions for backend operations. Unlike user authentication, which is scoped to a specific user's permissions, service role authentication has access to the data and operations available to the app's admin.
269271
*
270272
* @throws {Error} When accessed without providing a serviceToken during client creation.
271273
*
@@ -296,7 +298,9 @@ export function createClient(config: CreateClientConfig): Base44Client {
296298
/**
297299
* Creates a Base44 client from an HTTP request.
298300
*
299-
* The client is created by automatically extracting authentication tokens from a request to a backend function. Base44 inserts the necessary headers when forwarding requests to backend functions.
301+
* This function is designed for use in Base44-hosted backend functions. For frontends and external backends, use {@linkcode createClient | createClient()} instead.
302+
*
303+
* When used in a Base44-hosted backend function, `createClientFromRequest()` automatically extracts authentication tokens from the request headers that Base44 injects when forwarding requests. The returned client includes service role access using `base44.asServiceRole`, which provides admin-level permissions.
300304
*
301305
* To learn more about the Base44 client, see {@linkcode createClient | createClient()}.
302306
*

src/client.types.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,13 @@ export interface CreateClientConfig {
4141
appId: string;
4242
/**
4343
* User authentication token. Used to authenticate as a specific user.
44+
*
45+
* Inside Base44 apps, the token is managed automatically. For external apps, use auth methods like {@linkcode AuthModule.loginViaEmailPassword | loginViaEmailPassword()} which set the token automatically.
4446
*/
4547
token?: string;
4648
/**
47-
* Service role authentication token. Use this in the backend when you need elevated permissions to access data available to the app's admin or perform admin operations. This token should be kept secret and never exposed in the app's frontend. Typically, you get this token from a request to a backend function using {@linkcode createClientFromRequest | createClientFromRequest()}.
49+
* Service role authentication token. Provides elevated permissions to access data available to the app's admin. Only available in Base44-hosted backend functions. Automatically added to client's created using {@linkcode createClientFromRequest | createClientFromRequest()}.
50+
* @internal
4851
*/
4952
serviceToken?: string;
5053
/**

src/modules/agents.ts

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ export function createAgentsModule({
1717
}: AgentsModuleConfig): AgentsModule {
1818
const baseURL = `/apps/${appId}/agents`;
1919

20+
// Track active conversations
21+
const currentConversations: Record<string, AgentConversation | undefined> = {};
22+
2023
const getConversations = () => {
2124
return axios.get<any, AgentConversation[]>(`${baseURL}/conversations`);
2225
};
@@ -44,14 +47,8 @@ export function createAgentsModule({
4447
conversation: AgentConversation,
4548
message: AgentMessage
4649
) => {
47-
const room = `/agent-conversations/${conversation.id}`;
48-
const socket = getSocket();
49-
await socket.updateModel(room, {
50-
...conversation,
51-
messages: [...(conversation.messages || []), message],
52-
});
5350
return axios.post<any, AgentMessage>(
54-
`${baseURL}/conversations/${conversation.id}/messages`,
51+
`${baseURL}/conversations/v2/${conversation.id}/messages`,
5552
message
5653
);
5754
};
@@ -62,11 +59,41 @@ export function createAgentsModule({
6259
) => {
6360
const room = `/agent-conversations/${conversationId}`;
6461
const socket = getSocket();
62+
63+
// Store the promise for initial conversation state
64+
const conversationPromise = getConversation(conversationId).then((conv) => {
65+
currentConversations[conversationId] = conv;
66+
return conv;
67+
});
68+
6569
return socket.subscribeToRoom(room, {
6670
connect: () => {},
67-
update_model: ({ data: jsonStr }) => {
68-
const conv = JSON.parse(jsonStr) as AgentConversation;
69-
onUpdate?.(conv);
71+
update_model: async ({ data: jsonStr }) => {
72+
const data = JSON.parse(jsonStr);
73+
74+
if (data._message) {
75+
// Wait for initial conversation to be loaded
76+
await conversationPromise;
77+
const message = data._message as AgentMessage;
78+
79+
// Update shared conversation state
80+
const currentConversation = currentConversations[conversationId];
81+
if (currentConversation) {
82+
const messages = currentConversation.messages || [];
83+
const existingIndex = messages.findIndex((m) => m.id === message.id);
84+
85+
const updatedMessages =
86+
existingIndex !== -1
87+
? messages.map((m, i) => (i === existingIndex ? message : m))
88+
: [...messages, message];
89+
90+
currentConversations[conversationId] = {
91+
...currentConversation,
92+
messages: updatedMessages,
93+
};
94+
onUpdate?.(currentConversations[conversationId]!);
95+
}
96+
}
7097
},
7198
});
7299
};

src/modules/auth.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,23 @@ export function createAuthModule(
5757
window.location.href = loginUrl;
5858
},
5959

60+
// Redirects the user to a provider's login page
61+
loginWithProvider(provider: string, fromUrl: string = "/") {
62+
// Build the full redirect URL
63+
const redirectUrl = new URL(fromUrl, window.location.origin).toString();
64+
65+
// Build the provider login URL (google is the default, so no provider path needed)
66+
const providerPath = provider === "google" ? "" : `/${provider}`;
67+
const loginUrl = `${
68+
options.serverUrl
69+
}/api/apps/auth${providerPath}/login?app_id=${appId}&from_url=${encodeURIComponent(
70+
redirectUrl
71+
)}`;
72+
73+
// Redirect to the provider login page
74+
window.location.href = loginUrl;
75+
},
76+
6077
// Logout the current user
6178
// Removes the token from localStorage and optionally redirects to a URL or reloads the page
6279
logout(redirectUrl?: string) {

src/modules/auth.types.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,28 @@ export interface AuthModule {
185185
*/
186186
redirectToLogin(nextUrl: string): void;
187187

188+
/**
189+
* Redirects the user to a third-party authentication provider's login page.
190+
*
191+
* Initiates OAuth/SSO login flow with providers like Google, Microsoft, etc. Requires a browser environment and can't be used in the backend.
192+
*
193+
* @param provider - Name of the supported authentication provider (e.g., 'google', 'microsoft').
194+
* @param fromUrl - URL to redirect to after successful authentication. Defaults to '/'.
195+
*
196+
* @example
197+
* ```typescript
198+
* // Login with Google and return to current page
199+
* base44.auth.loginWithProvider('google', window.location.pathname);
200+
* ```
201+
*
202+
* @example
203+
* ```typescript
204+
* // Login with GitHub and redirect to dashboard
205+
* base44.auth.loginWithProvider('microsoft', '/dashboard');
206+
* ```
207+
*/
208+
loginWithProvider(provider: string, fromUrl?: string): void;
209+
188210
/**
189211
* Logs out the current user.
190212
*

src/modules/custom-integrations.types.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,8 @@ export interface CustomIntegrationCallResponse {
6363
* ```typescript
6464
* // Call a custom GitHub integration
6565
* const response = await base44.integrations.custom.call(
66-
* "github", // integration slug (defined by workspace admin)
67-
* "listIssues", // operation ID from the OpenAPI spec
66+
* "github", // integration slug (defined by workspace admin)
67+
* "get:/repos/{owner}/{repo}/issues", // endpoint in method:path format
6868
* {
6969
* pathParams: { owner: "myorg", repo: "myrepo" },
7070
* queryParams: { state: "open", per_page: 100 }
@@ -83,7 +83,7 @@ export interface CustomIntegrationCallResponse {
8383
* // Call with request body payload
8484
* const response = await base44.integrations.custom.call(
8585
* "github",
86-
* "createIssue",
86+
* "post:/repos/{owner}/{repo}/issues",
8787
* {
8888
* pathParams: { owner: "myorg", repo: "myrepo" },
8989
* payload: {
@@ -101,7 +101,7 @@ export interface CustomIntegrationsModule {
101101
* Call a custom integration endpoint.
102102
*
103103
* @param slug - The integration's unique identifier (slug), as defined by the workspace admin.
104-
* @param operationId - The operation ID from the OpenAPI spec (e.g., "listIssues", "getUser").
104+
* @param operationId - The endpoint identifier in method:path format (e.g., "get:/repos/{owner}/{repo}/issues", "get:/users/{username}").
105105
* @param params - Optional parameters including payload, pathParams, queryParams, and headers.
106106
* @returns Promise resolving to the integration call response.
107107
*

src/modules/integrations.types.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -383,8 +383,8 @@ export type IntegrationsModule = {
383383
* @example
384384
* ```typescript
385385
* const response = await base44.integrations.custom.call(
386-
* "github", // integration slug
387-
* "listIssues", // operation ID
386+
* "github", // integration slug
387+
* "get:/repos/{owner}/{repo}/issues", // endpoint in method:path format
388388
* {
389389
* pathParams: { owner: "myorg", repo: "myrepo" },
390390
* queryParams: { state: "open" }

0 commit comments

Comments
 (0)