@rebasepro/types 0.20.1-canary.g4d882ca → 0.21.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.
@@ -88,7 +88,23 @@ export interface RebaseBackendAppConfig {
88
88
  * Default `Dockerfile`.
89
89
  */
90
90
  dockerfile?: string;
91
- /** `runtime: "custom"` only. Build context relative to the root. Default `.`. */
91
+ /**
92
+ * `runtime: "custom"` only. Directory handed to `docker build` as the build
93
+ * context, relative to the directory holding `rebase.json`. Default `.`.
94
+ *
95
+ * The one path in this file allowed to point **above** the project. Every
96
+ * other one names something Rebase reads, and those must be inside the
97
+ * project or a bundle cannot carry them; this names something Rebase never
98
+ * opens. In a workspace repository it normally has to be the workspace root
99
+ * (`".."`), because the lockfile and sibling packages a Dockerfile copies do
100
+ * not live beside `rebase.json`.
101
+ *
102
+ * {@link RebaseBackendAppConfig.dockerfile} stays relative to `rebase.json`
103
+ * whatever this is — it names a file in this repository, and moving the
104
+ * context should not rewrite it. `rebase build` re-expresses it against the
105
+ * context when it prints the command, because `docker build -f` resolves
106
+ * against the working directory rather than the context.
107
+ */
92
108
  context?: string;
93
109
  /** `runtime: "custom"` only. Port the container listens on. Default 8080. */
94
110
  port?: number;
@@ -109,6 +109,115 @@ export interface CollectionPatchMessage extends WebSocketMessage {
109
109
  /** See {@link WirePrimaryKeys}: how the subscriber finds {@link id} in its cache. */
110
110
  pks?: WirePrimaryKeys;
111
111
  }
112
+ /**
113
+ * A presence roster, keyed by the server's client id.
114
+ *
115
+ * The id is per socket rather than per user: the same person in two tabs is two
116
+ * entries, and a reconnect replaces an entry rather than updating it. What the
117
+ * values hold is entirely the application's — the server stores and echoes back
118
+ * whatever `presence_track` was given, and never reads into it.
119
+ */
120
+ export type PresenceState = Record<string, Record<string, unknown>>;
121
+ /**
122
+ * Server → client: a message broadcast into a channel.
123
+ *
124
+ * The body is `payload`, inherited from {@link WebSocketMessage} — the server
125
+ * passes it through untouched, so its shape is the application's business. The
126
+ * sender is never sent its own broadcast back.
127
+ */
128
+ export interface BroadcastMessage extends WebSocketMessage {
129
+ type: "broadcast";
130
+ channel: string;
131
+ /**
132
+ * The application-chosen event name. The only thing
133
+ * `channel.onBroadcast(event, …)` filters on; the server does not interpret
134
+ * it.
135
+ */
136
+ event: string;
137
+ /**
138
+ * Per-channel sequence number, present only on a channel the server has a
139
+ * retention rule for.
140
+ *
141
+ * Dense and monotonically increasing, so a client that remembers the last
142
+ * one it applied can name exactly where to resume from — see
143
+ * {@link ChannelHistoryMessage}. Absent on an ephemeral channel, where
144
+ * there is nothing to resume from and messages are delivered straight
145
+ * through.
146
+ */
147
+ seq?: number;
148
+ }
149
+ /**
150
+ * Server → client: the whole roster of a channel.
151
+ *
152
+ * Sent only in answer to a `presence_state` request. Joining does not push one,
153
+ * and a client that has just tracked itself is told only about its own join, so
154
+ * a client that waits for diffs alone believes it is the only one there until
155
+ * somebody else happens to move. This is why the SDK's `join()` asks for a
156
+ * roster rather than waiting to be given one.
157
+ */
158
+ export interface PresenceStateMessage extends WebSocketMessage {
159
+ type: "presence_state";
160
+ channel: string;
161
+ /**
162
+ * Everyone currently tracked, this client included. Empty for a channel
163
+ * nobody is tracking presence in — an answer, not an omission.
164
+ */
165
+ presences: PresenceState;
166
+ }
167
+ /**
168
+ * Server → client: what moved in a channel's roster.
169
+ *
170
+ * Carries only the movement, never the roster, so a receiver maintains its own
171
+ * copy by applying these to what it already had (which is why it needs a
172
+ * {@link PresenceStateMessage} to start from).
173
+ */
174
+ export interface PresenceDiffMessage extends WebSocketMessage {
175
+ type: "presence_diff";
176
+ channel: string;
177
+ /**
178
+ * Entries added or changed. A state update is a join over the same client
179
+ * id, since that is what a receiver has to do with it either way.
180
+ */
181
+ joins: PresenceState;
182
+ /**
183
+ * Entries removed — by `presence_untrack`, by a closed socket, or by the
184
+ * 30s expiry that reaps a client which stopped sending heartbeats.
185
+ *
186
+ * Keyed by client id like `joins`, and carrying each departing entry's last
187
+ * state rather than just its id: enough to say who left without having kept
188
+ * the roster.
189
+ */
190
+ leaves: PresenceState;
191
+ }
192
+ /**
193
+ * Server → client: a refusal about one channel.
194
+ *
195
+ * Channel frames are fire-and-forget — there is no pending request to reject
196
+ * and no subscription id to match — so a refused join, broadcast or history
197
+ * read is addressed by channel like any other channel frame. Without the
198
+ * `channel` field these fell through every branch of the client's message
199
+ * handler into a console warning, which is why it is the one thing that makes
200
+ * this a channel frame rather than a generic error.
201
+ *
202
+ * `type` is lowercase from the realtime service and uppercase from the socket
203
+ * gateway (auth, rate limiting). Both are sent; a client must accept both.
204
+ */
205
+ export interface ChannelErrorMessage extends WebSocketMessage {
206
+ type: "error" | "ERROR";
207
+ channel: string;
208
+ /**
209
+ * The refusal. `error` is a bare string when there is no code, and
210
+ * `{ message, code }` when there is — `CHANNEL_FORBIDDEN`, `RATE_LIMITED`,
211
+ * `CHANNEL_HISTORY_READ_FAILED` / `_WRITE_FAILED`,
212
+ * `CHANNEL_BUS_PAYLOAD_TOO_LARGE`.
213
+ *
214
+ * The channel is echoed inside the envelope as well as beside it, for a
215
+ * reader that has only the payload.
216
+ */
217
+ payload?: WebSocketErrorPayload & {
218
+ channel?: string;
219
+ };
220
+ }
112
221
  /**
113
222
  * One retained broadcast, as it travels on the wire.
114
223
  *
@@ -152,3 +261,14 @@ export interface ChannelHistoryMessage extends WebSocketMessage {
152
261
  */
153
262
  latestSeq?: number;
154
263
  }
264
+ /**
265
+ * Every frame routed by channel name rather than by `requestId` or
266
+ * `subscriptionId`.
267
+ *
268
+ * A discriminated union: each member fixes `type` to a literal, so a `switch`
269
+ * over a value of this type narrows to the member and its fields. Narrowing
270
+ * *into* it is the part that needs a predicate — a frame arrives as a
271
+ * {@link WebSocketMessage}, whose `type` is a bare `string`, and a `string`
272
+ * discriminates nothing.
273
+ */
274
+ export type ChannelMessage = BroadcastMessage | PresenceStateMessage | PresenceDiffMessage | ChannelHistoryMessage | ChannelErrorMessage;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rebasepro/types",
3
- "version": "0.20.1-canary.g4d882ca",
3
+ "version": "0.21.0",
4
4
  "description": "Rebase type definitions — shared interfaces and controller types",
5
5
  "keywords": [
6
6
  "rebase",