@depup/base44__sdk 0.8.44-depup.0 → 0.8.45-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,8 +13,8 @@ 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.44 |
17
- | Processed | 2026-08-26 |
16
+ | Original | [@base44/sdk](https://www.npmjs.com/package/@base44/sdk) @ 0.8.45 |
17
+ | Processed | 2026-09-02 |
18
18
  | Smoke test | passed |
19
19
  | Deps updated | 3 |
20
20
 
package/changes.json CHANGED
@@ -13,6 +13,6 @@
13
13
  "to": "^14.0.2"
14
14
  }
15
15
  },
16
- "timestamp": "2026-08-26T16:29:09.789Z",
16
+ "timestamp": "2026-09-02T08:12:09.333Z",
17
17
  "totalUpdated": 3
18
18
  }
package/dist/client.js CHANGED
@@ -9,10 +9,11 @@ import { createFunctionsModule } from "./modules/functions.js";
9
9
  import { createAgentsModule } from "./modules/agents.js";
10
10
  import { createAiGatewayModule } from "./modules/ai-gateway.js";
11
11
  import { createAppLogsModule } from "./modules/app-logs.js";
12
+ import { createAppModule } from "./modules/app.js";
12
13
  import { createUsersModule } from "./modules/users.js";
13
14
  import { RoomsSocket } from "./utils/socket-utils.js";
14
15
  import { createAnalyticsModule } from "./modules/analytics.js";
15
- import { createActorsModule, resolveActorsHost } from "./modules/actors.js";
16
+ import { createActorsModule, resolveActorsHost, } from "./modules/actors.js";
16
17
  /**
17
18
  * Creates a Base44 client.
18
19
  *
@@ -110,6 +111,15 @@ export function createClient(config) {
110
111
  token: serviceToken,
111
112
  interceptResponses: false,
112
113
  });
114
+ // Dedicated client for actor connection-token mints: no onError (a legacy
115
+ // actor answers every mint with an expected 409 before the proxy fallback,
116
+ // which must not reach the app's error handler — the actors module forwards
117
+ // genuine failures itself via onMintError) and no constructor token
118
+ // (auth is per-request so a login/logout is picked up on every reconnect).
119
+ const actorsAxiosClient = createAxiosClient({
120
+ baseURL: `${serverUrl}/api`,
121
+ headers,
122
+ });
113
123
  const userAuthModule = createAuthModule(axiosClient, functionsAxiosClient, appId, {
114
124
  appBaseUrl: normalizedAppBaseUrl,
115
125
  serverUrl,
@@ -127,11 +137,26 @@ export function createClient(config) {
127
137
  }
128
138
  const actorsModule = createActorsModule({
129
139
  appId,
130
- // serverUrl is often relative/empty (same-origin app); PartySocket needs an
131
- // absolute host, so fall back to the page origin.
140
+ // serverUrl is often relative/empty (same-origin app); the proxy-fallback
141
+ // URL needs an absolute host, so fall back to the page origin.
132
142
  host: resolveActorsHost(serverUrl, typeof window !== "undefined" ? (_a = window.location) === null || _a === void 0 ? void 0 : _a.origin : undefined),
133
143
  functionsVersion,
134
144
  getAuthToken: () => token || getAccessToken(),
145
+ mintConnectionToken: async (actorName, room, connectionId) => {
146
+ const authToken = token || getAccessToken();
147
+ return await actorsAxiosClient.post(`/apps/${appId}/actors/${encodeURIComponent(actorName)}/connection-token`, { room, connection_id: connectionId }, {
148
+ headers: {
149
+ ...(authToken ? { Authorization: `Bearer ${authToken}` } : {}),
150
+ // The mint endpoint resolves draft vs published from this header;
151
+ // only the functions axios clients send it by default.
152
+ ...(functionsVersion
153
+ ? { "Base44-Functions-Version": functionsVersion }
154
+ : {}),
155
+ },
156
+ });
157
+ },
158
+ transport: options === null || options === void 0 ? void 0 : options.actorsTransport,
159
+ onMintError: options === null || options === void 0 ? void 0 : options.onError,
135
160
  });
136
161
  const userModules = {
137
162
  entities: createEntitiesModule({
@@ -163,6 +188,7 @@ export function createClient(config) {
163
188
  }),
164
189
  aiGateway: createAiGatewayModule({ serverUrl, token, appId }),
165
190
  appLogs: createAppLogsModule(axiosClient, appId),
191
+ app: createAppModule(axiosClient, appId),
166
192
  users: createUsersModule(axiosClient, appId),
167
193
  analytics: createAnalyticsModule({
168
194
  axiosClient,
@@ -7,6 +7,7 @@ import type { FunctionsModule } from "./modules/functions.types.js";
7
7
  import type { AgentsModule } from "./modules/agents.types.js";
8
8
  import type { AiGatewayModule } from "./modules/ai-gateway.types.js";
9
9
  import type { AppLogsModule } from "./modules/app-logs.types.js";
10
+ import type { AppModule } from "./modules/app.types.js";
10
11
  import type { AnalyticsModule } from "./modules/analytics.types.js";
11
12
  import type { ActorsModule } from "./modules/actors.types.js";
12
13
  /**
@@ -15,8 +16,20 @@ import type { ActorsModule } from "./modules/actors.types.js";
15
16
  export interface CreateClientOptions {
16
17
  /**
17
18
  * Optional error handler that will be called whenever an API error occurs.
19
+ *
20
+ * Also receives {@link ActorsModule | actors} connection failures. Errors
21
+ * are usually {@linkcode Base44Error} instances — check `error.status`.
18
22
  */
19
23
  onError?: (error: Error) => void;
24
+ /**
25
+ * Forces the actors transport. `"auto"` (default) connects directly to the
26
+ * actor and falls back to the platform proxy when the app's actors don't
27
+ * support direct connections; `"proxy"` always uses the platform proxy
28
+ * (ops rollback — no connection-token calls); `"direct"` disables the
29
+ * fallback (validation environments).
30
+ * @internal
31
+ */
32
+ actorsTransport?: "auto" | "proxy" | "direct";
20
33
  }
21
34
  /**
22
35
  * Configuration for creating a Base44 client.
@@ -89,6 +102,8 @@ export interface Base44Client {
89
102
  analytics: AnalyticsModule;
90
103
  /** {@link AppLogsModule | App logs module} for tracking app usage. */
91
104
  appLogs: AppLogsModule;
105
+ /** {@link AppModule | App module} for reading the app's own public configuration. */
106
+ app: AppModule;
92
107
  /** {@link ActorsModule | Actors module} for subscribing to and sending messages via Cloudflare Durable Object-backed Actors. */
93
108
  actors: ActorsModule;
94
109
  /** {@link AuthModule | Auth module} for user authentication and management. */
package/dist/index.d.ts CHANGED
@@ -11,6 +11,7 @@ export type { FunctionsModule, FunctionName, FunctionNameRegistry, } from "./mod
11
11
  export type { AgentsModule, AgentName, AgentNameRegistry, AgentConversation, AgentMessage, AgentMessageReasoning, AgentMessageToolCall, AgentMessageUsage, AgentMessageCustomContext, AgentMessageMetadata, CreateConversationParams, } from "./modules/agents.types.js";
12
12
  export type { AiGatewayModule, AiGatewayConnection, } from "./modules/ai-gateway.types.js";
13
13
  export type { AppLogsModule } from "./modules/app-logs.types.js";
14
+ export type { AppModule, AppPublicSettings, AppPublicSettingsResponse, } from "./modules/app.types.js";
14
15
  export type { ActorsModule, ActorClient, ActorRef, Connection, ActorSubscription, ActorConnectOptions, ActorNameRegistry, ActorRegistry, } from "./modules/actors.types.js";
15
16
  export type { SsoModule, SsoAccessTokenResponse } from "./modules/sso.types.js";
16
17
  export { Actor, type Conn } from "./actor.js";
@@ -1,21 +1,47 @@
1
1
  import type { ActorRef } from "./actors.types.js";
2
+ /** Credentials minted by the platform for one direct actor connection. */
3
+ export interface ActorConnectionCredentials {
4
+ /** Direct actor endpoint, already carrying `?_pk=<connectionId>`. */
5
+ websocket_url: string;
6
+ /** Short-lived JWT bound to (app, actor, room, connectionId); appended to
7
+ * the URL as `token=` since browsers can't set WebSocket headers. */
8
+ token: string;
9
+ }
2
10
  interface ActorsConfig {
3
11
  appId: string;
4
- /** Current user access token, if authenticated. Rides the WS query so the
5
- * platform proxy can authenticate the connection; anonymous connects omit it. */
12
+ /** Current user access token, if authenticated. Rides the WS query on the
13
+ * proxy-fallback path so the platform proxy can authenticate the connection;
14
+ * anonymous connects omit it. */
6
15
  getAuthToken(): string | null | undefined;
7
16
  /** Same semantics as function calls: editors with a non-prod version get the
8
17
  * draft actor script; everyone else gets the published one. */
9
18
  functionsVersion?: string;
10
- /** Absolute host PartySocket dials (it strips the scheme and connects wss, ws
19
+ /** Absolute host for the proxy-fallback URL (scheme is swapped to wss, ws
11
20
  * for localhost). Resolved by {@link resolveActorsHost}. */
12
21
  host: string;
22
+ /** Mints a direct-connect credential for one (actor, room, connection).
23
+ * Called per connection attempt: the token's expiry is checked at upgrade,
24
+ * so every reconnect needs a fresh one. */
25
+ mintConnectionToken(actorName: string, room: string, connectionId: string): Promise<ActorConnectionCredentials>;
26
+ /** @internal Ops escape hatch: "proxy" never mints (legacy path only),
27
+ * "direct" never falls back. Default "auto". */
28
+ transport?: "auto" | "proxy" | "direct";
29
+ /** Called when a mint fails for a reason other than the expected
30
+ * direct→proxy fallback (which recovers by itself). Wired to the client's
31
+ * `options.onError`. */
32
+ onMintError?: (error: Error) => void;
13
33
  }
14
34
  /**
15
- * Absolute host for the actor WebSocket. PartySocket needs an absolute host and
16
- * can't resolve a relative/empty `serverUrl` (same-origin apps use a relative
17
- * `/api`, so `serverUrl` is often `""`), so fall back to the page origin.
18
- * PartySocket handles the scheme (https→wss, ws for localhost).
35
+ * The legacy platform-proxy URL, byte-for-byte what PartySocket built before
36
+ * the direct path existed: same scheme swap (including its localhost-needs-a-
37
+ * port quirk), case-preserved party segment, `_pk` first in the query. The
38
+ * `handler` param is load-bearing — the proxy reads it for the actor name.
39
+ */
40
+ export declare function buildProxyActorUrl(rawHost: string, actorName: string, instanceId: string, connectionId: string, appId: string, token: string | null | undefined, functionsVersion?: string): string;
41
+ /**
42
+ * Absolute host for the proxy-fallback actor URL. A relative/empty `serverUrl`
43
+ * can't be dialed (same-origin apps use a relative `/api`, so `serverUrl` is
44
+ * often `""`), so fall back to the page origin.
19
45
  */
20
46
  export declare function resolveActorsHost(serverUrl: string, browserOrigin?: string): string;
21
47
  export declare function createActorsModule(config: ActorsConfig): {
@@ -1,8 +1,32 @@
1
- import PartySocket from "partysocket";
2
- // Heartbeat / half-open detection: PartySocket only reconnects on a close/error
1
+ import { WebSocket as ReconnectingWebSocket } from "partysocket";
2
+ // Heartbeat / half-open detection: the socket only reconnects on a close/error
3
3
  // event, so ping periodically and force a reconnect if nothing returns in DEAD_MS.
4
4
  const PING_MS = 1000;
5
5
  const DEAD_MS = 3000;
6
+ // Mint responses that mean "direct can't serve this connection, the proxy can":
7
+ // 409 = legacy-family actor script, 503 = direct connections not provisioned,
8
+ // 422 = no principal (e.g. anonymous outside a browser) or an id/room only the
9
+ // proxy's looser validation accepts, 405 = a backend that predates the mint
10
+ // endpoint (its actor deploy routes catch the path via `{handler_name:path}`
11
+ // but not the POST method — and the real endpoint never 405s a POST). The
12
+ // proxy serves migrated actors too, so falling back is always safe.
13
+ const PROXY_FALLBACK_STATUSES = new Set([405, 409, 422, 503]);
14
+ // Mint responses no retry can fix (bad request / forbidden / not found): the
15
+ // connection closes instead of re-minting forever; a fresh connect() re-probes.
16
+ // 401 is deliberately absent — the auth token is re-read on every attempt, so a
17
+ // login recovers on the next retry. Disjoint from PROXY_FALLBACK_STATUSES.
18
+ const TERMINAL_MINT_STATUSES = new Set([400, 403, 404]);
19
+ /** The mint's rejection can be anything; a `Base44Error` carries a numeric
20
+ * `.status` (absent for network failures). */
21
+ function mintErrorStatus(err) {
22
+ const status = err && typeof err === "object"
23
+ ? err.status
24
+ : undefined;
25
+ return typeof status === "number" ? status : undefined;
26
+ }
27
+ function toError(err) {
28
+ return err instanceof Error ? err : new Error(String(err));
29
+ }
6
30
  /**
7
31
  * A live connection to an actor instance. Only obtainable from
8
32
  * {@link ActorRef.connect}, so `subscribe`/`send` are always valid — the socket
@@ -14,23 +38,54 @@ class Connection {
14
38
  this.onClose = onClose;
15
39
  this.listeners = new Set();
16
40
  this.heartbeat = null;
41
+ this.closed = false;
17
42
  this.id = (_a = options === null || options === void 0 ? void 0 : options.id) !== null && _a !== void 0 ? _a : crypto.randomUUID();
18
- const ws = new PartySocket({
19
- host: config.host,
20
- party: actorName,
21
- room: instanceId,
22
- id: this.id,
23
- // Re-read on every (re)connect so a login/logout is picked up.
24
- query: () => {
25
- const token = config.getAuthToken();
26
- return {
27
- app_id: config.appId,
28
- handler: actorName,
29
- ...(token ? { token } : {}),
30
- ...(config.functionsVersion ? { fv: config.functionsVersion } : {}),
31
- };
32
- },
33
- });
43
+ // Direct-first with proxy fallback, decided per connection attempt. Once a
44
+ // mint answers with a fallback status the choice is sticky for this
45
+ // socket's lifetime (a fresh connect() after close() probes direct again,
46
+ // picking up actors migrated in the meantime). Any other mint failure
47
+ // rejects, which ReconnectingWebSocket retries with backoff — except the
48
+ // terminal statuses, which close this connection for good.
49
+ let useProxy = config.transport === "proxy";
50
+ const urlProvider = async () => {
51
+ var _a;
52
+ if (this.closed)
53
+ throw new Error("Actor connection is closed");
54
+ if (!useProxy) {
55
+ try {
56
+ const { websocket_url, token } = await config.mintConnectionToken(actorName, instanceId, this.id);
57
+ const sep = websocket_url.includes("?") ? "&" : "?";
58
+ return `${websocket_url}${sep}token=${encodeURIComponent(token)}`;
59
+ }
60
+ catch (err) {
61
+ const status = mintErrorStatus(err);
62
+ const isFallback = config.transport !== "direct" &&
63
+ status !== undefined &&
64
+ PROXY_FALLBACK_STATUSES.has(status);
65
+ if (!isFallback) {
66
+ if (status !== undefined && TERMINAL_MINT_STATUSES.has(status)) {
67
+ // close() before notifying: ws.close() stops the redial the
68
+ // rethrow below would otherwise schedule, and a handler that
69
+ // immediately calls connect() gets a clean new connection.
70
+ this.close();
71
+ }
72
+ // Reported from here because the socket's error event only
73
+ // preserves `err.message`, never `.status`.
74
+ try {
75
+ (_a = config.onMintError) === null || _a === void 0 ? void 0 : _a.call(config, toError(err));
76
+ }
77
+ catch (_b) {
78
+ // an app handler must not break the dial loop or mask `err`
79
+ }
80
+ throw err;
81
+ }
82
+ useProxy = true;
83
+ }
84
+ }
85
+ // Rebuilt per attempt so a login/logout is picked up on reconnect.
86
+ return buildProxyActorUrl(config.host, actorName, instanceId, this.id, config.appId, config.getAuthToken(), config.functionsVersion);
87
+ };
88
+ const ws = new ReconnectingWebSocket(urlProvider);
34
89
  this.ws = ws;
35
90
  let lastMsg = Date.now();
36
91
  const bumpAlive = () => { lastMsg = Date.now(); };
@@ -53,7 +108,11 @@ class Connection {
53
108
  this.heartbeat = setInterval(() => {
54
109
  if (Date.now() - lastMsg > DEAD_MS) {
55
110
  bumpAlive(); // avoid a reconnect storm while the new socket comes up
56
- ws.reconnect();
111
+ // Only kick a half-open socket (OPEN but silent). When it isn't open
112
+ // the socket is already redialing with backoff, and reconnect() would
113
+ // reset that backoff into a mint call every DEAD_MS.
114
+ if (ws.readyState === ws.OPEN)
115
+ ws.reconnect();
57
116
  return;
58
117
  }
59
118
  try {
@@ -73,9 +132,15 @@ class Connection {
73
132
  };
74
133
  }
75
134
  send(data) {
135
+ // after close() the socket would buffer forever (unbounded enqueue)
136
+ if (this.closed)
137
+ return;
76
138
  this.ws.send(JSON.stringify(data));
77
139
  }
78
140
  close() {
141
+ if (this.closed)
142
+ return;
143
+ this.closed = true;
79
144
  if (this.heartbeat) {
80
145
  clearInterval(this.heartbeat);
81
146
  this.heartbeat = null;
@@ -104,10 +169,38 @@ function makeActorRef(actorName, instanceId, config, connections) {
104
169
  };
105
170
  }
106
171
  /**
107
- * Absolute host for the actor WebSocket. PartySocket needs an absolute host and
108
- * can't resolve a relative/empty `serverUrl` (same-origin apps use a relative
109
- * `/api`, so `serverUrl` is often `""`), so fall back to the page origin.
110
- * PartySocket handles the scheme (https→wss, ws for localhost).
172
+ * The legacy platform-proxy URL, byte-for-byte what PartySocket built before
173
+ * the direct path existed: same scheme swap (including its localhost-needs-a-
174
+ * port quirk), case-preserved party segment, `_pk` first in the query. The
175
+ * `handler` param is load-bearing — the proxy reads it for the actor name.
176
+ */
177
+ export function buildProxyActorUrl(rawHost, actorName, instanceId, connectionId, appId, token, functionsVersion) {
178
+ let host = rawHost.replace(/^(http|https|ws|wss):\/\//, "");
179
+ if (host.endsWith("/"))
180
+ host = host.slice(0, -1);
181
+ const insecure = host.startsWith("localhost:") ||
182
+ host.startsWith("127.0.0.1:") ||
183
+ host.startsWith("192.168.") ||
184
+ host.startsWith("10.") ||
185
+ (host.startsWith("172.") &&
186
+ host.split(".")[1] >= "16" &&
187
+ host.split(".")[1] <= "31") ||
188
+ host.startsWith("[::ffff:7f00:1]:");
189
+ const query = new URLSearchParams([
190
+ ["_pk", connectionId],
191
+ ["app_id", appId],
192
+ ["handler", actorName],
193
+ ]);
194
+ if (token)
195
+ query.append("token", token);
196
+ if (functionsVersion)
197
+ query.append("fv", functionsVersion);
198
+ return `${insecure ? "ws" : "wss"}://${host}/parties/${actorName}/${instanceId}?${query}`;
199
+ }
200
+ /**
201
+ * Absolute host for the proxy-fallback actor URL. A relative/empty `serverUrl`
202
+ * can't be dialed (same-origin apps use a relative `/api`, so `serverUrl` is
203
+ * often `""`), so fall back to the page origin.
111
204
  */
112
205
  export function resolveActorsHost(serverUrl, browserOrigin) {
113
206
  return serverUrl && !serverUrl.startsWith("/") ? serverUrl : browserOrigin !== null && browserOrigin !== void 0 ? browserOrigin : serverUrl;
@@ -56,9 +56,14 @@ export interface Connection<N extends string = string> {
56
56
  readonly id: string;
57
57
  /** Register a message listener. Multiple are allowed; returns a per-listener unsubscribe. */
58
58
  subscribe(callback: (data: ToClientFor<N>) => void): ActorSubscription;
59
- /** Send a message. Buffered by the socket until it's open. */
59
+ /** Send a message. Buffered by the socket until it's open; dropped after
60
+ * {@link close}. */
60
61
  send(data: ToServerFor<N>): void;
61
- /** Tear down the socket, heartbeat, and all listeners. */
62
+ /**
63
+ * Tear down the socket, heartbeat, and all listeners. Safe to call more
64
+ * than once. A connection also closes itself when it fails permanently —
65
+ * see {@link ActorRef.connect}.
66
+ */
62
67
  close(): void;
63
68
  }
64
69
  /**
@@ -66,7 +71,15 @@ export interface Connection<N extends string = string> {
66
71
  * {@link connect} to open the socket and get a {@link Connection}.
67
72
  */
68
73
  export interface ActorRef<N extends string = string> {
69
- /** Open the WebSocket and return the {@link Connection}. Idempotent. */
74
+ /**
75
+ * Open the WebSocket and return the {@link Connection}. Idempotent while the
76
+ * connection is open.
77
+ *
78
+ * A connection that fails permanently (for example, the actor doesn't exist
79
+ * or the caller isn't allowed to connect) closes itself and reports the
80
+ * error to the client's `onError` handler. Call `connect()` again after
81
+ * fixing the cause to get a fresh {@link Connection}, and re-subscribe.
82
+ */
70
83
  connect(options?: ActorConnectOptions): Connection<N>;
71
84
  }
72
85
  /**
@@ -25,6 +25,9 @@ const analyticsSharedState = getSharedInstance(ANALYTICS_SHARED_STATE_NAME, () =
25
25
  wasInitializationTracked: false,
26
26
  sessionContext: null,
27
27
  sessionStartTime: null,
28
+ // Memoized session id for when `localStorage` can't persist one — see
29
+ // getAnalyticsSessionId.
30
+ fallbackSessionId: null,
28
31
  config: {
29
32
  ...defaultConfiguration,
30
33
  ...getAnalyticsConfigFromUrlParams(),
@@ -216,9 +219,11 @@ function trackSessionDurationEvent(track) {
216
219
  });
217
220
  }
218
221
  function getEventIntrinsicData() {
222
+ var _a, _b;
219
223
  return {
220
224
  timestamp: new Date().toISOString(),
221
- pageUrl: typeof window !== "undefined" ? window.location.pathname : null,
225
+ // `window.location` is absent on React Native, so read it optionally.
226
+ pageUrl: typeof window !== "undefined" ? (_b = (_a = window.location) === null || _a === void 0 ? void 0 : _a.pathname) !== null && _b !== void 0 ? _b : null : null,
222
227
  };
223
228
  }
224
229
  function transformEventDataToApiRequestData(sessionContext) {
@@ -302,9 +307,15 @@ export function getAnalyticsConfigFromUrlParams() {
302
307
  // return the config object //
303
308
  return { enabled: analyticsEnable === "true" };
304
309
  }
310
+ // When the id can't be persisted (React Native has no `localStorage`), keep
311
+ // it stable for the process instead of minting a fresh one per call.
312
+ function getFallbackSessionId() {
313
+ var _a;
314
+ return ((_a = analyticsSharedState.fallbackSessionId) !== null && _a !== void 0 ? _a : (analyticsSharedState.fallbackSessionId = generateUuid()));
315
+ }
305
316
  export function getAnalyticsSessionId() {
306
317
  if (typeof window === "undefined") {
307
- return generateUuid();
318
+ return getFallbackSessionId();
308
319
  }
309
320
  try {
310
321
  const sessionId = localStorage.getItem(ANALYTICS_SESSION_ID_LOCAL_STORAGE_KEY);
@@ -316,6 +327,6 @@ export function getAnalyticsSessionId() {
316
327
  return sessionId;
317
328
  }
318
329
  catch (_a) {
319
- return generateUuid();
330
+ return getFallbackSessionId();
320
331
  }
321
332
  }
@@ -0,0 +1,11 @@
1
+ import { AxiosInstance } from "axios";
2
+ import { AppModule } from "./app.types";
3
+ /**
4
+ * Creates the app module for the Base44 SDK.
5
+ *
6
+ * @param axios - Axios instance
7
+ * @param appId - Application ID
8
+ * @returns App module for reading the app's own configuration
9
+ * @internal
10
+ */
11
+ export declare function createAppModule(axios: AxiosInstance, appId: string): AppModule;
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Creates the app module for the Base44 SDK.
3
+ *
4
+ * @param axios - Axios instance
5
+ * @param appId - Application ID
6
+ * @returns App module for reading the app's own configuration
7
+ * @internal
8
+ */
9
+ export function createAppModule(axios, appId) {
10
+ return {
11
+ async getPublicSettings() {
12
+ return axios.get(`/apps/public/prod/public-settings/by-id/${appId}`);
13
+ },
14
+ };
15
+ }
@@ -1,3 +1,55 @@
1
+ /**
2
+ * The app's access policy: whether the app is reachable without an account, and
3
+ * who may sign in.
4
+ */
5
+ export type AppPublicSettings = "private_with_login" | "public_with_login" | "public_without_login" | "workspace_with_login" | string;
6
+ /**
7
+ * The app's public configuration, as returned by {@link AppModule.getPublicSettings}.
8
+ */
9
+ export interface AppPublicSettingsResponse {
10
+ /** The app's ID. */
11
+ id: string;
12
+ /** The app's access policy. */
13
+ public_settings: AppPublicSettings;
14
+ }
15
+ /**
16
+ * App module for reading the app's own public configuration.
17
+ *
18
+ * Use it to discover how the app is gated before rendering it, so a private app
19
+ * can send the visitor to login instead of rendering an empty shell.
20
+ *
21
+ * ## Authentication Modes
22
+ *
23
+ * This module is available to use with a client in all authentication modes. The
24
+ * client's token, when it has one, is sent with the request — a signed-in visitor
25
+ * who has no access to the app is reported differently from an anonymous one.
26
+ */
27
+ export interface AppModule {
28
+ /**
29
+ * Get the app's public configuration.
30
+ *
31
+ * Rejects with a {@linkcode Base44Error} when the visitor may not open the app:
32
+ * `status` is `403` and `data.extra_data.reason` says why — `"auth_required"`
33
+ * when the visitor must sign in, `"user_not_registered"` when the signed-in
34
+ * visitor has no access to this app.
35
+ *
36
+ * @returns Promise resolving to the app's ID and access policy.
37
+ *
38
+ * @example
39
+ * ```typescript
40
+ * // Decide what to render before the app boots
41
+ * try {
42
+ * const { public_settings } = await base44.app.getPublicSettings();
43
+ * console.log('App access policy:', public_settings);
44
+ * } catch (error) {
45
+ * if (error.status === 403) {
46
+ * console.log('Blocked because:', error.data?.extra_data?.reason);
47
+ * }
48
+ * }
49
+ * ```
50
+ */
51
+ getPublicSettings(): Promise<AppPublicSettingsResponse>;
52
+ }
1
53
  /**
2
54
  * @internal
3
55
  */
@@ -62,7 +114,7 @@ export interface AppLike {
62
114
  agents?: Record<string, any>;
63
115
  logo_url?: string;
64
116
  slug?: string;
65
- public_settings?: "private_with_login" | "public_with_login" | "public_without_login" | "workspace_with_login" | string;
117
+ public_settings?: AppPublicSettings;
66
118
  is_blocked?: boolean;
67
119
  github_repo_url?: string;
68
120
  main_page?: string;
@@ -134,12 +134,15 @@ export interface AuthModule {
134
134
  /**
135
135
  * Updates the current authenticated user's information.
136
136
  *
137
- * You can update `role` and any [custom fields](/developers/backend/resources/entities/user-schema#custom-fields) defined in your
138
- * User entity schema.
139
- * The `role` value must be either `'user'` or `'admin'`.
137
+ * You can update any [custom fields](/developers/backend/resources/entities/user-schema#custom-fields)
138
+ * defined in your User entity schema.
139
+ *
140
+ * Updating `role` requires editor access on the app.
141
+ *
140
142
  * <Note>
141
- * The following fields are read-only and can't be changed with this method:
142
- * `id`, `email`, `full_name`, `created_date`, `updated_date`, and `created_by`.
143
+ * These fields can't be changed with this method:
144
+ * `id`, `email`, `full_name`, `created_date`, `updated_date`, `created_by`,
145
+ * and `collaborator_role`.
143
146
  * </Note>
144
147
  *
145
148
  * @param data - Object containing the fields to update.
@@ -147,9 +150,8 @@ export interface AuthModule {
147
150
  *
148
151
  * @example
149
152
  * ```typescript
150
- * // Update role and custom fields defined in your User entity
153
+ * // Update custom fields defined in your User entity
151
154
  * await base44.auth.updateMe({
152
- * role: 'admin',
153
155
  * bio: 'Software developer',
154
156
  * preferences: { theme: 'dark' }
155
157
  * });
@@ -43,9 +43,9 @@ export interface InvokeLLMParams {
43
43
  prompt: string;
44
44
  /** Optionally specify a model to override the app-level model setting for this specific call.
45
45
  *
46
- * Options: `"gpt_5_mini"`, `"gemini_3_flash"`, `"gpt_5_4"`, `"gpt_5_5"`, `"gemini_3_1_pro"`, `"claude_sonnet_4_6"`, `"claude_opus_4_6"`, `"claude_opus_4_7"`, `"claude_opus_4_8"`
46
+ * Options: `"gpt_5_mini"`, `"gemini_3_flash"`, `"gpt_5_4"`, `"gpt_5_6_sol"`, `"gpt_5_6_luna"`, `"gemini_3_1_pro"`, `"claude_sonnet_4_6"`, `"claude_opus_4_6"`, `"claude_opus_4_7"`, `"claude_opus_4_8"`, `"claude-sonnet-5"`
47
47
  */
48
- model?: 'gpt_5_mini' | 'gemini_3_flash' | 'gpt_5_4' | 'gpt_5_5' | 'gemini_3_1_pro' | 'claude_sonnet_4_6' | 'claude_opus_4_6' | 'claude_opus_4_7' | 'claude_opus_4_8';
48
+ model?: 'gpt_5_mini' | 'gemini_3_flash' | 'gpt_5_4' | 'gpt_5_6_sol' | 'gpt_5_6_luna' | 'gemini_3_1_pro' | 'claude_sonnet_4_6' | 'claude_opus_4_6' | 'claude_opus_4_7' | 'claude_opus_4_8' | 'claude-sonnet-5';
49
49
  /** If set to `true`, the LLM will use Google Search, Maps, and News to gather real-time context before answering.
50
50
  * @default false
51
51
  */
@@ -132,8 +132,10 @@ export function createAxiosClient({ baseURL, headers = {}, token, interceptRespo
132
132
  client.interceptors.request.use((config) => {
133
133
  // `window.location` is absent on React Native (where `window` still exists),
134
134
  // so guard on it before reading `.href`.
135
- if (typeof window !== "undefined" && window.location) {
136
- config.headers.set("X-Origin-URL", window.location.href);
135
+ if (typeof window !== "undefined") {
136
+ if (window.location) {
137
+ config.headers.set("X-Origin-URL", window.location.href);
138
+ }
137
139
  // On unauthenticated requests, attach a stable anonymous visitor id so the
138
140
  // backend can support anonymous agent access (conversation grouping + ownership).
139
141
  // Authenticated requests are identified by their Authorization header instead.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@depup/base44__sdk",
3
- "version": "0.8.44-depup.0",
3
+ "version": "0.8.45-depup.0",
4
4
  "description": "JavaScript SDK for Base44 API (with updated dependencies)",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -88,8 +88,8 @@
88
88
  },
89
89
  "depsUpdated": 3,
90
90
  "originalPackage": "@base44/sdk",
91
- "originalVersion": "0.8.44",
92
- "processedAt": "2026-08-26T16:29:25.763Z",
91
+ "originalVersion": "0.8.45",
92
+ "processedAt": "2026-09-02T08:12:22.602Z",
93
93
  "smokeTest": "passed"
94
94
  }
95
95
  }