@base44-preview/sdk 0.8.40-pr.212.8d7ec0a → 0.8.40-pr.212.ae9a5d0
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/actor.d.ts +7 -0
- package/dist/actor.js +8 -0
- package/dist/client.js +15 -29
- package/dist/client.types.d.ts +0 -10
- package/dist/modules/actors.d.ts +14 -2
- package/dist/modules/actors.js +36 -6
- package/dist/modules/actors.types.d.ts +1 -1
- package/package.json +1 -1
package/dist/actor.d.ts
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
* At deploy time the bundler replaces this import with the compiled
|
|
9
9
|
* Cloudflare Durable Object implementation — this file provides types only.
|
|
10
10
|
*/
|
|
11
|
+
import type { Base44Client } from "./client";
|
|
11
12
|
/**
|
|
12
13
|
* A single client connection. `Send` is the message type this connection accepts
|
|
13
14
|
* via {@link send} — the actor's *outgoing* (server→client) messages.
|
|
@@ -74,4 +75,10 @@ export declare abstract class Actor<Incoming = unknown, Outgoing = unknown> {
|
|
|
74
75
|
protected stopLoop(): Promise<void>;
|
|
75
76
|
protected get instanceId(): string;
|
|
76
77
|
protected get storage(): Storage;
|
|
78
|
+
/**
|
|
79
|
+
* Anonymous Base44 client scoped to this actor instance — no user or service
|
|
80
|
+
* auth, so entity access is RLS-gated (same as a logged-out visitor).
|
|
81
|
+
* Example: `const rows = await this.client.entities.Score.list();`
|
|
82
|
+
*/
|
|
83
|
+
protected get client(): Base44Client;
|
|
77
84
|
}
|
package/dist/actor.js
CHANGED
|
@@ -60,4 +60,12 @@ export class Actor {
|
|
|
60
60
|
get storage() {
|
|
61
61
|
throw new Error("Actor.storage is only available inside a deployed actor");
|
|
62
62
|
}
|
|
63
|
+
/**
|
|
64
|
+
* Anonymous Base44 client scoped to this actor instance — no user or service
|
|
65
|
+
* auth, so entity access is RLS-gated (same as a logged-out visitor).
|
|
66
|
+
* Example: `const rows = await this.client.entities.Score.list();`
|
|
67
|
+
*/
|
|
68
|
+
get client() {
|
|
69
|
+
throw new Error("Actor.client is only available inside a deployed actor");
|
|
70
|
+
}
|
|
63
71
|
}
|
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, resolveActorsHost } from "./modules/actors.js";
|
|
16
16
|
/**
|
|
17
17
|
* Creates a Base44 client.
|
|
18
18
|
*
|
|
@@ -51,28 +51,10 @@ import { createActorsModule } from "./modules/actors.js";
|
|
|
51
51
|
* ```
|
|
52
52
|
*/
|
|
53
53
|
export function createClient(config) {
|
|
54
|
-
var _a, _b;
|
|
55
|
-
const { serverUrl = "https://base44.app", appId, token, serviceToken, requiresAuth = false, appBaseUrl, options, functionsVersion, headers: optionalHeaders,
|
|
54
|
+
var _a, _b, _c;
|
|
55
|
+
const { serverUrl = "https://base44.app", appId, token, serviceToken, requiresAuth = false, appBaseUrl, options, functionsVersion, headers: optionalHeaders, } = 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
|
-
// Derive the Actor WebSocket URL if not explicitly provided. Default to
|
|
59
|
-
// the app's OWN origin (the app URL proxies /parties to the backend) so the
|
|
60
|
-
// socket is same-origin with the running app, not the API host: prefer an
|
|
61
|
-
// explicit appBaseUrl, then the browser origin, then fall back to serverUrl
|
|
62
|
-
// (Node/SSR, where there's no window). Convert https:// → wss:// (http → ws)
|
|
63
|
-
// and strip the trailing slash.
|
|
64
|
-
const resolvedActorsWsUrl = (() => {
|
|
65
|
-
var _a, _b;
|
|
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
|
-
})();
|
|
76
58
|
const socketConfig = {
|
|
77
59
|
serverUrl,
|
|
78
60
|
mountPath: "/ws-user-apps/socket.io/",
|
|
@@ -142,6 +124,14 @@ export function createClient(config) {
|
|
|
142
124
|
userAuthModule.setToken(accessToken);
|
|
143
125
|
}
|
|
144
126
|
}
|
|
127
|
+
const actorsModule = createActorsModule({
|
|
128
|
+
appId,
|
|
129
|
+
// serverUrl is often relative/empty (same-origin app); PartySocket needs an
|
|
130
|
+
// absolute host, so fall back to the page origin.
|
|
131
|
+
host: resolveActorsHost(serverUrl, typeof window !== "undefined" ? (_a = window.location) === null || _a === void 0 ? void 0 : _a.origin : undefined),
|
|
132
|
+
functionsVersion,
|
|
133
|
+
getAuthToken: () => token || getAccessToken(),
|
|
134
|
+
});
|
|
145
135
|
const userModules = {
|
|
146
136
|
entities: createEntitiesModule({
|
|
147
137
|
axios: axiosClient,
|
|
@@ -161,7 +151,7 @@ export function createClient(config) {
|
|
|
161
151
|
}
|
|
162
152
|
return headers;
|
|
163
153
|
},
|
|
164
|
-
baseURL: (
|
|
154
|
+
baseURL: (_b = functionsAxiosClient.defaults) === null || _b === void 0 ? void 0 : _b.baseURL,
|
|
165
155
|
}),
|
|
166
156
|
agents: createAgentsModule({
|
|
167
157
|
axios: axiosClient,
|
|
@@ -179,14 +169,10 @@ export function createClient(config) {
|
|
|
179
169
|
appId,
|
|
180
170
|
userAuthModule,
|
|
181
171
|
}),
|
|
182
|
-
actors:
|
|
183
|
-
appId,
|
|
184
|
-
actorsWsUrl: resolvedActorsWsUrl,
|
|
185
|
-
functionsVersion,
|
|
186
|
-
getAuthToken: () => token || getAccessToken(),
|
|
187
|
-
}),
|
|
172
|
+
actors: actorsModule.module,
|
|
188
173
|
cleanup: () => {
|
|
189
174
|
userModules.analytics.cleanup();
|
|
175
|
+
actorsModule.closeAll();
|
|
190
176
|
if (socket) {
|
|
191
177
|
socket.disconnect();
|
|
192
178
|
}
|
|
@@ -210,7 +196,7 @@ export function createClient(config) {
|
|
|
210
196
|
}
|
|
211
197
|
return headers;
|
|
212
198
|
},
|
|
213
|
-
baseURL: (
|
|
199
|
+
baseURL: (_c = serviceRoleFunctionsAxiosClient.defaults) === null || _c === void 0 ? void 0 : _c.baseURL,
|
|
214
200
|
}),
|
|
215
201
|
agents: createAgentsModule({
|
|
216
202
|
axios: serviceRoleAxiosClient,
|
package/dist/client.types.d.ts
CHANGED
|
@@ -74,16 +74,6 @@ export interface CreateClientConfig {
|
|
|
74
74
|
* Additional client options.
|
|
75
75
|
*/
|
|
76
76
|
options?: CreateClientOptions;
|
|
77
|
-
/**
|
|
78
|
-
* Base WebSocket URL for Actor connections.
|
|
79
|
-
*
|
|
80
|
-
* Defaults to the app's own origin (`appBaseUrl`, else the browser's
|
|
81
|
-
* `window.location.origin`, else `serverUrl`) with `https://` replaced by
|
|
82
|
-
* `wss://` (or `http://` by `ws://`) — so the Actor socket is same-origin
|
|
83
|
-
* with the running app, which proxies `/parties` to the backend dispatcher.
|
|
84
|
-
* Override only when the Actor host differs from the app origin.
|
|
85
|
-
*/
|
|
86
|
-
actorsWsUrl?: string;
|
|
87
77
|
}
|
|
88
78
|
/**
|
|
89
79
|
* The Base44 client instance.
|
package/dist/modules/actors.d.ts
CHANGED
|
@@ -7,7 +7,19 @@ interface ActorsConfig {
|
|
|
7
7
|
/** Same semantics as function calls: editors with a non-prod version get the
|
|
8
8
|
* draft actor script; everyone else gets the published one. */
|
|
9
9
|
functionsVersion?: string;
|
|
10
|
-
|
|
10
|
+
/** Absolute host PartySocket dials (it strips the scheme and connects wss, ws
|
|
11
|
+
* for localhost). Resolved by {@link resolveActorsHost}. */
|
|
12
|
+
host: string;
|
|
11
13
|
}
|
|
12
|
-
|
|
14
|
+
/**
|
|
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).
|
|
19
|
+
*/
|
|
20
|
+
export declare function resolveActorsHost(serverUrl: string, browserOrigin?: string): string;
|
|
21
|
+
export declare function createActorsModule(config: ActorsConfig): {
|
|
22
|
+
module: Record<string, (instanceId: string) => ActorRoom>;
|
|
23
|
+
closeAll: () => void;
|
|
24
|
+
};
|
|
13
25
|
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;
|
|
@@ -27,7 +28,7 @@ class Room {
|
|
|
27
28
|
const connId = (_a = options === null || options === void 0 ? void 0 : options.id) !== null && _a !== void 0 ? _a : crypto.randomUUID();
|
|
28
29
|
this.connId = connId;
|
|
29
30
|
const ws = new PartySocket({
|
|
30
|
-
host: this.config.
|
|
31
|
+
host: this.config.host,
|
|
31
32
|
party: this.actorName,
|
|
32
33
|
room: this.instanceId,
|
|
33
34
|
id: connId,
|
|
@@ -94,7 +95,7 @@ class Room {
|
|
|
94
95
|
this.ws.send(JSON.stringify(data));
|
|
95
96
|
}
|
|
96
97
|
close() {
|
|
97
|
-
var _a;
|
|
98
|
+
var _a, _b;
|
|
98
99
|
if (this.heartbeat) {
|
|
99
100
|
clearInterval(this.heartbeat);
|
|
100
101
|
this.heartbeat = null;
|
|
@@ -102,12 +103,41 @@ class Room {
|
|
|
102
103
|
this.listeners.clear();
|
|
103
104
|
(_a = this.ws) === null || _a === void 0 ? void 0 : _a.close();
|
|
104
105
|
this.ws = null;
|
|
106
|
+
this.connId = null;
|
|
107
|
+
(_b = this.onClose) === null || _b === void 0 ? void 0 : _b.call(this);
|
|
105
108
|
}
|
|
106
109
|
}
|
|
110
|
+
/**
|
|
111
|
+
* Absolute host for the actor WebSocket. PartySocket needs an absolute host and
|
|
112
|
+
* can't resolve a relative/empty `serverUrl` (same-origin apps use a relative
|
|
113
|
+
* `/api`, so `serverUrl` is often `""`), so fall back to the page origin.
|
|
114
|
+
* PartySocket handles the scheme (https→wss, ws for localhost).
|
|
115
|
+
*/
|
|
116
|
+
export function resolveActorsHost(serverUrl, browserOrigin) {
|
|
117
|
+
return serverUrl && !serverUrl.startsWith("/") ? serverUrl : browserOrigin !== null && browserOrigin !== void 0 ? browserOrigin : serverUrl;
|
|
118
|
+
}
|
|
107
119
|
export function createActorsModule(config) {
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
120
|
+
// Live rooms this client opened, so client.cleanup() can reclaim any the app
|
|
121
|
+
// forgot to close() (each room removes itself here on close).
|
|
122
|
+
const rooms = new Set();
|
|
123
|
+
const module = new Proxy({}, {
|
|
124
|
+
get(_, key) {
|
|
125
|
+
// Symbols and `then` resolve to undefined (so the module isn't mistaken
|
|
126
|
+
// for a thenable when awaited); any string key is an actor name.
|
|
127
|
+
if (typeof key !== "string" || key === "then")
|
|
128
|
+
return undefined;
|
|
129
|
+
return (instanceId) => {
|
|
130
|
+
const room = new Room(key, instanceId, config, () => rooms.delete(room));
|
|
131
|
+
rooms.add(room);
|
|
132
|
+
return room;
|
|
133
|
+
};
|
|
111
134
|
},
|
|
112
135
|
});
|
|
136
|
+
return {
|
|
137
|
+
module,
|
|
138
|
+
closeAll: () => {
|
|
139
|
+
for (const room of [...rooms])
|
|
140
|
+
room.close();
|
|
141
|
+
},
|
|
142
|
+
};
|
|
113
143
|
}
|
|
@@ -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;
|