@base44-preview/sdk 0.8.46-pr.273.f546cdd → 0.8.46-pr.274.c9536b0
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 -7
- package/dist/actor.js +6 -6
- package/dist/client.js +1 -1
- package/dist/client.types.d.ts +2 -2
- package/dist/modules/actors.d.ts +1 -1
- package/dist/modules/actors.js +5 -5
- package/dist/modules/actors.types.d.ts +24 -152
- package/dist/modules/analytics.js +2 -2
- package/dist/modules/app.types.d.ts +4 -4
- package/dist/modules/auth.js +1 -1
- package/dist/modules/auth.types.d.ts +2 -2
- package/dist/modules/connectors.js +2 -2
- package/dist/modules/connectors.types.d.ts +4 -4
- package/dist/modules/entities.js +1 -1
- package/dist/utils/common.js +1 -1
- package/package.json +1 -1
package/dist/actor.d.ts
CHANGED
|
@@ -6,12 +6,12 @@
|
|
|
6
6
|
* export class MyActor extends Actor { ... }
|
|
7
7
|
*
|
|
8
8
|
* At deploy time the bundler replaces this import with the compiled
|
|
9
|
-
* Cloudflare Durable Object implementation
|
|
9
|
+
* Cloudflare Durable Object implementation — this file provides types only.
|
|
10
10
|
*/
|
|
11
11
|
import type { Base44Client } from "./client";
|
|
12
12
|
/**
|
|
13
13
|
* A single client connection. `Send` is the message type this connection accepts
|
|
14
|
-
* via {@link send}
|
|
14
|
+
* via {@link send} — the actor's *outgoing* (server→client) messages.
|
|
15
15
|
*/
|
|
16
16
|
export interface Conn<Send = unknown> {
|
|
17
17
|
/** Unique per-connection id (one per socket/tab), the same value the client
|
|
@@ -33,9 +33,9 @@ export interface Storage {
|
|
|
33
33
|
* Base class for an Actor.
|
|
34
34
|
*
|
|
35
35
|
* @typeParam Incoming - messages this actor *receives* from clients
|
|
36
|
-
* (`handleMessage`'s `msg`)
|
|
36
|
+
* (`handleMessage`'s `msg`) — the schema's `toServer` section.
|
|
37
37
|
* @typeParam Outgoing - messages this actor *sends* to clients
|
|
38
|
-
* (`conn.send`/`broadcast`)
|
|
38
|
+
* (`conn.send`/`broadcast`) — the schema's `toClient` section.
|
|
39
39
|
*
|
|
40
40
|
* With a generated `schema.jsonc`, wire both from the registry so they can't drift
|
|
41
41
|
* from the client's types:
|
|
@@ -51,7 +51,7 @@ export declare abstract class Actor<Incoming = unknown, Outgoing = unknown> {
|
|
|
51
51
|
abstract handleTick(): void | Promise<void>;
|
|
52
52
|
/**
|
|
53
53
|
* Optional wake hook: runs once when the instance starts, before any
|
|
54
|
-
* connection is handled
|
|
54
|
+
* connection is handled — safe to load persisted state here.
|
|
55
55
|
*/
|
|
56
56
|
handleStart(): void | Promise<void>;
|
|
57
57
|
/**
|
|
@@ -71,7 +71,7 @@ export declare abstract class Actor<Incoming = unknown, Outgoing = unknown> {
|
|
|
71
71
|
/**
|
|
72
72
|
* Managed ticker (opt-in). Override {@link shouldTick} and the platform runs
|
|
73
73
|
* {@link handleTick} on a timer of {@link tickIntervalMs} while it returns true,
|
|
74
|
-
* and stops (letting the Durable Object hibernate
|
|
74
|
+
* and stops (letting the Durable Object hibernate — no compute cost) when it
|
|
75
75
|
* returns false. The platform owns scheduling, rescheduling, self-heal, and
|
|
76
76
|
* error-safety.
|
|
77
77
|
*
|
|
@@ -85,7 +85,7 @@ export declare abstract class Actor<Incoming = unknown, Outgoing = unknown> {
|
|
|
85
85
|
protected get instanceId(): string;
|
|
86
86
|
protected get storage(): Storage;
|
|
87
87
|
/**
|
|
88
|
-
* Anonymous Base44 client scoped to this actor instance
|
|
88
|
+
* Anonymous Base44 client scoped to this actor instance — no user or service
|
|
89
89
|
* auth, so entity access is RLS-gated (same as a logged-out visitor). Always
|
|
90
90
|
* operates on production data: an actor runs server-side with no per-connection
|
|
91
91
|
* identity, so a Test DB preview selected in the editor does not apply here.
|
package/dist/actor.js
CHANGED
|
@@ -6,15 +6,15 @@
|
|
|
6
6
|
* export class MyActor extends Actor { ... }
|
|
7
7
|
*
|
|
8
8
|
* At deploy time the bundler replaces this import with the compiled
|
|
9
|
-
* Cloudflare Durable Object implementation
|
|
9
|
+
* Cloudflare Durable Object implementation — this file provides types only.
|
|
10
10
|
*/
|
|
11
11
|
/**
|
|
12
12
|
* Base class for an Actor.
|
|
13
13
|
*
|
|
14
14
|
* @typeParam Incoming - messages this actor *receives* from clients
|
|
15
|
-
* (`handleMessage`'s `msg`)
|
|
15
|
+
* (`handleMessage`'s `msg`) — the schema's `toServer` section.
|
|
16
16
|
* @typeParam Outgoing - messages this actor *sends* to clients
|
|
17
|
-
* (`conn.send`/`broadcast`)
|
|
17
|
+
* (`conn.send`/`broadcast`) — the schema's `toClient` section.
|
|
18
18
|
*
|
|
19
19
|
* With a generated `schema.jsonc`, wire both from the registry so they can't drift
|
|
20
20
|
* from the client's types:
|
|
@@ -28,7 +28,7 @@ export class Actor {
|
|
|
28
28
|
/**
|
|
29
29
|
* Managed ticker (opt-in). Override {@link shouldTick} and the platform runs
|
|
30
30
|
* {@link handleTick} on a timer of {@link tickIntervalMs} while it returns true,
|
|
31
|
-
* and stops (letting the Durable Object hibernate
|
|
31
|
+
* and stops (letting the Durable Object hibernate — no compute cost) when it
|
|
32
32
|
* returns false. The platform owns scheduling, rescheduling, self-heal, and
|
|
33
33
|
* error-safety.
|
|
34
34
|
*
|
|
@@ -39,7 +39,7 @@ export class Actor {
|
|
|
39
39
|
}
|
|
40
40
|
/**
|
|
41
41
|
* Optional wake hook: runs once when the instance starts, before any
|
|
42
|
-
* connection is handled
|
|
42
|
+
* connection is handled — safe to load persisted state here.
|
|
43
43
|
*/
|
|
44
44
|
handleStart() { }
|
|
45
45
|
/**
|
|
@@ -73,7 +73,7 @@ export class Actor {
|
|
|
73
73
|
throw new Error("Actor.storage is only available inside a deployed actor");
|
|
74
74
|
}
|
|
75
75
|
/**
|
|
76
|
-
* Anonymous Base44 client scoped to this actor instance
|
|
76
|
+
* Anonymous Base44 client scoped to this actor instance — no user or service
|
|
77
77
|
* auth, so entity access is RLS-gated (same as a logged-out visitor). Always
|
|
78
78
|
* operates on production data: an actor runs server-side with no per-connection
|
|
79
79
|
* identity, so a Test DB preview selected in the editor does not apply here.
|
package/dist/client.js
CHANGED
|
@@ -113,7 +113,7 @@ export function createClient(config) {
|
|
|
113
113
|
});
|
|
114
114
|
// Dedicated client for actor connection-token mints: no onError (a legacy
|
|
115
115
|
// actor answers every mint with an expected 409 before the proxy fallback,
|
|
116
|
-
// which must not reach the app's error handler
|
|
116
|
+
// which must not reach the app's error handler — the actors module forwards
|
|
117
117
|
// genuine failures itself via onMintError) and no constructor token
|
|
118
118
|
// (auth is per-request so a login/logout is picked up on every reconnect).
|
|
119
119
|
const actorsAxiosClient = createAxiosClient({
|
package/dist/client.types.d.ts
CHANGED
|
@@ -18,14 +18,14 @@ export interface CreateClientOptions {
|
|
|
18
18
|
* Optional error handler that will be called whenever an API error occurs.
|
|
19
19
|
*
|
|
20
20
|
* Also receives {@link ActorsModule | actors} connection failures. Errors
|
|
21
|
-
* are usually {@linkcode Base44Error} instances
|
|
21
|
+
* are usually {@linkcode Base44Error} instances — check `error.status`.
|
|
22
22
|
*/
|
|
23
23
|
onError?: (error: Error) => void;
|
|
24
24
|
/**
|
|
25
25
|
* Forces the actors transport. `"auto"` (default) connects directly to the
|
|
26
26
|
* actor and falls back to the platform proxy when the app's actors don't
|
|
27
27
|
* support direct connections; `"proxy"` always uses the platform proxy
|
|
28
|
-
* (ops rollback
|
|
28
|
+
* (ops rollback — no connection-token calls); `"direct"` disables the
|
|
29
29
|
* fallback (validation environments).
|
|
30
30
|
* @internal
|
|
31
31
|
*/
|
package/dist/modules/actors.d.ts
CHANGED
|
@@ -35,7 +35,7 @@ interface ActorsConfig {
|
|
|
35
35
|
* The legacy platform-proxy URL, byte-for-byte what PartySocket built before
|
|
36
36
|
* the direct path existed: same scheme swap (including its localhost-needs-a-
|
|
37
37
|
* port quirk), case-preserved party segment, `_pk` first in the query. The
|
|
38
|
-
* `handler` param is load-bearing
|
|
38
|
+
* `handler` param is load-bearing — the proxy reads it for the actor name.
|
|
39
39
|
*/
|
|
40
40
|
export declare function buildProxyActorUrl(rawHost: string, actorName: string, instanceId: string, connectionId: string, appId: string, token: string | null | undefined, functionsVersion?: string): string;
|
|
41
41
|
/**
|
package/dist/modules/actors.js
CHANGED
|
@@ -8,12 +8,12 @@ const DEAD_MS = 3000;
|
|
|
8
8
|
// 422 = no principal (e.g. anonymous outside a browser) or an id/room only the
|
|
9
9
|
// proxy's looser validation accepts, 405 = a backend that predates the mint
|
|
10
10
|
// endpoint (its actor deploy routes catch the path via `{handler_name:path}`
|
|
11
|
-
// but not the POST method
|
|
11
|
+
// but not the POST method — and the real endpoint never 405s a POST). The
|
|
12
12
|
// proxy serves migrated actors too, so falling back is always safe.
|
|
13
13
|
const PROXY_FALLBACK_STATUSES = new Set([405, 409, 422, 503]);
|
|
14
14
|
// Mint responses no retry can fix (bad request / forbidden / not found): the
|
|
15
15
|
// connection closes instead of re-minting forever; a fresh connect() re-probes.
|
|
16
|
-
// 401 is deliberately absent
|
|
16
|
+
// 401 is deliberately absent — the auth token is re-read on every attempt, so a
|
|
17
17
|
// login recovers on the next retry. Disjoint from PROXY_FALLBACK_STATUSES.
|
|
18
18
|
const TERMINAL_MINT_STATUSES = new Set([400, 403, 404]);
|
|
19
19
|
/** The mint's rejection can be anything; a `Base44Error` carries a numeric
|
|
@@ -29,7 +29,7 @@ function toError(err) {
|
|
|
29
29
|
}
|
|
30
30
|
/**
|
|
31
31
|
* A live connection to an actor instance. Only obtainable from
|
|
32
|
-
* {@link ActorRef.connect}, so `subscribe`/`send` are always valid
|
|
32
|
+
* {@link ActorRef.connect}, so `subscribe`/`send` are always valid — the socket
|
|
33
33
|
* exists for this object's whole lifetime.
|
|
34
34
|
*/
|
|
35
35
|
class Connection {
|
|
@@ -44,7 +44,7 @@ class Connection {
|
|
|
44
44
|
// mint answers with a fallback status the choice is sticky for this
|
|
45
45
|
// socket's lifetime (a fresh connect() after close() probes direct again,
|
|
46
46
|
// picking up actors migrated in the meantime). Any other mint failure
|
|
47
|
-
// rejects, which ReconnectingWebSocket retries with backoff
|
|
47
|
+
// rejects, which ReconnectingWebSocket retries with backoff — except the
|
|
48
48
|
// terminal statuses, which close this connection for good.
|
|
49
49
|
let useProxy = config.transport === "proxy";
|
|
50
50
|
const urlProvider = async () => {
|
|
@@ -172,7 +172,7 @@ function makeActorRef(actorName, instanceId, config, connections) {
|
|
|
172
172
|
* The legacy platform-proxy URL, byte-for-byte what PartySocket built before
|
|
173
173
|
* the direct path existed: same scheme swap (including its localhost-needs-a-
|
|
174
174
|
* port quirk), case-preserved party segment, `_pk` first in the query. The
|
|
175
|
-
* `handler` param is load-bearing
|
|
175
|
+
* `handler` param is load-bearing — the proxy reads it for the actor name.
|
|
176
176
|
*/
|
|
177
177
|
export function buildProxyActorUrl(rawHost, actorName, instanceId, connectionId, appId, token, functionsVersion) {
|
|
178
178
|
let host = rawHost.replace(/^(http|https|ws|wss):\/\//, "");
|
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
*
|
|
8
8
|
* @example
|
|
9
9
|
* ```typescript
|
|
10
|
-
* // Declare message types for a deployed actor
|
|
11
10
|
* declare module "@base44/sdk" {
|
|
12
11
|
* interface ActorRegistry {
|
|
13
12
|
* ChatRoom: {
|
|
@@ -22,7 +21,7 @@ export interface ActorRegistry {
|
|
|
22
21
|
}
|
|
23
22
|
/**
|
|
24
23
|
* Auto-populated by `base44 types generate` with the names of your deployed actors.
|
|
25
|
-
* Do not edit this interface manually
|
|
24
|
+
* Do not edit this interface manually — use {@link ActorRegistry} for message types.
|
|
26
25
|
*/
|
|
27
26
|
export interface ActorNameRegistry {
|
|
28
27
|
}
|
|
@@ -36,136 +35,55 @@ type ToServerFor<N extends string> = N extends keyof ActorRegistry ? ActorRegist
|
|
|
36
35
|
/** Options for {@link ActorRef.connect}. */
|
|
37
36
|
export interface ActorConnectOptions {
|
|
38
37
|
/**
|
|
39
|
-
* The connection id
|
|
40
|
-
*
|
|
41
|
-
* identity
|
|
38
|
+
* The connection id — becomes the actor's `conn.id`. Supply a stable value
|
|
39
|
+
* (e.g. persisted per tab) so a reconnect reuses the same server-side
|
|
40
|
+
* identity; omit for an auto-generated per-connection id.
|
|
42
41
|
*/
|
|
43
42
|
id?: string;
|
|
44
43
|
}
|
|
45
44
|
/** Handle for one listener registered via {@link Connection.subscribe}. */
|
|
46
45
|
export interface ActorSubscription {
|
|
47
|
-
/**
|
|
48
|
-
* Removes this listener. Other listeners on the same connection, and the
|
|
49
|
-
* connection itself, stay live. To close the connection as well, call
|
|
50
|
-
* {@link Connection.close}.
|
|
51
|
-
*
|
|
52
|
-
* @example
|
|
53
|
-
* ```typescript
|
|
54
|
-
* // Stop listening without closing the connection
|
|
55
|
-
* const sub = conn.subscribe((msg) => console.log(msg));
|
|
56
|
-
* sub.unsubscribe();
|
|
57
|
-
* ```
|
|
58
|
-
*/
|
|
46
|
+
/** Remove this listener; other listeners and the socket stay live. */
|
|
59
47
|
unsubscribe(): void;
|
|
60
48
|
}
|
|
61
49
|
/**
|
|
62
50
|
* A live connection to an actor instance, returned by {@link ActorRef.connect}.
|
|
63
|
-
* `subscribe`/`send` are always valid
|
|
51
|
+
* `subscribe`/`send` are always valid — you only get a `Connection` once the
|
|
64
52
|
* socket has been opened, so there's no pre-connect state to guard against.
|
|
65
53
|
*/
|
|
66
54
|
export interface Connection<N extends string = string> {
|
|
67
|
-
/** The connection id
|
|
55
|
+
/** The connection id (the value the actor sees as `conn.id`). */
|
|
68
56
|
readonly id: string;
|
|
69
|
-
/**
|
|
70
|
-
* Registers a listener for messages sent by the actor. Any number of
|
|
71
|
-
* listeners can be registered on one connection, and each receives every
|
|
72
|
-
* message.
|
|
73
|
-
*
|
|
74
|
-
* The callback payload is typed when the actor is declared in
|
|
75
|
-
* {@link ActorRegistry}, and is `unknown` otherwise.
|
|
76
|
-
*
|
|
77
|
-
* @param callback - Called with each message the actor sends to this client.
|
|
78
|
-
* @returns An {@link ActorSubscription} that removes this one listener.
|
|
79
|
-
*
|
|
80
|
-
* @example
|
|
81
|
-
* ```typescript
|
|
82
|
-
* // Listen for messages from the actor
|
|
83
|
-
* const sub = conn.subscribe((msg) => {
|
|
84
|
-
* if (msg.type === "message") console.log(msg.text);
|
|
85
|
-
* });
|
|
86
|
-
* ```
|
|
87
|
-
*/
|
|
57
|
+
/** Register a message listener. Multiple are allowed; returns a per-listener unsubscribe. */
|
|
88
58
|
subscribe(callback: (data: ToClientFor<N>) => void): ActorSubscription;
|
|
89
|
-
/**
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
-
* Messages sent before the socket finishes opening are buffered and flushed
|
|
93
|
-
* on open. Messages sent after {@link close} are dropped silently.
|
|
94
|
-
*
|
|
95
|
-
* The payload is typed when the actor is declared in {@link ActorRegistry},
|
|
96
|
-
* and is `unknown` otherwise.
|
|
97
|
-
*
|
|
98
|
-
* @param data - The message to send to the actor.
|
|
99
|
-
*
|
|
100
|
-
* @example
|
|
101
|
-
* ```typescript
|
|
102
|
-
* // Send a message to the actor
|
|
103
|
-
* conn.send({ type: "message", text: "hi" });
|
|
104
|
-
* ```
|
|
105
|
-
*/
|
|
59
|
+
/** Send a message. Buffered by the socket until it's open; dropped after
|
|
60
|
+
* {@link close}. */
|
|
106
61
|
send(data: ToServerFor<N>): void;
|
|
107
62
|
/**
|
|
108
|
-
*
|
|
109
|
-
*
|
|
110
|
-
*
|
|
111
|
-
* A connection also closes itself when it fails permanently. See
|
|
112
|
-
* {@link ActorRef.connect} for how to recover from that.
|
|
113
|
-
*
|
|
114
|
-
* @example
|
|
115
|
-
* ```typescript
|
|
116
|
-
* // Close when the view that opened the connection goes away.
|
|
117
|
-
* useEffect(() => {
|
|
118
|
-
* const conn = base44.actors.ChatRoom(roomId).connect();
|
|
119
|
-
* conn.subscribe(setMessage);
|
|
120
|
-
* return () => conn.close();
|
|
121
|
-
* }, [roomId]);
|
|
122
|
-
* ```
|
|
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}.
|
|
123
66
|
*/
|
|
124
67
|
close(): void;
|
|
125
68
|
}
|
|
126
69
|
/**
|
|
127
|
-
* A handle to one actor instance
|
|
70
|
+
* A handle to one actor instance — `base44.actors.MyActor(id)`. Call
|
|
128
71
|
* {@link connect} to open the socket and get a {@link Connection}.
|
|
129
72
|
*/
|
|
130
73
|
export interface ActorRef<N extends string = string> {
|
|
131
74
|
/**
|
|
132
|
-
*
|
|
133
|
-
*
|
|
134
|
-
* again returns the same connection rather than opening a second socket.
|
|
135
|
-
*
|
|
136
|
-
* The returned connection is usable straight away. Messages passed to
|
|
137
|
-
* {@link Connection.send} before the socket finishes opening are buffered and
|
|
138
|
-
* flushed on open.
|
|
139
|
-
*
|
|
140
|
-
* A connection that fails permanently, for example because the actor doesn't
|
|
141
|
-
* exist or the caller isn't allowed to connect, closes itself and reports the
|
|
142
|
-
* error to the client's `onError` handler. Call `connect()` again once the
|
|
143
|
-
* cause is fixed to get a fresh {@link Connection}, then re-subscribe, as
|
|
144
|
-
* listeners do not carry over.
|
|
145
|
-
*
|
|
146
|
-
* @param options - Connection options. See {@link ActorConnectOptions}.
|
|
147
|
-
* @returns A live {@link Connection} to this actor instance.
|
|
148
|
-
*
|
|
149
|
-
* @example
|
|
150
|
-
* ```typescript
|
|
151
|
-
* // Connect to an actor instance
|
|
152
|
-
* const conn = base44.actors.ChatRoom("room-1").connect();
|
|
153
|
-
* ```
|
|
154
|
-
*
|
|
155
|
-
* @example
|
|
156
|
-
* ```typescript
|
|
157
|
-
* // Reuse a stable connection id so a reconnect keeps the same
|
|
158
|
-
* // server-side identity.
|
|
159
|
-
* let id = sessionStorage.getItem("chat-conn-id") ?? crypto.randomUUID();
|
|
160
|
-
* sessionStorage.setItem("chat-conn-id", id);
|
|
75
|
+
* Open the WebSocket and return the {@link Connection}. Idempotent while the
|
|
76
|
+
* connection is open.
|
|
161
77
|
*
|
|
162
|
-
*
|
|
163
|
-
*
|
|
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.
|
|
164
82
|
*/
|
|
165
83
|
connect(options?: ActorConnectOptions): Connection<N>;
|
|
166
84
|
}
|
|
167
85
|
/**
|
|
168
|
-
* Client for a single named Actor
|
|
86
|
+
* Client for a single named Actor — call it with an instance id to get an
|
|
169
87
|
* {@link ActorRef}. Typed automatically when the actor is registered in
|
|
170
88
|
* {@link ActorRegistry}.
|
|
171
89
|
*/
|
|
@@ -173,62 +91,16 @@ export interface ActorClient<N extends string = string> {
|
|
|
173
91
|
(instanceId: string): ActorRef<N>;
|
|
174
92
|
}
|
|
175
93
|
/**
|
|
176
|
-
*
|
|
94
|
+
* The actors module provides access to Cloudflare Durable Object-backed
|
|
177
95
|
* Actors deployed by the Base44 platform.
|
|
178
96
|
*
|
|
179
|
-
* An Actor is a named server-side object with persistent state. Each instance
|
|
180
|
-
* is addressed by an id, so `base44.actors.ChatRoom("room-1")` and
|
|
181
|
-
* `base44.actors.ChatRoom("room-2")` are separate instances with separate
|
|
182
|
-
* state. Clients open a WebSocket to an instance and exchange messages with it.
|
|
183
|
-
*
|
|
184
|
-
* This module provides:
|
|
185
|
-
* - Per-instance WebSocket connections, opened with {@link ActorRef.connect}
|
|
186
|
-
* - Message listeners, registered with {@link Connection.subscribe}
|
|
187
|
-
* - Message sending, with {@link Connection.send}
|
|
188
|
-
* - Automatic reconnection with backoff, including recovery from half-open
|
|
189
|
-
* sockets that stop delivering messages without emitting a close event
|
|
190
|
-
* - End-to-end typing of message payloads through {@link ActorRegistry}
|
|
191
|
-
*
|
|
192
|
-
* This module is available to use with a client in anonymous and user
|
|
193
|
-
* authentication modes. Connecting anonymously requires a browser environment.
|
|
194
|
-
*
|
|
195
|
-
* Connections stay open until you call {@link Connection.close}, so close them
|
|
196
|
-
* when the view that opened them goes away.
|
|
197
|
-
*
|
|
198
|
-
* @example
|
|
199
97
|
* ```typescript
|
|
200
|
-
*
|
|
201
|
-
* const
|
|
202
|
-
*
|
|
203
|
-
* const sub = conn.subscribe((msg) => {
|
|
204
|
-
* console.log(msg);
|
|
205
|
-
* });
|
|
206
|
-
*
|
|
98
|
+
* const conn = base44.actors.MyActor("room-1").connect();
|
|
99
|
+
* const sub = conn.subscribe((msg) => console.log(msg)); // typed via ActorRegistry
|
|
207
100
|
* conn.send({ type: "message", text: "hi" });
|
|
208
|
-
*
|
|
209
|
-
* // Later, when the view goes away.
|
|
210
101
|
* sub.unsubscribe();
|
|
211
102
|
* conn.close();
|
|
212
103
|
* ```
|
|
213
|
-
*
|
|
214
|
-
* @example
|
|
215
|
-
* ```typescript
|
|
216
|
-
* // Register the actor to type both directions of the conversation.
|
|
217
|
-
* declare module "@base44/sdk" {
|
|
218
|
-
* interface ActorRegistry {
|
|
219
|
-
* ChatRoom: {
|
|
220
|
-
* toClient: { type: "joined" | "message"; from?: string; text?: string };
|
|
221
|
-
* toServer: { type: "message"; text: string };
|
|
222
|
-
* };
|
|
223
|
-
* }
|
|
224
|
-
* }
|
|
225
|
-
*
|
|
226
|
-
* const conn = base44.actors.ChatRoom("room-1").connect();
|
|
227
|
-
* conn.subscribe((msg) => {
|
|
228
|
-
* // msg is typed as the toClient union.
|
|
229
|
-
* if (msg.type === "message") console.log(msg.text);
|
|
230
|
-
* });
|
|
231
|
-
* ```
|
|
232
104
|
*/
|
|
233
105
|
export type ActorsModule = {
|
|
234
106
|
[K in AllActorNames]: K extends keyof ActorRegistry ? ActorClient<string & K> : ActorClient;
|
|
@@ -25,7 +25,7 @@ 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
|
|
28
|
+
// Memoized session id for when `localStorage` can't persist one — see
|
|
29
29
|
// getAnalyticsSessionId.
|
|
30
30
|
fallbackSessionId: null,
|
|
31
31
|
config: {
|
|
@@ -255,7 +255,7 @@ async function getSessionContext(userAuthModule) {
|
|
|
255
255
|
// With no token there is no identity to resolve: `me()` can only answer 401,
|
|
256
256
|
// which the browser logs to the console before any handler here sees it. On
|
|
257
257
|
// a public page that request is the sole reason an error appears, so skip
|
|
258
|
-
// it. This is not memoized
|
|
258
|
+
// it. This is not memoized — a visitor who logs in later must still resolve.
|
|
259
259
|
if (!userAuthModule.hasToken()) {
|
|
260
260
|
return { user_id: null, session_id: getAnalyticsSessionId() };
|
|
261
261
|
}
|
|
@@ -21,7 +21,7 @@ export interface AppPublicSettingsResponse {
|
|
|
21
21
|
* ## Authentication Modes
|
|
22
22
|
*
|
|
23
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
|
|
24
|
+
* client's token, when it has one, is sent with the request — a signed-in visitor
|
|
25
25
|
* who has no access to the app is reported differently from an anonymous one.
|
|
26
26
|
*/
|
|
27
27
|
export interface AppModule {
|
|
@@ -29,9 +29,9 @@ export interface AppModule {
|
|
|
29
29
|
* Get the app's public configuration.
|
|
30
30
|
*
|
|
31
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
|
|
33
|
-
*
|
|
34
|
-
*
|
|
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
35
|
*
|
|
36
36
|
* @returns Promise resolving to the app's ID and access policy.
|
|
37
37
|
*
|
package/dist/modules/auth.js
CHANGED
|
@@ -70,7 +70,7 @@ export function createAuthModule(axios, functionsAxiosClient, appId, options) {
|
|
|
70
70
|
// two identical GETs, so the second pays the first's full latency on every
|
|
71
71
|
// cold load.
|
|
72
72
|
//
|
|
73
|
-
// This shares the pending promise only
|
|
73
|
+
// This shares the pending promise only — it is cleared as soon as the request
|
|
74
74
|
// settles, so no resolved user is ever retained. Caching the user across
|
|
75
75
|
// requests would leave the app rendering a stale identity after logout or a
|
|
76
76
|
// session swap.
|
|
@@ -526,7 +526,7 @@ export interface AuthModule {
|
|
|
526
526
|
/**
|
|
527
527
|
* The auth module as constructed internally, before it is narrowed to
|
|
528
528
|
* {@link AuthModule} on the public client. Not exported from the package
|
|
529
|
-
* index
|
|
529
|
+
* index — SDK consumers see only {@link AuthModule}.
|
|
530
530
|
*
|
|
531
531
|
* @internal
|
|
532
532
|
*/
|
|
@@ -534,7 +534,7 @@ export interface InternalAuthModule extends AuthModule {
|
|
|
534
534
|
/**
|
|
535
535
|
* Whether an access token is currently set on the client.
|
|
536
536
|
*
|
|
537
|
-
* Reports only the presence of a token, never its validity
|
|
537
|
+
* Reports only the presence of a token, never its validity — an expired or
|
|
538
538
|
* revoked token still reads as `true`. Callers use this to skip requests that
|
|
539
539
|
* could not succeed without a session, not to decide that one is valid.
|
|
540
540
|
*/
|
|
@@ -93,8 +93,8 @@ function assertNonEmptyString(value, label) {
|
|
|
93
93
|
* POST a request to the connector proxy and normalize the response.
|
|
94
94
|
*
|
|
95
95
|
* The proxy reports upstream outcomes in the body rather than as HTTP status, so
|
|
96
|
-
* a provider 4xx/5xx arrives here as a resolved response with `success: false
|
|
97
|
-
*
|
|
96
|
+
* a provider 4xx/5xx arrives here as a resolved response with `success: false` —
|
|
97
|
+
* only Base44-side failures reject through the axios error interceptor.
|
|
98
98
|
*
|
|
99
99
|
* @internal
|
|
100
100
|
*/
|
|
@@ -87,7 +87,7 @@ export interface ConnectorApiResponse<T = unknown> {
|
|
|
87
87
|
status: number | null;
|
|
88
88
|
/**
|
|
89
89
|
* The parsed upstream response body, or proxy error details when no response
|
|
90
|
-
* was received.
|
|
90
|
+
* was received. `null` when the response was binary — see {@link dataBase64}.
|
|
91
91
|
*/
|
|
92
92
|
data: T | null;
|
|
93
93
|
/**
|
|
@@ -148,9 +148,9 @@ export interface ConnectorProxyRawResponse {
|
|
|
148
148
|
*
|
|
149
149
|
* ## Metered connectors
|
|
150
150
|
*
|
|
151
|
-
* A few [platform connectors](#shared-connectors) are backed by paid third-party APIs that charge Base44 per call. For those, the OAuth token is **not** available to your code
|
|
151
|
+
* A few [platform connectors](#shared-connectors) are backed by paid third-party APIs that charge Base44 per call. For those, the OAuth token is **not** available to your code — {@linkcode getConnection | getConnection()} rejects with a `403`. Call them with {@linkcode callApi | callApi()} instead: Base44 attaches the credential server-side, forwards the request, and bills your workspace's integration credits for the call.
|
|
152
152
|
*
|
|
153
|
-
* This applies to platform connectors only. A workspace-registered or app user connector runs on **your own** OAuth app, so the provider invoices you directly and there is nothing for Base44 to meter
|
|
153
|
+
* This applies to platform connectors only. A workspace-registered or app user connector runs on **your own** OAuth app, so the provider invoices you directly and there is nothing for Base44 to meter — those keep normal token access via {@linkcode getWorkspaceConnection | getWorkspaceConnection()} and {@linkcode getCurrentAppUserConnection | getCurrentAppUserConnection()}.
|
|
154
154
|
*
|
|
155
155
|
* Two things to keep in mind when writing against a metered connector:
|
|
156
156
|
*
|
|
@@ -422,7 +422,7 @@ export interface ConnectorsModule {
|
|
|
422
422
|
*
|
|
423
423
|
* @param integrationType - The type of integration, such as `'x'`. See [Available connectors](#available-connectors).
|
|
424
424
|
* @param request - The upstream request to forward. See {@link ConnectorApiRequest}.
|
|
425
|
-
* @returns Promise resolving to a {@link ConnectorApiResponse}. Note that an upstream error is reported in `success` and `status`, not thrown
|
|
425
|
+
* @returns Promise resolving to a {@link ConnectorApiResponse}. Note that an upstream error is reported in `success` and `status`, not thrown — only Base44-side failures reject.
|
|
426
426
|
*
|
|
427
427
|
* @example
|
|
428
428
|
* ```typescript
|
package/dist/modules/entities.js
CHANGED
|
@@ -143,7 +143,7 @@ function createEntityHandler(axios, appId, entityName, getSocket) {
|
|
|
143
143
|
// developer console so they know to fetch the full record on
|
|
144
144
|
// demand (e.g. a follow-up entities.X.get(id) call) instead of
|
|
145
145
|
// rendering the slimmed payload directly. Skip on delete events
|
|
146
|
-
//
|
|
146
|
+
// — the record no longer exists.
|
|
147
147
|
if (event.type !== "delete" && ((_a = event.data) === null || _a === void 0 ? void 0 : _a._oversize)) {
|
|
148
148
|
console.error(`[Base44 SDK] Realtime broadcast for ${entityName}#${event.id} was oversize and got slimmed for transport. ` +
|
|
149
149
|
`Fields >10 KB are empty and the rest of the record may be a stub. ` +
|
package/dist/utils/common.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export const isNode = typeof window === "undefined";
|
|
2
2
|
export const isInIFrame = !isNode && window.self !== window.top;
|
|
3
3
|
// React Native defines `window` (so `isNode` is false there) but not `document`.
|
|
4
|
-
// Browser-only code paths gated on `window`/`isNode` alone would run
|
|
4
|
+
// Browser-only code paths gated on `window`/`isNode` alone would run — and crash —
|
|
5
5
|
// on React Native. Node (no `window`) is already handled by those `window` guards;
|
|
6
6
|
// this flags the window-without-a-DOM case that isn't.
|
|
7
7
|
export const isReactNative = !isNode && typeof document === "undefined";
|