@depup/base44__sdk 0.8.25-depup.0 → 0.8.40-depup.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.
package/README.md CHANGED
@@ -13,17 +13,16 @@ npm install @depup/base44__sdk
13
13
 
14
14
  | Field | Value |
15
15
  |-------|-------|
16
- | Original | [@base44/sdk](https://www.npmjs.com/package/@base44/sdk) @ 0.8.25 |
17
- | Processed | 2026-04-12 |
16
+ | Original | [@base44/sdk](https://www.npmjs.com/package/@base44/sdk) @ 0.8.40 |
17
+ | Processed | 2026-07-21 |
18
18
  | Smoke test | passed |
19
- | Deps updated | 2 |
19
+ | Deps updated | 1 |
20
20
 
21
21
  ## Dependency Changes
22
22
 
23
23
  | Dependency | From | To |
24
24
  |------------|------|-----|
25
- | axios | ^1.6.2 | ^1.15.0 |
26
- | socket.io-client | ^4.7.5 | ^4.8.3 |
25
+ | uuid | ^13.0.2 | ^14.0.1 |
27
26
 
28
27
  ---
29
28
 
package/changes.json CHANGED
@@ -1,14 +1,10 @@
1
1
  {
2
2
  "bumped": {
3
- "axios": {
4
- "from": "^1.6.2",
5
- "to": "^1.15.0"
6
- },
7
- "socket.io-client": {
8
- "from": "^4.7.5",
9
- "to": "^4.8.3"
3
+ "uuid": {
4
+ "from": "^13.0.2",
5
+ "to": "^14.0.1"
10
6
  }
11
7
  },
12
- "timestamp": "2026-04-12T12:17:46.370Z",
13
- "totalUpdated": 2
8
+ "timestamp": "2026-07-21T16:02:37.704Z",
9
+ "totalUpdated": 1
14
10
  }
package/dist/client.d.ts CHANGED
@@ -12,12 +12,12 @@ export type { Base44Client, CreateClientConfig, CreateClientOptions };
12
12
  * The client supports three authentication modes:
13
13
  * - **Anonymous**: Access modules without authentication using `base44.moduleName`. Operations are scoped to public data and permissions.
14
14
  * - **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.
15
- * - **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()}.
15
+ * - **Service role authentication**: Access modules with elevated permissions using `base44.asServiceRole.moduleName`. Operations bypass entity access rules and field-level security, giving full read and write access to all of the app's data. Only available in Base44-hosted backend functions. Create a client with service role authentication using {@linkcode createClientFromRequest | createClientFromRequest()}.
16
16
  *
17
17
  * For example, when using the {@linkcode EntitiesModule | entities} module:
18
18
  * - **Anonymous**: Can only read public data.
19
19
  * - **User authentication**: Can access the current user's data.
20
- * - **Service role authentication**: Can access all data that admins can access.
20
+ * - **Service role authentication**: Can read and write any record, bypassing access rules.
21
21
  *
22
22
  * Most modules are available in all three modes, but with different permission levels. However, some modules are only available in specific authentication modes.
23
23
  *
@@ -43,7 +43,7 @@ export declare function createClient(config: CreateClientConfig): Base44Client;
43
43
  *
44
44
  * This function is designed for use in Base44-hosted backend functions. For frontends and external backends, use {@linkcode createClient | createClient()} instead.
45
45
  *
46
- * 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.
46
+ * 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 bypasses entity access rules and field-level security.
47
47
  *
48
48
  * To learn more about the Base44 client, see {@linkcode createClient | createClient()}.
49
49
  *
@@ -82,7 +82,7 @@ export declare function createClient(config: CreateClientConfig): Base44Client;
82
82
  * try {
83
83
  * const base44 = createClientFromRequest(req);
84
84
  *
85
- * // Access admin data with service role permissions
85
+ * // Read across all users, bypassing the Orders entity's access rules
86
86
  * const recentOrders = await base44.asServiceRole.entities.Orders.list('-created_at', 50);
87
87
  *
88
88
  * return Response.json({ orders: recentOrders });
package/dist/client.js CHANGED
@@ -7,6 +7,7 @@ import { createConnectorsModule, createUserConnectorsModule, } from "./modules/c
7
7
  import { getAccessToken } from "./utils/auth-utils.js";
8
8
  import { createFunctionsModule } from "./modules/functions.js";
9
9
  import { createAgentsModule } from "./modules/agents.js";
10
+ import { createAiGatewayModule } from "./modules/ai-gateway.js";
10
11
  import { createAppLogsModule } from "./modules/app-logs.js";
11
12
  import { createUsersModule } from "./modules/users.js";
12
13
  import { RoomsSocket } from "./utils/socket-utils.js";
@@ -23,12 +24,12 @@ import { createAnalyticsModule } from "./modules/analytics.js";
23
24
  * The client supports three authentication modes:
24
25
  * - **Anonymous**: Access modules without authentication using `base44.moduleName`. Operations are scoped to public data and permissions.
25
26
  * - **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.
26
- * - **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()}.
27
+ * - **Service role authentication**: Access modules with elevated permissions using `base44.asServiceRole.moduleName`. Operations bypass entity access rules and field-level security, giving full read and write access to all of the app's data. Only available in Base44-hosted backend functions. Create a client with service role authentication using {@linkcode createClientFromRequest | createClientFromRequest()}.
27
28
  *
28
29
  * For example, when using the {@linkcode EntitiesModule | entities} module:
29
30
  * - **Anonymous**: Can only read public data.
30
31
  * - **User authentication**: Can access the current user's data.
31
- * - **Service role authentication**: Can access all data that admins can access.
32
+ * - **Service role authentication**: Can read and write any record, bypassing access rules.
32
33
  *
33
34
  * Most modules are available in all three modes, but with different permission levels. However, some modules are only available in specific authentication modes.
34
35
  *
@@ -112,6 +113,16 @@ export function createClient(config) {
112
113
  appBaseUrl: normalizedAppBaseUrl,
113
114
  serverUrl,
114
115
  });
116
+ // Apply the access token before any module that may issue authenticated
117
+ // requests during construction (notably analytics, which fires an init
118
+ // event whose flush calls auth.me()). Without this, the first User/me
119
+ // request is built before setToken runs and goes out unauthenticated.
120
+ if (typeof window !== "undefined") {
121
+ const accessToken = token || getAccessToken();
122
+ if (accessToken) {
123
+ userAuthModule.setToken(accessToken);
124
+ }
125
+ }
115
126
  const userModules = {
116
127
  entities: createEntitiesModule({
117
128
  axios: axiosClient,
@@ -140,6 +151,7 @@ export function createClient(config) {
140
151
  serverUrl,
141
152
  token,
142
153
  }),
154
+ aiGateway: createAiGatewayModule({ serverUrl, token, appId }),
143
155
  appLogs: createAppLogsModule(axiosClient, appId),
144
156
  users: createUsersModule(axiosClient, appId),
145
157
  analytics: createAnalyticsModule({
@@ -182,6 +194,7 @@ export function createClient(config) {
182
194
  serverUrl,
183
195
  token,
184
196
  }),
197
+ aiGateway: createAiGatewayModule({ serverUrl, token: serviceToken, appId }),
185
198
  appLogs: createAppLogsModule(serviceRoleAxiosClient, appId),
186
199
  cleanup: () => {
187
200
  if (socket) {
@@ -189,14 +202,6 @@ export function createClient(config) {
189
202
  }
190
203
  },
191
204
  };
192
- // Always try to get token from localStorage or URL parameters
193
- if (typeof window !== "undefined") {
194
- // Get token from URL or localStorage
195
- const accessToken = token || getAccessToken();
196
- if (accessToken) {
197
- userModules.auth.setToken(accessToken);
198
- }
199
- }
200
205
  // If authentication is required, verify token and redirect to login if needed
201
206
  if (requiresAuth && typeof window !== "undefined") {
202
207
  // We perform this check asynchronously to not block client creation
@@ -255,7 +260,7 @@ export function createClient(config) {
255
260
  /**
256
261
  * Provides access to service role modules.
257
262
  *
258
- * 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.
263
+ * Service role authentication provides elevated permissions for backend operations. Unlike user authentication, which is scoped to a specific user's permissions, service role authentication bypasses entity access rules and field-level security entirely, giving full read and write access to all of the app's data.
259
264
  *
260
265
  * @throws {Error} When accessed without providing a serviceToken during client creation.
261
266
  *
@@ -266,7 +271,7 @@ export function createClient(config) {
266
271
  * serviceToken: 'service-role-token'
267
272
  * });
268
273
  *
269
- * // Also access a module with elevated permissions
274
+ * // Read every user record, bypassing the User entity's access rules
270
275
  * const allUsers = await base44.asServiceRole.entities.User.list();
271
276
  * ```
272
277
  */
@@ -284,7 +289,7 @@ export function createClient(config) {
284
289
  *
285
290
  * This function is designed for use in Base44-hosted backend functions. For frontends and external backends, use {@linkcode createClient | createClient()} instead.
286
291
  *
287
- * 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.
292
+ * 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 bypasses entity access rules and field-level security.
288
293
  *
289
294
  * To learn more about the Base44 client, see {@linkcode createClient | createClient()}.
290
295
  *
@@ -323,7 +328,7 @@ export function createClient(config) {
323
328
  * try {
324
329
  * const base44 = createClientFromRequest(req);
325
330
  *
326
- * // Access admin data with service role permissions
331
+ * // Read across all users, bypassing the Orders entity's access rules
327
332
  * const recentOrders = await base44.asServiceRole.entities.Orders.list('-created_at', 50);
328
333
  *
329
334
  * return Response.json({ orders: recentOrders });
@@ -341,6 +346,7 @@ export function createClientFromRequest(request) {
341
346
  const serverUrlHeader = request.headers.get("Base44-Api-Url");
342
347
  const functionsVersion = request.headers.get("Base44-Functions-Version");
343
348
  const stateHeader = request.headers.get("Base44-State");
349
+ const dataEnvHeader = request.headers.get("X-Data-Env");
344
350
  if (!appId) {
345
351
  throw new Error("Base44-App-Id header is required, but is was not found on the request");
346
352
  }
@@ -368,6 +374,16 @@ export function createClientFromRequest(request) {
368
374
  if (stateHeader) {
369
375
  additionalHeaders["Base44-State"] = stateHeader;
370
376
  }
377
+ // Propagate the data environment so entity operations from the function stay
378
+ // in the same environment (e.g. test data) as the triggering request. This
379
+ // matters for the user-scoped client: unlike the service token, the user JWT
380
+ // carries no data-env, so without forwarding this header the callbacks fall
381
+ // back to production data even when the app runs in test-data mode.
382
+ // Forward only the known closed set (matches the backend contract) rather
383
+ // than relaying an arbitrary attacker-supplied header value onward.
384
+ if (dataEnvHeader === "dev" || dataEnvHeader === "prod") {
385
+ additionalHeaders["X-Data-Env"] = dataEnvHeader;
386
+ }
371
387
  return createClient({
372
388
  serverUrl: serverUrlHeader || "https://base44.app",
373
389
  appId,
@@ -5,6 +5,7 @@ import type { SsoModule } from "./modules/sso.types.js";
5
5
  import type { ConnectorsModule, UserConnectorsModule } from "./modules/connectors.types.js";
6
6
  import type { FunctionsModule } from "./modules/functions.types.js";
7
7
  import type { AgentsModule } from "./modules/agents.types.js";
8
+ import type { AiGatewayModule } from "./modules/ai-gateway.types.js";
8
9
  import type { AppLogsModule } from "./modules/app-logs.types.js";
9
10
  import type { AnalyticsModule } from "./modules/analytics.types.js";
10
11
  /**
@@ -49,7 +50,7 @@ export interface CreateClientConfig {
49
50
  */
50
51
  token?: string;
51
52
  /**
52
- * 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()}.
53
+ * Service role authentication token. Provides elevated permissions that bypass entity access rules and field-level security. Only available in Base44-hosted backend functions. Automatically added to clients created using {@linkcode createClientFromRequest | createClientFromRequest()}.
53
54
  * @internal
54
55
  */
55
56
  serviceToken?: string;
@@ -81,6 +82,8 @@ export interface CreateClientConfig {
81
82
  export interface Base44Client {
82
83
  /** {@link AgentsModule | Agents module} for managing AI agent conversations. */
83
84
  agents: AgentsModule;
85
+ /** {@link AiGatewayModule | AI Gateway module} for connecting to the Base44 AI Gateway with your own SDK. */
86
+ aiGateway: AiGatewayModule;
84
87
  /** {@link AnalyticsModule | Analytics module} for tracking custom events in your app. */
85
88
  analytics: AnalyticsModule;
86
89
  /** {@link AppLogsModule | App logs module} for tracking app usage. */
@@ -117,13 +120,15 @@ export interface Base44Client {
117
120
  /**
118
121
  * Provides access to supported modules with elevated permissions.
119
122
  *
120
- * 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.
123
+ * Service role authentication provides elevated permissions for backend operations. Unlike user authentication, which is scoped to a specific user's permissions, service role authentication bypasses entity access rules and field-level security entirely, giving full read and write access to all of the app's data.
121
124
  *
122
125
  * @throws {Error} When accessed without providing a serviceToken during client creation
123
126
  */
124
127
  readonly asServiceRole: {
125
128
  /** {@link AgentsModule | Agents module} with elevated permissions. */
126
129
  agents: AgentsModule;
130
+ /** {@link AiGatewayModule | AI Gateway module} with the service-role token. */
131
+ aiGateway: AiGatewayModule;
127
132
  /** {@link AppLogsModule | App logs module} with elevated permissions. */
128
133
  appLogs: AppLogsModule;
129
134
  /** {@link ConnectorsModule | Connectors module} for OAuth token retrieval. */
package/dist/index.d.ts CHANGED
@@ -4,11 +4,12 @@ import { getAccessToken, saveAccessToken, removeAccessToken, getLoginUrl } from
4
4
  export { createClient, createClientFromRequest, Base44Error, getAccessToken, saveAccessToken, removeAccessToken, getLoginUrl, };
5
5
  export type { Base44Client, CreateClientConfig, CreateClientOptions, Base44ErrorJSON, };
6
6
  export * from "./types.js";
7
- export type { DeleteManyResult, DeleteResult, EntitiesModule, EntityHandler, EntityRecord, EntityTypeRegistry, ImportResult, RealtimeEventType, RealtimeEvent, RealtimeCallback, SortField, UpdateManyResult, } from "./modules/entities.types.js";
7
+ export type { DeleteManyResult, DeleteResult, EntitiesModule, EntityFilterOperators, EntityFilterQuery, EntityFilterValue, EntityHandler, EntityRecord, EntityTypeRegistry, ImportResult, RealtimeEventType, RealtimeEvent, RealtimeCallback, SortField, UpdateManyResult, } from "./modules/entities.types.js";
8
8
  export type { AuthModule, LoginResponse, RegisterParams, VerifyOtpParams, ChangePasswordParams, ResetPasswordParams, User, } from "./modules/auth.types.js";
9
9
  export type { IntegrationsModule, IntegrationEndpointFunction, CoreIntegrations, InvokeLLMParams, GenerateImageParams, GenerateImageResult, UploadFileParams, UploadFileResult, SendEmailParams, SendEmailResult, ExtractDataFromUploadedFileParams, ExtractDataFromUploadedFileResult, UploadPrivateFileParams, UploadPrivateFileResult, CreateFileSignedUrlParams, CreateFileSignedUrlResult, } from "./modules/integrations.types.js";
10
10
  export type { FunctionsModule, FunctionName, FunctionNameRegistry, } from "./modules/functions.types.js";
11
11
  export type { AgentsModule, AgentName, AgentNameRegistry, AgentConversation, AgentMessage, AgentMessageReasoning, AgentMessageToolCall, AgentMessageUsage, AgentMessageCustomContext, AgentMessageMetadata, CreateConversationParams, } from "./modules/agents.types.js";
12
+ export type { AiGatewayModule, AiGatewayConnection, } from "./modules/ai-gateway.types.js";
12
13
  export type { AppLogsModule } from "./modules/app-logs.types.js";
13
14
  export type { SsoModule, SsoAccessTokenResponse } from "./modules/sso.types.js";
14
15
  export type { ConnectorsModule, UserConnectorsModule, } from "./modules/connectors.types.js";
@@ -43,7 +43,7 @@ export interface AgentMessageToolCall {
43
43
  /** Arguments passed to the tool as JSON string. */
44
44
  arguments_string: string;
45
45
  /** Status of the tool call. */
46
- status: "running" | "success" | "error" | "stopped";
46
+ status: "running" | "success" | "error" | "stopped" | "waiting_for_user_input";
47
47
  /** Results from the tool call. */
48
48
  results?: string;
49
49
  }
@@ -194,7 +194,7 @@ export interface AgentsModuleConfig {
194
194
  * This module is available to use with a client in all authentication modes:
195
195
  *
196
196
  * - **Anonymous or User authentication** (`base44.agents`): Access is scoped to the current user's permissions. Users must be authenticated to create and access conversations.
197
- * - **Service role authentication** (`base44.asServiceRole.agents`): Operations have elevated admin-level permissions. Can access all conversations that the app's admin role has access to.
197
+ * - **Service role authentication** (`base44.asServiceRole.agents`): Operations are invoked with the service role for backend code that needs elevated permissions.
198
198
  *
199
199
  * ## Generated Types
200
200
  *
@@ -0,0 +1,2 @@
1
+ import { AiGatewayModule, AiGatewayModuleConfig } from "./ai-gateway.types.js";
2
+ export declare function createAiGatewayModule({ serverUrl, token, appId, }: AiGatewayModuleConfig): AiGatewayModule;
@@ -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 {};
@@ -1,5 +1,5 @@
1
1
  import { getSharedInstance } from "../utils/sharedInstance.js";
2
- import { generateUuid } from "../utils/common.js";
2
+ import { generateUuid, isReactNative } from "../utils/common.js";
3
3
  export const USER_HEARTBEAT_EVENT_NAME = "__user_heartbeat_event__";
4
4
  export const ANALYTICS_INITIALIZATION_EVENT_NAME = "__initialization_event__";
5
5
  export const ANALYTICS_SESSION_DURATION_EVENT_NAME = "__session_duration_event__";
@@ -34,7 +34,11 @@ export const createAnalyticsModule = ({ axiosClient, serverUrl, appId, userAuthM
34
34
  var _a;
35
35
  // prevent overflow of events //
36
36
  const { maxQueueSize, throttleTime, batchSize } = analyticsSharedState.config;
37
- if (!((_a = analyticsSharedState.config) === null || _a === void 0 ? void 0 : _a.enabled)) {
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) {
38
42
  return {
39
43
  track: () => { },
40
44
  cleanup: () => { },
@@ -242,7 +246,10 @@ async function getSessionContext(userAuthModule) {
242
246
  return analyticsSharedState.sessionContext;
243
247
  }
244
248
  export function getAnalyticsConfigFromUrlParams() {
245
- if (typeof window === "undefined")
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)
246
253
  return undefined;
247
254
  const urlParams = new URLSearchParams(window.location.search);
248
255
  const analyticsEnable = urlParams.get(ANALYTICS_CONFIG_ENABLE_URL_PARAM_KEY);
@@ -1,3 +1,57 @@
1
+ function isInsideIframe() {
2
+ if (typeof window === "undefined")
3
+ return false;
4
+ return window !== window.parent;
5
+ }
6
+ /**
7
+ * Opens a URL in a centered popup and waits for the backend to postMessage
8
+ * the auth result back. On success, redirects the current window to
9
+ * redirectUrl with the token params appended, preserving the same behaviour
10
+ * as a normal full-page redirect flow.
11
+ *
12
+ * @param url - The login URL to open in the popup (should include popup_origin).
13
+ * @param redirectUrl - Where to redirect after auth (the original fromUrl).
14
+ * @param expectedOrigin - The origin we expect the postMessage to come from.
15
+ */
16
+ function loginViaPopup(url, redirectUrl, expectedOrigin) {
17
+ const width = 500;
18
+ const height = 600;
19
+ const left = Math.round(window.screenX + (window.outerWidth - width) / 2);
20
+ const top = Math.round(window.screenY + (window.outerHeight - height) / 2);
21
+ const popup = window.open(url, "base44_auth", `width=${width},height=${height},left=${left},top=${top},resizable=yes,scrollbars=yes`);
22
+ if (!popup) {
23
+ return;
24
+ }
25
+ const cleanup = () => {
26
+ window.removeEventListener("message", onMessage);
27
+ clearInterval(pollTimer);
28
+ if (!popup.closed)
29
+ popup.close();
30
+ };
31
+ const onMessage = (event) => {
32
+ var _a;
33
+ if (event.origin !== expectedOrigin)
34
+ return;
35
+ if (event.source !== popup)
36
+ return;
37
+ if (!((_a = event.data) === null || _a === void 0 ? void 0 : _a.access_token))
38
+ return;
39
+ cleanup();
40
+ const callbackUrl = new URL(redirectUrl);
41
+ const { access_token, is_new_user } = event.data;
42
+ callbackUrl.searchParams.set("access_token", access_token);
43
+ if (is_new_user != null) {
44
+ callbackUrl.searchParams.set("is_new_user", String(is_new_user));
45
+ }
46
+ window.location.href = callbackUrl.toString();
47
+ };
48
+ // Only used to detect the user closing the popup before auth completes
49
+ const pollTimer = setInterval(() => {
50
+ if (popup.closed)
51
+ cleanup();
52
+ }, 500);
53
+ window.addEventListener("message", onMessage);
54
+ }
1
55
  /**
2
56
  * Creates the auth module for the Base44 SDK.
3
57
  *
@@ -49,7 +103,13 @@ export function createAuthModule(axios, functionsAxiosClient, appId, options) {
49
103
  authPath = `/apps/auth${providerPath}/login`;
50
104
  }
51
105
  const loginUrl = `${options.appBaseUrl}/api${authPath}?${queryParams}`;
52
- // Redirect to the provider login page
106
+ // When running inside an iframe, use a popup to avoid OAuth providers
107
+ // blocking iframe navigation.
108
+ if (isInsideIframe()) {
109
+ const popupLoginUrl = `${loginUrl}&popup_origin=${encodeURIComponent(window.location.origin)}`;
110
+ return loginViaPopup(popupLoginUrl, redirectUrl, window.location.origin);
111
+ }
112
+ // Default: full-page redirect
53
113
  window.location.href = loginUrl;
54
114
  },
55
115
  // Logout the current user