@doany-ai/sdk 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +60 -0
  3. package/dist/client.d.ts +96 -0
  4. package/dist/client.js +395 -0
  5. package/dist/client.types.d.ts +149 -0
  6. package/dist/client.types.js +1 -0
  7. package/dist/index.d.ts +17 -0
  8. package/dist/index.js +5 -0
  9. package/dist/modules/agents.d.ts +2 -0
  10. package/dist/modules/agents.js +89 -0
  11. package/dist/modules/agents.types.d.ts +397 -0
  12. package/dist/modules/agents.types.js +1 -0
  13. package/dist/modules/ai-gateway.d.ts +2 -0
  14. package/dist/modules/ai-gateway.js +13 -0
  15. package/dist/modules/ai-gateway.types.d.ts +88 -0
  16. package/dist/modules/ai-gateway.types.js +1 -0
  17. package/dist/modules/analytics.d.ts +20 -0
  18. package/dist/modules/analytics.js +284 -0
  19. package/dist/modules/analytics.types.d.ts +122 -0
  20. package/dist/modules/analytics.types.js +1 -0
  21. package/dist/modules/app-logs.d.ts +11 -0
  22. package/dist/modules/app-logs.js +27 -0
  23. package/dist/modules/app-logs.types.d.ts +46 -0
  24. package/dist/modules/app-logs.types.js +1 -0
  25. package/dist/modules/app.types.d.ts +142 -0
  26. package/dist/modules/app.types.js +1 -0
  27. package/dist/modules/auth.d.ts +13 -0
  28. package/dist/modules/auth.js +240 -0
  29. package/dist/modules/auth.types.d.ts +517 -0
  30. package/dist/modules/auth.types.js +1 -0
  31. package/dist/modules/connectors.d.ts +20 -0
  32. package/dist/modules/connectors.js +98 -0
  33. package/dist/modules/connectors.types.d.ts +376 -0
  34. package/dist/modules/connectors.types.js +1 -0
  35. package/dist/modules/custom-integrations.d.ts +11 -0
  36. package/dist/modules/custom-integrations.js +32 -0
  37. package/dist/modules/custom-integrations.types.d.ts +89 -0
  38. package/dist/modules/custom-integrations.types.js +1 -0
  39. package/dist/modules/entities.d.ts +20 -0
  40. package/dist/modules/entities.js +163 -0
  41. package/dist/modules/entities.types.d.ts +702 -0
  42. package/dist/modules/entities.types.js +1 -0
  43. package/dist/modules/functions.d.ts +12 -0
  44. package/dist/modules/functions.js +79 -0
  45. package/dist/modules/functions.types.d.ts +150 -0
  46. package/dist/modules/functions.types.js +1 -0
  47. package/dist/modules/integrations.d.ts +11 -0
  48. package/dist/modules/integrations.js +77 -0
  49. package/dist/modules/integrations.types.d.ts +418 -0
  50. package/dist/modules/integrations.types.js +1 -0
  51. package/dist/modules/sso.d.ts +11 -0
  52. package/dist/modules/sso.js +22 -0
  53. package/dist/modules/sso.types.d.ts +68 -0
  54. package/dist/modules/sso.types.js +1 -0
  55. package/dist/modules/types.d.ts +5 -0
  56. package/dist/modules/types.js +5 -0
  57. package/dist/modules/users.d.ts +16 -0
  58. package/dist/modules/users.js +23 -0
  59. package/dist/types.d.ts +72 -0
  60. package/dist/types.js +1 -0
  61. package/dist/utils/auth-utils.d.ts +117 -0
  62. package/dist/utils/auth-utils.js +189 -0
  63. package/dist/utils/auth-utils.types.d.ts +146 -0
  64. package/dist/utils/auth-utils.types.js +1 -0
  65. package/dist/utils/axios-client.d.ts +100 -0
  66. package/dist/utils/axios-client.js +202 -0
  67. package/dist/utils/axios-client.types.d.ts +28 -0
  68. package/dist/utils/axios-client.types.js +1 -0
  69. package/dist/utils/common.d.ts +4 -0
  70. package/dist/utils/common.js +11 -0
  71. package/dist/utils/sharedInstance.d.ts +1 -0
  72. package/dist/utils/sharedInstance.js +15 -0
  73. package/dist/utils/socket-utils.d.ts +47 -0
  74. package/dist/utils/socket-utils.js +170 -0
  75. package/package.json +54 -0
@@ -0,0 +1,13 @@
1
+ import { getAccessToken } from "../utils/auth-utils.js";
2
+ export function createAiGatewayModule({ serverUrl, token, appId, }) {
3
+ const connection = () => {
4
+ var _a;
5
+ return ({
6
+ baseURL: `${serverUrl}/api/apps/${appId}/ai/openai/v1`,
7
+ token: (_a = token !== null && token !== void 0 ? token : getAccessToken()) !== null && _a !== void 0 ? _a : "",
8
+ });
9
+ };
10
+ return {
11
+ connection,
12
+ };
13
+ }
@@ -0,0 +1,88 @@
1
+ /**
2
+ * A connection to the Base44 AI Gateway.
3
+ *
4
+ * Contains the base URL and bearer token to use with any OpenAI-compatible
5
+ * client pointed at the Base44 AI Gateway.
6
+ */
7
+ export interface AiGatewayConnection {
8
+ /** Base URL of the gateway's OpenAI-compatible endpoint. */
9
+ baseURL: string;
10
+ /** Bearer token used to authenticate requests to the gateway. */
11
+ token: string;
12
+ }
13
+ /**
14
+ * Configuration for the AI Gateway module.
15
+ * @internal
16
+ */
17
+ export interface AiGatewayModuleConfig {
18
+ /** Server URL */
19
+ serverUrl?: string;
20
+ /** Authentication token */
21
+ token?: string;
22
+ /** Application ID */
23
+ appId: string;
24
+ }
25
+ /**
26
+ * AI Gateway module for calling Base44's managed AI models from your own code.
27
+ *
28
+ * The gateway exposes an OpenAI-compatible Chat Completions endpoint, so any
29
+ * OpenAI-compatible SDK works against it:
30
+ * - Build custom AI agents or call models directly from your backend code
31
+ * - Uses your app's models, billing, and credit quota, no API key to manage
32
+ *
33
+ * Available in user authentication mode (`base44.aiGateway`) and with the
34
+ * service-role token via `base44.asServiceRole.aiGateway`.
35
+ */
36
+ export interface AiGatewayModule {
37
+ /**
38
+ * Gets the connection details for the Base44 AI Gateway.
39
+ *
40
+ * Returns the `baseURL` and `token` to pass to any OpenAI-compatible client.
41
+ *
42
+ * The `token` is the current caller's bearer token: the app user's token for
43
+ * `base44.aiGateway`, or the service-role token for `base44.asServiceRole.aiGateway`.
44
+ * When the caller is unauthenticated, `token` is an empty string.
45
+ *
46
+ * @returns The gateway {@linkcode AiGatewayConnection | connection} (`baseURL` and `token`).
47
+ *
48
+ * @example
49
+ * ```typescript
50
+ * import { ToolLoopAgent, tool, stepCountIs, hasToolCall } from "ai";
51
+ * import { createOpenAICompatible } from "@ai-sdk/openai-compatible";
52
+ * import { z } from "zod";
53
+ *
54
+ * const request = await base44.entities.ReturnRequest.get(returnId);
55
+ * const { baseURL, token } = base44.aiGateway.connection();
56
+ * // Point any OpenAI-compatible client at `baseURL` with `apiKey: token`.
57
+ * const models = createOpenAICompatible({ name: "base44", baseURL, apiKey: token });
58
+ *
59
+ * const agent = new ToolLoopAgent({
60
+ * model: models("automatic"),
61
+ * instructions:
62
+ * "Decide whether this return looks fine or needs the owner's attention. " +
63
+ * "Check the customer's past orders, then submit your verdict.",
64
+ * tools: {
65
+ * searchOrders: tool({
66
+ * description: "This customer's past orders, optionally filtered by status",
67
+ * inputSchema: z.object({ status: z.string().optional() }),
68
+ * execute: ({ status }) => {
69
+ * const query = { customer_email: request.customer_email };
70
+ * if (status) query.status = status;
71
+ * return base44.entities.Order.filter(query, "-created_date", 50);
72
+ * },
73
+ * }),
74
+ * submitVerdict: tool({
75
+ * description: "Record the final verdict",
76
+ * inputSchema: z.object({ decision: z.enum(["approved", "flagged"]), reason: z.string() }),
77
+ * execute: ({ decision, reason }) =>
78
+ * base44.entities.ReturnRequest.update(returnId, { status: decision, review_note: reason }),
79
+ * }),
80
+ * },
81
+ * stopWhen: [stepCountIs(8), hasToolCall("submitVerdict")],
82
+ * });
83
+ *
84
+ * await agent.generate({ prompt: `Review this return request: ${JSON.stringify(request)}` });
85
+ * ```
86
+ */
87
+ connection(): AiGatewayConnection;
88
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,20 @@
1
+ import { AxiosInstance } from "axios";
2
+ import { TrackEventParams, AnalyticsModuleOptions } from "./analytics.types";
3
+ import type { AuthModule } from "./auth.types";
4
+ export declare const USER_HEARTBEAT_EVENT_NAME = "__user_heartbeat_event__";
5
+ export declare const ANALYTICS_INITIALIZATION_EVENT_NAME = "__initialization_event__";
6
+ export declare const ANALYTICS_SESSION_DURATION_EVENT_NAME = "__session_duration_event__";
7
+ export declare const ANALYTICS_CONFIG_ENABLE_URL_PARAM_KEY = "analytics-enable";
8
+ export declare const ANALYTICS_SESSION_ID_LOCAL_STORAGE_KEY = "base44_analytics_session_id";
9
+ export interface AnalyticsModuleArgs {
10
+ axiosClient: AxiosInstance;
11
+ serverUrl: string;
12
+ appId: string;
13
+ userAuthModule: AuthModule;
14
+ }
15
+ export declare const createAnalyticsModule: ({ axiosClient, serverUrl, appId, userAuthModule, }: AnalyticsModuleArgs) => {
16
+ track: (params: TrackEventParams) => void;
17
+ cleanup: () => void;
18
+ };
19
+ export declare function getAnalyticsConfigFromUrlParams(): AnalyticsModuleOptions | undefined;
20
+ export declare function getAnalyticsSessionId(): string;
@@ -0,0 +1,284 @@
1
+ import { getSharedInstance } from "../utils/sharedInstance.js";
2
+ import { generateUuid, isReactNative } from "../utils/common.js";
3
+ export const USER_HEARTBEAT_EVENT_NAME = "__user_heartbeat_event__";
4
+ export const ANALYTICS_INITIALIZATION_EVENT_NAME = "__initialization_event__";
5
+ export const ANALYTICS_SESSION_DURATION_EVENT_NAME = "__session_duration_event__";
6
+ export const ANALYTICS_CONFIG_ENABLE_URL_PARAM_KEY = "analytics-enable";
7
+ export const ANALYTICS_SESSION_ID_LOCAL_STORAGE_KEY = "base44_analytics_session_id";
8
+ const defaultConfiguration = {
9
+ // default to enabled //
10
+ enabled: true,
11
+ maxQueueSize: 1000,
12
+ throttleTime: 1000,
13
+ batchSize: 30,
14
+ heartBeatInterval: 60 * 1000,
15
+ };
16
+ ///////////////////////////////////////////////
17
+ //// shared queue for analytics events ////
18
+ ///////////////////////////////////////////////
19
+ const ANALYTICS_SHARED_STATE_NAME = "analytics";
20
+ // shared state//
21
+ const analyticsSharedState = getSharedInstance(ANALYTICS_SHARED_STATE_NAME, () => ({
22
+ requestsQueue: [],
23
+ isProcessing: false,
24
+ isHeartBeatProcessing: false,
25
+ wasInitializationTracked: false,
26
+ sessionContext: null,
27
+ sessionStartTime: null,
28
+ config: {
29
+ ...defaultConfiguration,
30
+ ...getAnalyticsConfigFromUrlParams(),
31
+ },
32
+ }));
33
+ export const createAnalyticsModule = ({ axiosClient, serverUrl, appId, userAuthModule, }) => {
34
+ var _a;
35
+ // prevent overflow of events //
36
+ const { maxQueueSize, throttleTime, batchSize } = analyticsSharedState.config;
37
+ // Disable analytics on React Native. It defines `window` but not `document`,
38
+ // so the per-callsite `typeof window` guards below aren't enough to keep it
39
+ // from touching `document` (e.g. `document.referrer` on init). Node/SSR is
40
+ // still handled by those `window` guards, so this doesn't affect it.
41
+ if (!((_a = analyticsSharedState.config) === null || _a === void 0 ? void 0 : _a.enabled) || isReactNative) {
42
+ return {
43
+ track: () => { },
44
+ cleanup: () => { },
45
+ };
46
+ }
47
+ let clearHeartBeatProcessor = undefined;
48
+ const trackBatchUrl = `${serverUrl}/api/apps/${appId}/analytics/track/batch`;
49
+ const batchRequestFallback = async (events) => {
50
+ await axiosClient.request({
51
+ method: "POST",
52
+ url: `/apps/${appId}/analytics/track/batch`,
53
+ data: { events },
54
+ });
55
+ };
56
+ // currently disabled, until fully tested //
57
+ const beaconRequest = (events) => {
58
+ try {
59
+ const beaconPayload = JSON.stringify({ events });
60
+ const blob = new Blob([beaconPayload], { type: "application/json" });
61
+ return (typeof navigator === "undefined" ||
62
+ beaconPayload.length > 60000 ||
63
+ !navigator.sendBeacon(trackBatchUrl, blob));
64
+ }
65
+ catch (_a) {
66
+ return false;
67
+ }
68
+ };
69
+ const flush = async (eventsData, options = {}) => {
70
+ if (eventsData.length === 0)
71
+ return;
72
+ const sessionContext_ = await getSessionContext(userAuthModule);
73
+ const events = eventsData.map(transformEventDataToApiRequestData(sessionContext_));
74
+ try {
75
+ if (!options.isBeacon || !beaconRequest(events)) {
76
+ await batchRequestFallback(events);
77
+ }
78
+ }
79
+ catch (_a) {
80
+ // do nothing
81
+ }
82
+ };
83
+ const startProcessing = () => {
84
+ startAnalyticsProcessor(flush, {
85
+ throttleTime,
86
+ batchSize,
87
+ });
88
+ };
89
+ const track = (params) => {
90
+ if (analyticsSharedState.requestsQueue.length >= maxQueueSize) {
91
+ return;
92
+ }
93
+ const intrinsicData = getEventIntrinsicData();
94
+ analyticsSharedState.requestsQueue.push({
95
+ ...params,
96
+ ...intrinsicData,
97
+ });
98
+ startProcessing();
99
+ };
100
+ const onDocVisible = () => {
101
+ startAnalyticsProcessor(flush, {
102
+ throttleTime,
103
+ batchSize,
104
+ });
105
+ clearHeartBeatProcessor = startHeartBeatProcessor(track);
106
+ setSessionDurationTimerStart();
107
+ };
108
+ const onDocHidden = () => {
109
+ stopAnalyticsProcessor();
110
+ clearHeartBeatProcessor === null || clearHeartBeatProcessor === void 0 ? void 0 : clearHeartBeatProcessor();
111
+ trackSessionDurationEvent(track);
112
+ // flush entire queue on visibility change and hope for the best //
113
+ const eventsData = analyticsSharedState.requestsQueue.splice(0);
114
+ flush(eventsData, { isBeacon: true });
115
+ };
116
+ const onVisibilityChange = () => {
117
+ if (typeof window === "undefined")
118
+ return;
119
+ if (document.visibilityState === "hidden") {
120
+ onDocHidden();
121
+ }
122
+ else if (document.visibilityState === "visible") {
123
+ onDocVisible();
124
+ }
125
+ };
126
+ const cleanup = () => {
127
+ stopAnalyticsProcessor();
128
+ clearHeartBeatProcessor === null || clearHeartBeatProcessor === void 0 ? void 0 : clearHeartBeatProcessor();
129
+ if (typeof window !== "undefined") {
130
+ window.removeEventListener("visibilitychange", onVisibilityChange);
131
+ }
132
+ };
133
+ // start the flusing process ///
134
+ startProcessing();
135
+ // start the heart beat processor //
136
+ clearHeartBeatProcessor = startHeartBeatProcessor(track);
137
+ // track the referrer event //
138
+ trackInitializationEvent(track);
139
+ // start the visibility change listener //
140
+ if (typeof window !== "undefined") {
141
+ window.addEventListener("visibilitychange", onVisibilityChange);
142
+ }
143
+ return {
144
+ track,
145
+ cleanup,
146
+ };
147
+ };
148
+ function stopAnalyticsProcessor() {
149
+ analyticsSharedState.isProcessing = false;
150
+ }
151
+ async function startAnalyticsProcessor(handleTrack, options) {
152
+ if (analyticsSharedState.isProcessing) {
153
+ // only one instance of the analytics processor can be running at a time //
154
+ return;
155
+ }
156
+ analyticsSharedState.isProcessing = true;
157
+ const { throttleTime = 1000, batchSize = 30 } = options !== null && options !== void 0 ? options : {};
158
+ while (analyticsSharedState.isProcessing &&
159
+ analyticsSharedState.requestsQueue.length > 0) {
160
+ const requests = analyticsSharedState.requestsQueue.splice(0, batchSize);
161
+ requests.length && (await handleTrack(requests));
162
+ await new Promise((resolve) => setTimeout(resolve, throttleTime));
163
+ }
164
+ analyticsSharedState.isProcessing = false;
165
+ }
166
+ function startHeartBeatProcessor(track) {
167
+ var _a;
168
+ if (analyticsSharedState.isHeartBeatProcessing ||
169
+ ((_a = analyticsSharedState.config.heartBeatInterval) !== null && _a !== void 0 ? _a : 0) < 10) {
170
+ return () => { };
171
+ }
172
+ analyticsSharedState.isHeartBeatProcessing = true;
173
+ const interval = setInterval(() => {
174
+ track({ eventName: USER_HEARTBEAT_EVENT_NAME });
175
+ }, analyticsSharedState.config.heartBeatInterval);
176
+ return () => {
177
+ clearInterval(interval);
178
+ analyticsSharedState.isHeartBeatProcessing = false;
179
+ };
180
+ }
181
+ function trackInitializationEvent(track) {
182
+ if (typeof window === "undefined" ||
183
+ analyticsSharedState.wasInitializationTracked) {
184
+ return;
185
+ }
186
+ analyticsSharedState.wasInitializationTracked = true;
187
+ track({
188
+ eventName: ANALYTICS_INITIALIZATION_EVENT_NAME,
189
+ properties: {
190
+ referrer: document === null || document === void 0 ? void 0 : document.referrer,
191
+ },
192
+ });
193
+ }
194
+ function setSessionDurationTimerStart() {
195
+ if (typeof window === "undefined" ||
196
+ analyticsSharedState.sessionStartTime !== null) {
197
+ return;
198
+ }
199
+ analyticsSharedState.sessionStartTime = new Date().toISOString();
200
+ }
201
+ function trackSessionDurationEvent(track) {
202
+ if (typeof window === "undefined" ||
203
+ analyticsSharedState.sessionStartTime === null)
204
+ return;
205
+ const sessionDuration = new Date().getTime() -
206
+ new Date(analyticsSharedState.sessionStartTime).getTime();
207
+ analyticsSharedState.sessionStartTime = null;
208
+ track({
209
+ eventName: ANALYTICS_SESSION_DURATION_EVENT_NAME,
210
+ properties: { sessionDuration },
211
+ });
212
+ }
213
+ function getEventIntrinsicData() {
214
+ return {
215
+ timestamp: new Date().toISOString(),
216
+ pageUrl: typeof window !== "undefined" ? window.location.pathname : null,
217
+ };
218
+ }
219
+ function transformEventDataToApiRequestData(sessionContext) {
220
+ return (eventData) => ({
221
+ event_name: eventData.eventName,
222
+ properties: eventData.properties,
223
+ timestamp: eventData.timestamp,
224
+ page_url: eventData.pageUrl,
225
+ ...sessionContext,
226
+ });
227
+ }
228
+ let sessionContextPromise = null;
229
+ async function getSessionContext(userAuthModule) {
230
+ if (!analyticsSharedState.sessionContext) {
231
+ if (!sessionContextPromise) {
232
+ const sessionId = getAnalyticsSessionId();
233
+ sessionContextPromise = userAuthModule
234
+ .me()
235
+ .then((user) => ({
236
+ user_id: user.id,
237
+ session_id: sessionId,
238
+ }))
239
+ .catch(() => ({
240
+ user_id: null,
241
+ session_id: sessionId,
242
+ }));
243
+ }
244
+ analyticsSharedState.sessionContext = await sessionContextPromise;
245
+ }
246
+ return analyticsSharedState.sessionContext;
247
+ }
248
+ export function getAnalyticsConfigFromUrlParams() {
249
+ // `window.location` is absent on React Native. This runs at module load (via
250
+ // the shared-state factory), so an unguarded `window.location.search` would
251
+ // throw on import there.
252
+ if (typeof window === "undefined" || !window.location)
253
+ return undefined;
254
+ const urlParams = new URLSearchParams(window.location.search);
255
+ const analyticsEnable = urlParams.get(ANALYTICS_CONFIG_ENABLE_URL_PARAM_KEY);
256
+ // if the url param is not set, return undefined //
257
+ if (analyticsEnable == null || !analyticsEnable.length)
258
+ return undefined;
259
+ // remove the url param from the url //
260
+ const newUrlParams = new URLSearchParams(window.location.search);
261
+ newUrlParams.delete(ANALYTICS_CONFIG_ENABLE_URL_PARAM_KEY);
262
+ const newUrl = window.location.pathname +
263
+ (newUrlParams.toString() ? "?" + newUrlParams.toString() : "");
264
+ window.history.replaceState({}, "", newUrl);
265
+ // return the config object //
266
+ return { enabled: analyticsEnable === "true" };
267
+ }
268
+ export function getAnalyticsSessionId() {
269
+ if (typeof window === "undefined") {
270
+ return generateUuid();
271
+ }
272
+ try {
273
+ const sessionId = localStorage.getItem(ANALYTICS_SESSION_ID_LOCAL_STORAGE_KEY);
274
+ if (!sessionId) {
275
+ const newSessionId = generateUuid();
276
+ localStorage.setItem(ANALYTICS_SESSION_ID_LOCAL_STORAGE_KEY, newSessionId);
277
+ return newSessionId;
278
+ }
279
+ return sessionId;
280
+ }
281
+ catch (_a) {
282
+ return generateUuid();
283
+ }
284
+ }
@@ -0,0 +1,122 @@
1
+ /**
2
+ * Properties for analytics events.
3
+ *
4
+ * Key-value pairs with additional event data. Values can be strings, numbers, booleans, or null.
5
+ */
6
+ export type TrackEventProperties = {
7
+ [key: string]: string | number | boolean | null | undefined;
8
+ };
9
+ /**
10
+ * Parameters for tracking an analytics event.
11
+ */
12
+ export type TrackEventParams = {
13
+ /**
14
+ * Name of the event to track.
15
+ *
16
+ * Use descriptive names like `button_click`, `form_submit`, or `purchase_completed`.
17
+ */
18
+ eventName: string;
19
+ /**
20
+ * Optional key-value pairs with additional event data.
21
+ *
22
+ * Values can be strings, numbers, booleans, or null.
23
+ *
24
+ * @example
25
+ * ```typescript
26
+ * base44.analytics.track({
27
+ * eventName: 'add_to_cart',
28
+ * properties: {
29
+ * product_id: 'prod_123',
30
+ * price: 29.99,
31
+ * quantity: 2
32
+ * }
33
+ * });
34
+ * ```
35
+ */
36
+ properties?: TrackEventProperties;
37
+ };
38
+ export type TrackEventIntrinsicData = {
39
+ timestamp: string;
40
+ pageUrl?: string | null;
41
+ };
42
+ export type TrackEventData = {
43
+ properties?: TrackEventProperties;
44
+ eventName: string;
45
+ } & TrackEventIntrinsicData;
46
+ export type SessionContext = {
47
+ user_id?: string | null;
48
+ session_id?: string | null;
49
+ };
50
+ export type AnalyticsApiRequestData = {
51
+ event_name: string;
52
+ properties?: TrackEventProperties;
53
+ timestamp?: string;
54
+ page_url?: string | null;
55
+ } & SessionContext;
56
+ export type AnalyticsApiBatchRequest = {
57
+ method: "POST";
58
+ url: `/apps/${string}/analytics/track/batch`;
59
+ data: {
60
+ events: AnalyticsApiRequestData[];
61
+ };
62
+ };
63
+ export type AnalyticsModuleOptions = {
64
+ enabled?: boolean;
65
+ maxQueueSize?: number;
66
+ throttleTime?: number;
67
+ batchSize?: number;
68
+ heartBeatInterval?: number;
69
+ };
70
+ /**
71
+ * Analytics module for tracking custom events in your app.
72
+ *
73
+ * Use this module to track specific user actions. Track things like button clicks, form submissions, purchases, and feature usage.
74
+ *
75
+ * <Note> Analytics events tracked with this module appear as custom event cards in the [Analytics dashboard](/documentation/performance-and-seo/app-analytics).</Note>
76
+ *
77
+ * ## Best Practices
78
+ *
79
+ * When tracking events:
80
+ *
81
+ * - Choose clear, descriptive event names in snake_case like `signup_button_click` or `purchase_completed` rather than generic names like `click`.
82
+ * - Include relevant context in your properties such as identifiers like `product_id`, measurements like `price`, and flags like `is_first_purchase`.
83
+ *
84
+ * ## Authentication Modes
85
+ *
86
+ * This module is only available in user authentication mode (`base44.analytics`).
87
+ */
88
+ export interface AnalyticsModule {
89
+ /**
90
+ * Tracks a custom event that appears as a card in your Analytics dashboard.
91
+ *
92
+ * Each unique event name becomes its own card showing total count and trends over time. This method returns immediately and events are sent in batches in the background.
93
+ *
94
+ * @param params - Event parameters.
95
+ * @param params.eventName - Name of the event. This becomes the card title in your dashboard. Use descriptive names like `'signup_button_click'` or `'purchase_completed'`.
96
+ * @param params.properties - Optional data to attach to the event. You can filter and analyze events by these properties in the dashboard.
97
+ *
98
+ * @example Track a button click
99
+ * ```typescript
100
+ * // Track a button click
101
+ * base44.analytics.track({
102
+ * eventName: 'signup_button_click'
103
+ * });
104
+ * ```
105
+ *
106
+ * @example Track with properties
107
+ * ```typescript
108
+ * // Track with properties
109
+ * base44.analytics.track({
110
+ * eventName: 'add_to_cart',
111
+ * properties: {
112
+ * product_id: 'prod_123',
113
+ * product_name: 'Premium Widget',
114
+ * price: 29.99,
115
+ * quantity: 2,
116
+ * is_first_purchase: true
117
+ * }
118
+ * });
119
+ * ```
120
+ */
121
+ track(params: TrackEventParams): void;
122
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,11 @@
1
+ import { AxiosInstance } from "axios";
2
+ import { AppLogsModule } from "./app-logs.types";
3
+ /**
4
+ * Creates the app logs module for the Base44 SDK.
5
+ *
6
+ * @param axios - Axios instance
7
+ * @param appId - Application ID
8
+ * @returns App logs module with methods for tracking and analyzing app usage
9
+ * @internal
10
+ */
11
+ export declare function createAppLogsModule(axios: AxiosInstance, appId: string): AppLogsModule;
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Creates the app logs module for the Base44 SDK.
3
+ *
4
+ * @param axios - Axios instance
5
+ * @param appId - Application ID
6
+ * @returns App logs module with methods for tracking and analyzing app usage
7
+ * @internal
8
+ */
9
+ export function createAppLogsModule(axios, appId) {
10
+ const baseURL = `/app-logs/${appId}`;
11
+ return {
12
+ // Log user activity in the app
13
+ async logUserInApp(pageName) {
14
+ await axios.post(`${baseURL}/log-user-in-app/${pageName}`);
15
+ },
16
+ // Fetch app logs with optional parameters
17
+ async fetchLogs(params = {}) {
18
+ const response = await axios.get(baseURL, { params });
19
+ return response;
20
+ },
21
+ // Get app statistics
22
+ async getStats(params = {}) {
23
+ const response = await axios.get(`${baseURL}/stats`, { params });
24
+ return response;
25
+ },
26
+ };
27
+ }
@@ -0,0 +1,46 @@
1
+ /**
2
+ * App Logs module for tracking and analyzing app usage.
3
+ *
4
+ * This module provides a method to log user activity. The logs are reflected in the Analytics page in the app dashboard.
5
+ *
6
+ * ## Authentication Modes
7
+ *
8
+ * This module is available to use with a client in all authentication modes.
9
+ */
10
+ export interface AppLogsModule {
11
+ /**
12
+ * Log user activity in the app.
13
+ *
14
+ * Records when a user visits a specific page or section of the app. Useful for tracking user navigation patterns and popular features. The logs are reflected in the Analytics page in the app dashboard.
15
+ *
16
+ * The specified page name doesn't have to be the name of an actual page in the app, it can be any string you want to use to track the activity.
17
+ *
18
+ * @param pageName - Name of the page or section being visited.
19
+ * @returns Promise that resolves when the log is recorded.
20
+ *
21
+ * @example
22
+ * ```typescript
23
+ * // Log page visit or feature usage
24
+ * await base44.appLogs.logUserInApp('home');
25
+ * await base44.appLogs.logUserInApp('features-section');
26
+ * await base44.appLogs.logUserInApp('button-click');
27
+ * ```
28
+ */
29
+ logUserInApp(pageName: string): Promise<void>;
30
+ /**
31
+ * Fetch app logs with optional parameters.
32
+ *
33
+ * @param params - Optional query parameters for filtering logs.
34
+ * @returns Promise resolving to the logs data.
35
+ * @internal
36
+ */
37
+ fetchLogs(params?: Record<string, any>): Promise<any>;
38
+ /**
39
+ * Get app statistics.
40
+ *
41
+ * @param params - Optional query parameters for filtering stats.
42
+ * @returns Promise resolving to the stats data.
43
+ * @internal
44
+ */
45
+ getStats(params?: Record<string, any>): Promise<any>;
46
+ }
@@ -0,0 +1 @@
1
+ export {};