@base44-preview/sdk 0.8.40-pr.212.d742832 → 0.8.40-pr.212.f89ce7f
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/dist/client.js +20 -30
- package/dist/modules/actors.d.ts +16 -1
- package/dist/modules/actors.js +46 -11
- package/dist/modules/actors.types.d.ts +1 -1
- package/package.json +1 -1
package/dist/client.js
CHANGED
|
@@ -12,7 +12,7 @@ import { createAppLogsModule } from "./modules/app-logs.js";
|
|
|
12
12
|
import { createUsersModule } from "./modules/users.js";
|
|
13
13
|
import { RoomsSocket } from "./utils/socket-utils.js";
|
|
14
14
|
import { createAnalyticsModule } from "./modules/analytics.js";
|
|
15
|
-
import { createActorsModule } from "./modules/actors.js";
|
|
15
|
+
import { createActorsModule, resolveActorsWsUrl } from "./modules/actors.js";
|
|
16
16
|
/**
|
|
17
17
|
* Creates a Base44 client.
|
|
18
18
|
*
|
|
@@ -51,28 +51,18 @@ import { createActorsModule } from "./modules/actors.js";
|
|
|
51
51
|
* ```
|
|
52
52
|
*/
|
|
53
53
|
export function createClient(config) {
|
|
54
|
-
var _a, _b;
|
|
54
|
+
var _a, _b, _c, _d;
|
|
55
55
|
const { serverUrl = "https://base44.app", appId, token, serviceToken, requiresAuth = false, appBaseUrl, options, functionsVersion, headers: optionalHeaders, actorsWsUrl, } = config;
|
|
56
56
|
// Normalize appBaseUrl to always be a string (empty if not provided or invalid)
|
|
57
57
|
const normalizedAppBaseUrl = typeof appBaseUrl === "string" ? appBaseUrl : "";
|
|
58
|
-
//
|
|
59
|
-
// the
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
if (actorsWsUrl)
|
|
67
|
-
return actorsWsUrl.replace(/\/$/, "");
|
|
68
|
-
const appOrigin = normalizedAppBaseUrl ||
|
|
69
|
-
// React Native has a bare `window` with no `location`, so guard both.
|
|
70
|
-
(typeof window !== "undefined" ? (_b = (_a = window.location) === null || _a === void 0 ? void 0 : _a.origin) !== null && _b !== void 0 ? _b : "" : "");
|
|
71
|
-
return (appOrigin || serverUrl)
|
|
72
|
-
.replace(/\/$/, "")
|
|
73
|
-
.replace(/^https:\/\//, "wss://")
|
|
74
|
-
.replace(/^http:\/\//, "ws://");
|
|
75
|
-
})();
|
|
58
|
+
// Same-origin with the running app (it proxies /parties to the backend), not
|
|
59
|
+
// the API host. React Native has a bare `window` with no `location`, so guard both.
|
|
60
|
+
const resolvedActorsWsUrl = resolveActorsWsUrl({
|
|
61
|
+
actorsWsUrl,
|
|
62
|
+
appBaseUrl: normalizedAppBaseUrl,
|
|
63
|
+
browserOrigin: typeof window !== "undefined" ? (_b = (_a = window.location) === null || _a === void 0 ? void 0 : _a.origin) !== null && _b !== void 0 ? _b : "" : "",
|
|
64
|
+
serverUrl,
|
|
65
|
+
});
|
|
76
66
|
const socketConfig = {
|
|
77
67
|
serverUrl,
|
|
78
68
|
mountPath: "/ws-user-apps/socket.io/",
|
|
@@ -142,6 +132,12 @@ export function createClient(config) {
|
|
|
142
132
|
userAuthModule.setToken(accessToken);
|
|
143
133
|
}
|
|
144
134
|
}
|
|
135
|
+
const actorsModule = createActorsModule({
|
|
136
|
+
appId,
|
|
137
|
+
actorsWsUrl: resolvedActorsWsUrl,
|
|
138
|
+
functionsVersion,
|
|
139
|
+
getAuthToken: () => token || getAccessToken(),
|
|
140
|
+
});
|
|
145
141
|
const userModules = {
|
|
146
142
|
entities: createEntitiesModule({
|
|
147
143
|
axios: axiosClient,
|
|
@@ -161,7 +157,7 @@ export function createClient(config) {
|
|
|
161
157
|
}
|
|
162
158
|
return headers;
|
|
163
159
|
},
|
|
164
|
-
baseURL: (
|
|
160
|
+
baseURL: (_c = functionsAxiosClient.defaults) === null || _c === void 0 ? void 0 : _c.baseURL,
|
|
165
161
|
}),
|
|
166
162
|
agents: createAgentsModule({
|
|
167
163
|
axios: axiosClient,
|
|
@@ -179,16 +175,10 @@ export function createClient(config) {
|
|
|
179
175
|
appId,
|
|
180
176
|
userAuthModule,
|
|
181
177
|
}),
|
|
182
|
-
actors:
|
|
183
|
-
appId,
|
|
184
|
-
actorsWsUrl: resolvedActorsWsUrl,
|
|
185
|
-
functionsVersion,
|
|
186
|
-
// Same credential as function calls; the platform proxy authenticates the
|
|
187
|
-
// WS connection with it (anonymous when absent) — no pre-connect token mint.
|
|
188
|
-
getAuthToken: () => token || getAccessToken(),
|
|
189
|
-
}),
|
|
178
|
+
actors: actorsModule.module,
|
|
190
179
|
cleanup: () => {
|
|
191
180
|
userModules.analytics.cleanup();
|
|
181
|
+
actorsModule.closeAll();
|
|
192
182
|
if (socket) {
|
|
193
183
|
socket.disconnect();
|
|
194
184
|
}
|
|
@@ -212,7 +202,7 @@ export function createClient(config) {
|
|
|
212
202
|
}
|
|
213
203
|
return headers;
|
|
214
204
|
},
|
|
215
|
-
baseURL: (
|
|
205
|
+
baseURL: (_d = serviceRoleFunctionsAxiosClient.defaults) === null || _d === void 0 ? void 0 : _d.baseURL,
|
|
216
206
|
}),
|
|
217
207
|
agents: createAgentsModule({
|
|
218
208
|
axios: serviceRoleAxiosClient,
|
package/dist/modules/actors.d.ts
CHANGED
|
@@ -9,5 +9,20 @@ interface ActorsConfig {
|
|
|
9
9
|
functionsVersion?: string;
|
|
10
10
|
actorsWsUrl: string;
|
|
11
11
|
}
|
|
12
|
-
|
|
12
|
+
/**
|
|
13
|
+
* Base WebSocket URL for Actor connections. An explicit `actorsWsUrl` wins;
|
|
14
|
+
* otherwise the app's own origin (`appBaseUrl`, else the browser origin, else
|
|
15
|
+
* `serverUrl`) with `https://`→`wss://` / `http://`→`ws://` and no trailing
|
|
16
|
+
* slash — the app proxies `/parties` to the backend dispatcher.
|
|
17
|
+
*/
|
|
18
|
+
export declare function resolveActorsWsUrl(opts: {
|
|
19
|
+
actorsWsUrl?: string;
|
|
20
|
+
appBaseUrl?: string;
|
|
21
|
+
browserOrigin?: string;
|
|
22
|
+
serverUrl: string;
|
|
23
|
+
}): string;
|
|
24
|
+
export declare function createActorsModule(config: ActorsConfig): {
|
|
25
|
+
module: Record<string, (instanceId: string) => ActorRoom>;
|
|
26
|
+
closeAll: () => void;
|
|
27
|
+
};
|
|
13
28
|
export {};
|
package/dist/modules/actors.js
CHANGED
|
@@ -4,10 +4,11 @@ import PartySocket from "partysocket";
|
|
|
4
4
|
const PING_MS = 1000;
|
|
5
5
|
const DEAD_MS = 3000;
|
|
6
6
|
class Room {
|
|
7
|
-
constructor(actorName, instanceId, config) {
|
|
7
|
+
constructor(actorName, instanceId, config, onClose) {
|
|
8
8
|
this.actorName = actorName;
|
|
9
9
|
this.instanceId = instanceId;
|
|
10
10
|
this.config = config;
|
|
11
|
+
this.onClose = onClose;
|
|
11
12
|
this.ws = null;
|
|
12
13
|
this.listeners = new Set();
|
|
13
14
|
this.heartbeat = null;
|
|
@@ -53,11 +54,11 @@ class Room {
|
|
|
53
54
|
data = JSON.parse(ev.data);
|
|
54
55
|
}
|
|
55
56
|
catch (_a) {
|
|
56
|
-
return;
|
|
57
|
+
return;
|
|
57
58
|
}
|
|
58
59
|
const msgType = data && typeof data === "object" ? data.type : undefined;
|
|
59
60
|
if (msgType === "__pong")
|
|
60
|
-
return;
|
|
61
|
+
return;
|
|
61
62
|
for (const listener of this.listeners)
|
|
62
63
|
listener(data);
|
|
63
64
|
});
|
|
@@ -68,13 +69,12 @@ class Room {
|
|
|
68
69
|
return;
|
|
69
70
|
}
|
|
70
71
|
try {
|
|
71
|
-
//
|
|
72
|
-
//
|
|
73
|
-
// idle room's lastMsg goes stale and this watchdog reconnects every DEAD_MS.
|
|
72
|
+
// The deployed shim echoes __ping → __pong (base44-userapp-bundler
|
|
73
|
+
// shim/actor.ts); without that, an idle room reconnects every DEAD_MS.
|
|
74
74
|
ws.send(JSON.stringify({ type: "__ping" }));
|
|
75
75
|
}
|
|
76
76
|
catch (_a) {
|
|
77
|
-
//
|
|
77
|
+
// not open; the watchdog above will reconnect
|
|
78
78
|
}
|
|
79
79
|
}, PING_MS);
|
|
80
80
|
return this;
|
|
@@ -95,7 +95,7 @@ class Room {
|
|
|
95
95
|
this.ws.send(JSON.stringify(data));
|
|
96
96
|
}
|
|
97
97
|
close() {
|
|
98
|
-
var _a;
|
|
98
|
+
var _a, _b;
|
|
99
99
|
if (this.heartbeat) {
|
|
100
100
|
clearInterval(this.heartbeat);
|
|
101
101
|
this.heartbeat = null;
|
|
@@ -103,12 +103,47 @@ class Room {
|
|
|
103
103
|
this.listeners.clear();
|
|
104
104
|
(_a = this.ws) === null || _a === void 0 ? void 0 : _a.close();
|
|
105
105
|
this.ws = null;
|
|
106
|
+
this.connId = null;
|
|
107
|
+
(_b = this.onClose) === null || _b === void 0 ? void 0 : _b.call(this);
|
|
106
108
|
}
|
|
107
109
|
}
|
|
110
|
+
/**
|
|
111
|
+
* Base WebSocket URL for Actor connections. An explicit `actorsWsUrl` wins;
|
|
112
|
+
* otherwise the app's own origin (`appBaseUrl`, else the browser origin, else
|
|
113
|
+
* `serverUrl`) with `https://`→`wss://` / `http://`→`ws://` and no trailing
|
|
114
|
+
* slash — the app proxies `/parties` to the backend dispatcher.
|
|
115
|
+
*/
|
|
116
|
+
export function resolveActorsWsUrl(opts) {
|
|
117
|
+
if (opts.actorsWsUrl)
|
|
118
|
+
return opts.actorsWsUrl.replace(/\/$/, "");
|
|
119
|
+
const appOrigin = opts.appBaseUrl || opts.browserOrigin || "";
|
|
120
|
+
return (appOrigin || opts.serverUrl)
|
|
121
|
+
.replace(/\/$/, "")
|
|
122
|
+
.replace(/^https:\/\//, "wss://")
|
|
123
|
+
.replace(/^http:\/\//, "ws://");
|
|
124
|
+
}
|
|
108
125
|
export function createActorsModule(config) {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
126
|
+
// Live rooms this client opened, so client.cleanup() can reclaim any the app
|
|
127
|
+
// forgot to close() (each room removes itself here on close).
|
|
128
|
+
const rooms = new Set();
|
|
129
|
+
const module = new Proxy({}, {
|
|
130
|
+
get(_, key) {
|
|
131
|
+
// Symbols and `then` resolve to undefined (so the module isn't mistaken
|
|
132
|
+
// for a thenable when awaited); any string key is an actor name.
|
|
133
|
+
if (typeof key !== "string" || key === "then")
|
|
134
|
+
return undefined;
|
|
135
|
+
return (instanceId) => {
|
|
136
|
+
const room = new Room(key, instanceId, config, () => rooms.delete(room));
|
|
137
|
+
rooms.add(room);
|
|
138
|
+
return room;
|
|
139
|
+
};
|
|
112
140
|
},
|
|
113
141
|
});
|
|
142
|
+
return {
|
|
143
|
+
module,
|
|
144
|
+
closeAll: () => {
|
|
145
|
+
for (const room of [...rooms])
|
|
146
|
+
room.close();
|
|
147
|
+
},
|
|
148
|
+
};
|
|
114
149
|
}
|
|
@@ -58,7 +58,7 @@ export interface ActorRoom<N extends string = string> {
|
|
|
58
58
|
connect(options?: ActorConnectOptions): this;
|
|
59
59
|
/** Register a message listener. Multiple are allowed; returns a per-listener unsubscribe. */
|
|
60
60
|
subscribe(callback: (data: ToClientFor<N>) => void): ActorSubscription;
|
|
61
|
-
/** Send a message. Throws before {@link connect}; buffered by the socket
|
|
61
|
+
/** Send a message. Throws before {@link connect}; buffered by the socket once connecting. */
|
|
62
62
|
send(data: ToServerFor<N>): void;
|
|
63
63
|
/** Tear down the socket, heartbeat, and all listeners. */
|
|
64
64
|
close(): void;
|