@rebasepro/types 0.20.0 → 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.
- package/dist/call_context.d.ts +23 -2
- package/dist/controllers/data_driver.d.ts +33 -0
- package/dist/errors.d.ts +0 -15
- package/dist/index.es.js +25 -22
- package/dist/index.es.js.map +1 -1
- package/dist/types/admin_block.d.ts +9 -4
- package/dist/types/project_manifest.d.ts +64 -3
- package/dist/types/websockets.d.ts +120 -0
- package/package.json +1 -1
|
@@ -81,10 +81,15 @@ export declare function nestAdminCollectionKeys(collection: Record<string, unkno
|
|
|
81
81
|
/**
|
|
82
82
|
* {@link nestAdminKeysOf} for a property, applied to its children too.
|
|
83
83
|
*
|
|
84
|
-
* A map property carries `properties`, an array property carries `of`, and
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
*
|
|
84
|
+
* A map property carries `properties`, an array property carries `of`, and an
|
|
85
|
+
* array of typed blocks carries `oneOf.properties` — a record of properties like
|
|
86
|
+
* a map's. All of them hold properties with `admin` blocks of their own. A flat
|
|
87
|
+
* `readOnly` left on a child is as dead — and as fatal at the next boot — as one
|
|
88
|
+
* left on the parent, so the walk goes all the way down.
|
|
89
|
+
*
|
|
90
|
+
* `oneOf` was the container this walk did not know about, and it is the one the
|
|
91
|
+
* block-based collection templates are built out of: every block inside them
|
|
92
|
+
* kept its flat `markdown`, and the collection they created would not boot.
|
|
88
93
|
*
|
|
89
94
|
* @group Models
|
|
90
95
|
*/
|
|
@@ -88,7 +88,23 @@ export interface RebaseBackendAppConfig {
|
|
|
88
88
|
* Default `Dockerfile`.
|
|
89
89
|
*/
|
|
90
90
|
dockerfile?: string;
|
|
91
|
-
/**
|
|
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;
|
|
@@ -124,6 +140,30 @@ export interface RebaseStaticAppConfig {
|
|
|
124
140
|
* static *site* generator emits real files for its routes anyway.
|
|
125
141
|
*/
|
|
126
142
|
spa?: boolean;
|
|
143
|
+
/**
|
|
144
|
+
* Where this app mounts the Rebase CMS, as a URL path — the address you
|
|
145
|
+
* would type to reach it, not a path relative to `path`.
|
|
146
|
+
*
|
|
147
|
+
* The CMS is an ordinary React component in the developer's own app
|
|
148
|
+
* (`<RebaseCMS basePath="/admin">`), so its address is a *client-side
|
|
149
|
+
* route*: nothing on the server, in the bundle, or in the control plane can
|
|
150
|
+
* observe it. A project whose CMS sits at `/admin` inside a frontend that
|
|
151
|
+
* also serves a product at `/` is indistinguishable, from the outside, from
|
|
152
|
+
* one that has no CMS at all — which is exactly how a Rebase Cloud project
|
|
153
|
+
* came to have no discoverable admin URL anywhere in its console.
|
|
154
|
+
*
|
|
155
|
+
* Declaring it is the only way that fact travels. It is carried into the
|
|
156
|
+
* bundle manifest, recorded on the project's app row at deploy, and is what
|
|
157
|
+
* lets the console (and `rebase apps list`) offer a link straight to it.
|
|
158
|
+
*
|
|
159
|
+
* Must be `path` itself or something beneath it, since the app serving that
|
|
160
|
+
* URL is the one that has to answer for it. Absent means this app does not
|
|
161
|
+
* mount the CMS — the common case for a marketing site or a product app.
|
|
162
|
+
*
|
|
163
|
+
* @example "/" — the whole app is the CMS, as `rebase init` scaffolds it
|
|
164
|
+
* @example "/admin" — the CMS is one route of a larger app
|
|
165
|
+
*/
|
|
166
|
+
cms?: string;
|
|
127
167
|
}
|
|
128
168
|
export type RebaseAppConfig = RebaseBackendAppConfig | RebaseStaticAppConfig;
|
|
129
169
|
/**
|
|
@@ -215,7 +255,7 @@ export interface RebaseProjectManifest {
|
|
|
215
255
|
* Repository-wide opt-out from anonymous CLI usage sharing.
|
|
216
256
|
*
|
|
217
257
|
* **Only `false` does anything.** It suppresses sharing for everyone who
|
|
218
|
-
* clones this repository, overriding each developer's own
|
|
258
|
+
* clones this repository, overriding each developer's own answer — an
|
|
219
259
|
* organisation setting policy for work done on its behalf, the same shape
|
|
220
260
|
* as a committed `.npmrc`.
|
|
221
261
|
*
|
|
@@ -223,7 +263,7 @@ export interface RebaseProjectManifest {
|
|
|
223
263
|
* quietly. This file is committed, so a `true` here would be one developer
|
|
224
264
|
* answering a privacy question for every colleague who later clones the
|
|
225
265
|
* repo — consent by proxy, which is the exact thing opt-in exists to
|
|
226
|
-
* prevent. Individuals
|
|
266
|
+
* prevent. Individuals answer at `rebase init`, or with `rebase telemetry enable` / `disable`.
|
|
227
267
|
*/
|
|
228
268
|
telemetry?: boolean;
|
|
229
269
|
}
|
|
@@ -341,6 +381,27 @@ export interface RebaseBundleStatic {
|
|
|
341
381
|
dir: string;
|
|
342
382
|
/** Serve `index.html` for unmatched paths under `path`. */
|
|
343
383
|
spa: boolean;
|
|
384
|
+
/**
|
|
385
|
+
* The app's name in `rebase.json`.
|
|
386
|
+
*
|
|
387
|
+
* `dir` is `static/<name>` and has been since folding was written, so this
|
|
388
|
+
* is recoverable by string surgery — which is precisely why it is stated
|
|
389
|
+
* instead. A control plane reconciling app rows against this list has to
|
|
390
|
+
* match them by name, and a consumer that has to re-derive an identifier
|
|
391
|
+
* from a path is one refactor away from matching nothing and registering a
|
|
392
|
+
* duplicate app on every deploy.
|
|
393
|
+
*
|
|
394
|
+
* Optional because bundles built before this field exists do not carry it;
|
|
395
|
+
* a reader that needs a name falls back to the last segment of `dir`.
|
|
396
|
+
*/
|
|
397
|
+
name?: string;
|
|
398
|
+
/**
|
|
399
|
+
* Where this app mounts the Rebase CMS, as a URL path.
|
|
400
|
+
*
|
|
401
|
+
* Copied from the app's declaration — see {@link RebaseStaticAppConfig.cms}
|
|
402
|
+
* for why a client-side route has to be declared to be knowable at all.
|
|
403
|
+
*/
|
|
404
|
+
cms?: string;
|
|
344
405
|
}
|
|
345
406
|
/**
|
|
346
407
|
* A native module found in the dependency closure.
|
|
@@ -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;
|