Skip to content

Commit 375a874

Browse files
committed
add support to augment the types of the sdk
1 parent 0f59076 commit 375a874

File tree

4 files changed

+119
-22
lines changed

4 files changed

+119
-22
lines changed

src/index.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ export * from "./types.js";
3636
export type {
3737
EntitiesModule,
3838
EntityHandler,
39+
EntityTypeRegistry,
3940
RealtimeEventType,
4041
RealtimeEvent,
4142
RealtimeCallback,
@@ -71,10 +72,14 @@ export type {
7172
CreateFileSignedUrlResult,
7273
} from "./modules/integrations.types.js";
7374

74-
export type { FunctionsModule } from "./modules/functions.types.js";
75+
export type {
76+
FunctionsModule,
77+
FunctionNameRegistry,
78+
} from "./modules/functions.types.js";
7579

7680
export type {
7781
AgentsModule,
82+
AgentNameRegistry,
7883
AgentConversation,
7984
AgentMessage,
8085
AgentMessageReasoning,

src/modules/agents.types.ts

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,37 @@ import { AxiosInstance } from "axios";
22
import { RoomsSocket } from "../utils/socket-utils.js";
33
import { ModelFilterParams } from "../types.js";
44

5+
/**
6+
* Registry of agent names.
7+
*
8+
* This interface is designed to be augmented by generated type declaration files.
9+
* When augmented, it enables autocomplete for agent names in methods like `createConversation`.
10+
*
11+
* @example
12+
* ```typescript
13+
* // In your generated types.d.ts file:
14+
* declare module '@base44/sdk' {
15+
* interface AgentNameRegistry {
16+
* support_agent: true;
17+
* sales_bot: true;
18+
* }
19+
* }
20+
*
21+
* // Then in your code:
22+
* await base44.agents.createConversation({
23+
* agent_name: 'support_agent' // ✅ Autocomplete shows: 'support_agent' | 'sales_bot'
24+
* });
25+
* ```
26+
*/
27+
export interface AgentNameRegistry {}
28+
29+
/**
30+
* Agent name type - uses registry keys if augmented, otherwise falls back to string.
31+
*/
32+
export type AgentName = keyof AgentNameRegistry extends never
33+
? string
34+
: keyof AgentNameRegistry;
35+
536
/**
637
* Reasoning information for an agent message.
738
*
@@ -134,8 +165,8 @@ export interface AgentMessage {
134165
* Parameters for creating a new conversation.
135166
*/
136167
export interface CreateConversationParams {
137-
/** The name of the agent to create a conversation with. */
138-
agent_name: string;
168+
/** The name of the agent to create a conversation with. When AgentNameRegistry is augmented, provides autocomplete. */
169+
agent_name: AgentName;
139170
/** Optional metadata to attach to the conversation. */
140171
metadata?: Record<string, any>;
141172
}
@@ -359,7 +390,7 @@ export interface AgentsModule {
359390
* Generates a URL that users can use to connect with the agent through WhatsApp.
360391
* The URL includes authentication if a token is available.
361392
*
362-
* @param agentName - The name of the agent.
393+
* @param agentName - The name of the agent. When AgentNameRegistry is augmented, provides autocomplete.
363394
* @returns WhatsApp connection URL.
364395
*
365396
* @example
@@ -370,5 +401,5 @@ export interface AgentsModule {
370401
* // User can open this URL to start a WhatsApp conversation
371402
* ```
372403
*/
373-
getWhatsAppConnectURL(agentName: string): string;
404+
getWhatsAppConnectURL(agentName: AgentName): string;
374405
}

src/modules/entities.types.ts

Lines changed: 45 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,31 @@ export type SortField<T> =
8080
| `+${keyof T & string}`
8181
| `-${keyof T & string}`;
8282

83+
/**
84+
* Registry mapping entity names to their TypeScript types.
85+
*
86+
* This interface is designed to be augmented by generated type declaration files.
87+
* When augmented, it enables type-safe entity access throughout your application.
88+
*
89+
* @example
90+
* ```typescript
91+
* // In your generated types.d.ts file:
92+
* declare module '@base44/sdk' {
93+
* interface EntityTypeRegistry {
94+
* Task: { title: string; completed: boolean };
95+
* User: { email: string; name: string };
96+
* }
97+
* }
98+
*
99+
* // Then in your code:
100+
* const task = await base44.entities.Task.create({
101+
* title: 'Buy groceries', // ✅ Type-checked
102+
* completed: false
103+
* });
104+
* ```
105+
*/
106+
export interface EntityTypeRegistry {}
107+
83108
/**
84109
* Entity handler providing CRUD operations for a specific entity type.
85110
*
@@ -382,6 +407,22 @@ export interface EntityHandler<T = any> {
382407
subscribe(callback: RealtimeCallback<T>): () => void;
383408
}
384409

410+
/**
411+
* Typed entities module - maps registry keys to typed handlers.
412+
* Only used when EntityTypeRegistry is augmented.
413+
*/
414+
type TypedEntitiesModule = {
415+
[K in keyof EntityTypeRegistry]: EntityHandler<EntityTypeRegistry[K]>;
416+
};
417+
418+
/**
419+
* Dynamic entities module - allows any entity name with untyped handler.
420+
* Used as fallback and for entities not in the registry.
421+
*/
422+
type DynamicEntitiesModule = {
423+
[entityName: string]: EntityHandler<any>;
424+
};
425+
385426
/**
386427
* Entities module for managing app data.
387428
*
@@ -391,6 +432,9 @@ export interface EntityHandler<T = any> {
391432
* Entities are accessed dynamically using the pattern:
392433
* `base44.entities.EntityName.method()`
393434
*
435+
* When {@link EntityTypeRegistry} is augmented (via generated types.d.ts),
436+
* entity access becomes type-safe with autocomplete and type checking.
437+
*
394438
* This module is available to use with a client in all three authentication modes:
395439
*
396440
* - **Anonymous or User authentication** (`base44.entities`): Access is scoped to the current user's permissions. Anonymous users can only access public entities, while authenticated users can access entities they have permission to view or modify.
@@ -415,18 +459,4 @@ export interface EntityHandler<T = any> {
415459
* const allUsers = await base44.asServiceRole.entities.User.list();
416460
* ```
417461
*/
418-
export interface EntitiesModule {
419-
/**
420-
* Access any entity by name.
421-
*
422-
* Use this to access entities defined in the app.
423-
*
424-
* @example
425-
* ```typescript
426-
* // Access entities dynamically
427-
* base44.entities.MyEntity
428-
* base44.entities.AnotherEntity
429-
* ```
430-
*/
431-
[entityName: string]: EntityHandler<any>;
432-
}
462+
export type EntitiesModule = TypedEntitiesModule & DynamicEntitiesModule;

src/modules/functions.types.ts

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,34 @@
1+
/**
2+
* Registry of function names.
3+
*
4+
* This interface is designed to be augmented by generated type declaration files.
5+
* When augmented, it enables autocomplete for function names in the `invoke` method.
6+
*
7+
* @example
8+
* ```typescript
9+
* // In your generated types.d.ts file:
10+
* declare module '@base44/sdk' {
11+
* interface FunctionNameRegistry {
12+
* calculateTotal: true;
13+
* processImage: true;
14+
* }
15+
* }
16+
*
17+
* // Then in your code:
18+
* await base44.functions.invoke('calculateTotal', { ... });
19+
* // ^^^^^^^^^^^^^^^^
20+
* // ✅ Autocomplete shows: 'calculateTotal' | 'processImage'
21+
* ```
22+
*/
23+
export interface FunctionNameRegistry {}
24+
25+
/**
26+
* Function name type - uses registry keys if augmented, otherwise falls back to string.
27+
*/
28+
export type FunctionName = keyof FunctionNameRegistry extends never
29+
? string
30+
: keyof FunctionNameRegistry;
31+
132
/**
233
* Functions module for invoking custom backend functions.
334
*
@@ -17,7 +48,7 @@ export interface FunctionsModule {
1748
* the result. If any parameter is a `File` object, the request will automatically be
1849
* sent as `multipart/form-data`. Otherwise, it will be sent as JSON.
1950
*
20-
* @param functionName - The name of the function to invoke.
51+
* @param functionName - The name of the function to invoke. When FunctionNameRegistry is augmented, provides autocomplete.
2152
* @param data - An object containing named parameters for the function.
2253
* @returns Promise resolving to the function's response. The `data` property contains the data returned by the function, if there is any.
2354
*
@@ -46,5 +77,5 @@ export interface FunctionsModule {
4677
* };
4778
* ```
4879
*/
49-
invoke(functionName: string, data: Record<string, any>): Promise<any>;
80+
invoke(functionName: FunctionName, data?: Record<string, any>): Promise<any>;
5081
}

0 commit comments

Comments
 (0)