@rebasepro/client 0.8.0 → 0.9.1-canary.09aaf62
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/README.md +11 -11
- package/dist/admin.d.ts +1 -0
- package/dist/auth.d.ts +35 -38
- package/dist/backups.d.ts +13 -0
- package/dist/collection.d.ts +9 -13
- package/dist/errors.d.ts +9 -0
- package/dist/index.d.ts +38 -22
- package/dist/index.es.js +985 -271
- package/dist/index.es.js.map +1 -1
- package/dist/realtime-channel.d.ts +89 -0
- package/dist/sdk_query_builder.d.ts +63 -0
- package/dist/transport.d.ts +36 -6
- package/dist/websocket.d.ts +92 -22
- package/package.json +8 -9
- package/src/admin.ts +1 -1
- package/src/api-keys.ts +1 -1
- package/src/auth.ts +188 -64
- package/src/backups.ts +40 -0
- package/src/collection.test.ts +92 -3
- package/src/collection.ts +88 -75
- package/src/data-proxy.test.ts +167 -0
- package/src/errors.ts +9 -0
- package/src/index.ts +211 -28
- package/src/realtime-channel.test.ts +241 -0
- package/src/realtime-channel.ts +238 -0
- package/src/realtime-optout.test.ts +119 -0
- package/src/realtime-row-identity.test.ts +254 -0
- package/src/reviver.ts +2 -2
- package/src/sdk_query_builder.ts +141 -0
- package/src/storage.ts +64 -32
- package/src/transport.ts +59 -25
- package/src/websocket.ts +522 -193
- package/dist/collection.test.d.ts +0 -1
- package/dist/cron.test.d.ts +0 -1
- package/dist/index.umd.js +0 -2215
- package/dist/index.umd.js.map +0 -1
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Broadcast channels and presence, as an SDK surface.
|
|
3
|
+
*
|
|
4
|
+
* The realtime engine has supported `join_channel`, `broadcast`,
|
|
5
|
+
* `presence_track`, `presence_untrack` and `presence_state` for a while, but
|
|
6
|
+
* the client only recognised those types well enough to send them
|
|
7
|
+
* fire-and-forget: there were no methods to call and no way to receive channel
|
|
8
|
+
* or broadcast events, since `on()` handles only connect / disconnect /
|
|
9
|
+
* reconnect / error. Anything wanting presence therefore opened a *second*
|
|
10
|
+
* socket and reimplemented the AUTHENTICATE → AUTH_SUCCESS handshake, the
|
|
11
|
+
* reconnect backoff, and the presence heartbeat — a couple of hundred lines
|
|
12
|
+
* per app, all of it duplicating this package.
|
|
13
|
+
*
|
|
14
|
+
* Two protocol details this hides, because both are easy to get wrong and
|
|
15
|
+
* neither is discoverable from the message list:
|
|
16
|
+
*
|
|
17
|
+
* - **A joining client is told only about its own join.** The `presence_diff`
|
|
18
|
+
* it receives after `presence_track` contains just itself. The existing
|
|
19
|
+
* roster arrives only in response to an explicit `presence_state` request,
|
|
20
|
+
* so `join()` sends one.
|
|
21
|
+
* - **Presence expires after 30s** (`PRESENCE_TIMEOUT_MS` server-side). A
|
|
22
|
+
* client that tracks once and goes quiet silently vanishes from everyone
|
|
23
|
+
* else's roster while still sitting in the document, so `track()` starts a
|
|
24
|
+
* heartbeat and `leave()` stops it.
|
|
25
|
+
*/
|
|
26
|
+
/** Presence state keyed by the server's client id. */
|
|
27
|
+
export type PresenceState = Record<string, Record<string, unknown>>;
|
|
28
|
+
export interface PresenceDiff {
|
|
29
|
+
joins: PresenceState;
|
|
30
|
+
leaves: PresenceState;
|
|
31
|
+
}
|
|
32
|
+
export interface BroadcastEvent {
|
|
33
|
+
event: string;
|
|
34
|
+
payload: unknown;
|
|
35
|
+
}
|
|
36
|
+
/** The socket operations a channel needs; satisfied by RebaseWebSocketClient. */
|
|
37
|
+
export interface ChannelTransport {
|
|
38
|
+
sendMessage(message: Record<string, unknown>): Promise<unknown>;
|
|
39
|
+
onChannelMessage(channel: string, handler: (message: Record<string, unknown>) => void): () => void;
|
|
40
|
+
onReconnect(handler: () => void): () => void;
|
|
41
|
+
}
|
|
42
|
+
export declare class RebaseRealtimeChannel {
|
|
43
|
+
readonly name: string;
|
|
44
|
+
private transport;
|
|
45
|
+
private presenceHandlers;
|
|
46
|
+
private broadcastHandlers;
|
|
47
|
+
private unsubscribers;
|
|
48
|
+
/** Last known roster, kept so handlers always get a full picture. */
|
|
49
|
+
private presences;
|
|
50
|
+
/** What this client last tracked, replayed on reconnect and heartbeat. */
|
|
51
|
+
private trackedState;
|
|
52
|
+
private heartbeat;
|
|
53
|
+
private joined;
|
|
54
|
+
constructor(name: string, transport: ChannelTransport);
|
|
55
|
+
/**
|
|
56
|
+
* Join the channel and ask for the current roster.
|
|
57
|
+
*
|
|
58
|
+
* Called automatically by `track`, `broadcast`, `onPresence` and
|
|
59
|
+
* `onBroadcast`; calling it directly is only needed to start receiving
|
|
60
|
+
* before there is anything to send.
|
|
61
|
+
*/
|
|
62
|
+
join(): Promise<void>;
|
|
63
|
+
private rejoin;
|
|
64
|
+
/**
|
|
65
|
+
* Publish this client's presence state, and keep publishing it.
|
|
66
|
+
*
|
|
67
|
+
* Calling `track` again replaces the state (and restarts the heartbeat),
|
|
68
|
+
* which is how you update e.g. a cursor position.
|
|
69
|
+
*/
|
|
70
|
+
track(state: Record<string, unknown>): Promise<void>;
|
|
71
|
+
/** Stop publishing presence, without leaving the channel. */
|
|
72
|
+
untrack(): Promise<void>;
|
|
73
|
+
/**
|
|
74
|
+
* Observe the roster. The handler fires immediately with what is already
|
|
75
|
+
* known, then on every change.
|
|
76
|
+
*/
|
|
77
|
+
onPresence(handler: (state: PresenceState, diff?: PresenceDiff) => void): () => void;
|
|
78
|
+
/** Send a broadcast. The sender does not receive its own message. */
|
|
79
|
+
broadcast(event: string, payload: unknown): Promise<void>;
|
|
80
|
+
/** Observe broadcasts. Pass an event name to filter. */
|
|
81
|
+
onBroadcast(handler: (event: BroadcastEvent) => void): () => void;
|
|
82
|
+
onBroadcast(event: string, handler: (payload: unknown) => void): () => void;
|
|
83
|
+
/** Leave the channel and release every listener and timer. */
|
|
84
|
+
leave(): Promise<void>;
|
|
85
|
+
private stopHeartbeat;
|
|
86
|
+
/** Fold an incoming frame into the roster and fan it out. */
|
|
87
|
+
private handle;
|
|
88
|
+
private emitPresence;
|
|
89
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { FindResult, LogicalCondition, SDKCollectionClient, SDKQueryBuilderInterface, WhereFilterOp, WhereValue } from "@rebasepro/types";
|
|
2
|
+
/**
|
|
3
|
+
* SDK Query Builder — returns flat rows (`FindResult<M>`) instead of
|
|
4
|
+
* Entity-wrapped results (`FindResponse<M>`).
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* const { data } = await rebase.data.posts
|
|
8
|
+
* .where("status", "==", "published")
|
|
9
|
+
* .orderBy("created_at", "desc")
|
|
10
|
+
* .limit(10)
|
|
11
|
+
* .find();
|
|
12
|
+
*
|
|
13
|
+
* console.log(data[0].title); // flat access
|
|
14
|
+
*/
|
|
15
|
+
export declare class SDKQueryBuilder<M extends Record<string, unknown> = Record<string, unknown>> implements SDKQueryBuilderInterface<M> {
|
|
16
|
+
private collection;
|
|
17
|
+
private params;
|
|
18
|
+
constructor(collection: SDKCollectionClient<M>);
|
|
19
|
+
/**
|
|
20
|
+
* Add a filter condition to your query.
|
|
21
|
+
* @example
|
|
22
|
+
* client.data.users.where('age', '>=', 18).find()
|
|
23
|
+
*/
|
|
24
|
+
where<K extends keyof M & string>(column: K, operator: WhereFilterOp, value: WhereValue<M[K]>): this;
|
|
25
|
+
where(logicalCondition: LogicalCondition): this;
|
|
26
|
+
/**
|
|
27
|
+
* Order the results by a specific column.
|
|
28
|
+
*/
|
|
29
|
+
orderBy(column: keyof M & string, direction?: "asc" | "desc"): this;
|
|
30
|
+
/**
|
|
31
|
+
* Limit the number of results returned.
|
|
32
|
+
*/
|
|
33
|
+
limit(count: number): this;
|
|
34
|
+
/**
|
|
35
|
+
* Skip the first N results.
|
|
36
|
+
*/
|
|
37
|
+
offset(count: number): this;
|
|
38
|
+
/**
|
|
39
|
+
* Set a free-text search string if supported by the backend.
|
|
40
|
+
*/
|
|
41
|
+
search(searchString: string): this;
|
|
42
|
+
/**
|
|
43
|
+
* Include related entities in the response.
|
|
44
|
+
* Relations will be populated with full data instead of just IDs.
|
|
45
|
+
*
|
|
46
|
+
* @param relations - Relation names to include, or "*" for all.
|
|
47
|
+
* @example
|
|
48
|
+
* client.data.posts.include("tags", "author").find()
|
|
49
|
+
*/
|
|
50
|
+
include(...relations: string[]): this;
|
|
51
|
+
/**
|
|
52
|
+
* Execute the find query and return the results as flat rows.
|
|
53
|
+
*/
|
|
54
|
+
find(): Promise<FindResult<M>>;
|
|
55
|
+
/**
|
|
56
|
+
* Count the records matching this query.
|
|
57
|
+
*/
|
|
58
|
+
count(): Promise<number>;
|
|
59
|
+
/**
|
|
60
|
+
* Listen to realtime updates matching this query.
|
|
61
|
+
*/
|
|
62
|
+
listen(onUpdate: (data: FindResult<M>) => void, onError?: (error: Error) => void): () => void;
|
|
63
|
+
}
|
package/dist/transport.d.ts
CHANGED
|
@@ -1,23 +1,53 @@
|
|
|
1
1
|
import { FindParams as TypesFindParams, FindResponse as TypesFindResponse } from "@rebasepro/types";
|
|
2
|
+
export { RebaseApiError } from "@rebasepro/types";
|
|
3
|
+
export type { RebaseErrorInit } from "@rebasepro/types";
|
|
2
4
|
export interface RebaseClientConfig {
|
|
5
|
+
/**
|
|
6
|
+
* Origin of the Rebase server — scheme, host and port **only**.
|
|
7
|
+
*
|
|
8
|
+
* {@link apiPath} is appended to this, so do not include it here:
|
|
9
|
+
* `"http://localhost:3001"` is correct, while `"http://localhost:3001/api"`
|
|
10
|
+
* silently builds `/api/api/…` and every request 404s. Omit entirely for
|
|
11
|
+
* same-origin requests from the browser.
|
|
12
|
+
*/
|
|
3
13
|
baseUrl?: string;
|
|
14
|
+
/**
|
|
15
|
+
* Bearer token sent as `Authorization` on every request.
|
|
16
|
+
*
|
|
17
|
+
* In the browser this is the signed-in user's access token, so row-level
|
|
18
|
+
* security applies. Server-side callers — scripts, cron jobs, ETL — pass the
|
|
19
|
+
* service key instead, which resolves to `{ uid: "service", roles: ["admin"] }`
|
|
20
|
+
* and **bypasses RLS**: there is no user to constrain those queries, so scope
|
|
21
|
+
* them explicitly.
|
|
22
|
+
*/
|
|
4
23
|
token?: string;
|
|
24
|
+
/**
|
|
25
|
+
* Path the API is mounted under, appended to {@link baseUrl}.
|
|
26
|
+
* Defaults to `"/api"`; override only if the server mounts it elsewhere.
|
|
27
|
+
*/
|
|
5
28
|
apiPath?: string;
|
|
6
29
|
fetch?: typeof globalThis.fetch;
|
|
7
30
|
onUnauthorized?: () => Promise<boolean>;
|
|
8
31
|
websocketUrl?: string;
|
|
32
|
+
/**
|
|
33
|
+
* Open the realtime WebSocket. **Defaults to `true`.**
|
|
34
|
+
*
|
|
35
|
+
* The socket connects as soon as the client is constructed and keeps the
|
|
36
|
+
* Node event loop alive, so a one-shot script (CLI, cron job, ETL) will not
|
|
37
|
+
* exit on its own. Set this to `false` for any process that reads or writes
|
|
38
|
+
* and then terminates — `.listen()` and `.listenById()` then throw instead
|
|
39
|
+
* of silently doing nothing.
|
|
40
|
+
*
|
|
41
|
+
* Long-lived processes that do want realtime can instead call
|
|
42
|
+
* `client.close()` when shutting down.
|
|
43
|
+
*/
|
|
44
|
+
realtime?: boolean;
|
|
9
45
|
}
|
|
10
46
|
/**
|
|
11
47
|
* Re-export from `@rebasepro/types` for backward compatibility.
|
|
12
48
|
*/
|
|
13
49
|
export type FindParams = TypesFindParams;
|
|
14
50
|
export type FindResponse<T> = TypesFindResponse<T extends Record<string, unknown> ? T : Record<string, unknown>>;
|
|
15
|
-
export declare class RebaseApiError extends Error {
|
|
16
|
-
status: number;
|
|
17
|
-
code?: string;
|
|
18
|
-
details?: unknown;
|
|
19
|
-
constructor(status: number, message: string, code?: string, details?: unknown);
|
|
20
|
-
}
|
|
21
51
|
export declare function buildQueryString(params?: FindParams): string;
|
|
22
52
|
export interface Transport {
|
|
23
53
|
request: <T = unknown>(path: string, init?: RequestInit) => Promise<T>;
|
package/dist/websocket.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { DeleteProps, CollectionConfig, FetchCollectionProps, FetchOneProps, SaveProps, TableMetadata, BranchInfo } from "@rebasepro/types";
|
|
2
2
|
export interface RebaseWebSocketConfig {
|
|
3
3
|
websocketUrl: string;
|
|
4
4
|
/** Optional auth token getter for WebSocket authentication */
|
|
@@ -8,21 +8,31 @@ export interface RebaseWebSocketConfig {
|
|
|
8
8
|
/** Callback to handle unauthorized requests or token expiration (refreshes auth session) */
|
|
9
9
|
onUnauthorized?: () => Promise<boolean>;
|
|
10
10
|
}
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
11
|
+
/**
|
|
12
|
+
* Low-level realtime WebSocket client.
|
|
13
|
+
*
|
|
14
|
+
* @internal Not a stable app-facing API. `createRebaseClient()` constructs and
|
|
15
|
+
* manages this internally (exposed as `client.ws`, typed by the minimal
|
|
16
|
+
* `RebaseWebSocket` contract in `@rebasepro/types`). It is re-exported from the
|
|
17
|
+
* package root only because the `@rebasepro/client-postgres` driver
|
|
18
|
+
* instantiates it directly; its surface may change without a major bump.
|
|
19
|
+
*/
|
|
16
20
|
export declare class RebaseWebSocketClient {
|
|
17
21
|
private websocketUrl;
|
|
18
22
|
private ws;
|
|
19
23
|
getAuthToken?: () => Promise<string | null>;
|
|
20
24
|
private subscriptions;
|
|
21
25
|
private listeners;
|
|
26
|
+
/** Channel-name → handlers, for broadcast and presence frames. */
|
|
27
|
+
private channelHandlers;
|
|
28
|
+
/** Subscribe to broadcast/presence frames for one channel. */
|
|
29
|
+
onChannelMessage(channel: string, handler: (message: Record<string, unknown>) => void): () => void;
|
|
30
|
+
/** Notified after the socket comes back, so channels can re-join. */
|
|
31
|
+
onReconnect(handler: () => void): () => void;
|
|
22
32
|
on(event: "connect" | "disconnect" | "reconnect" | "error", cb: (...args: unknown[]) => void): () => boolean;
|
|
23
33
|
private emit;
|
|
24
34
|
private collectionSubscriptions;
|
|
25
|
-
private
|
|
35
|
+
private singleSubscriptions;
|
|
26
36
|
private backendToCollectionKey;
|
|
27
37
|
private backendToEntityKey;
|
|
28
38
|
private pendingRequests;
|
|
@@ -31,6 +41,7 @@ export declare class RebaseWebSocketClient {
|
|
|
31
41
|
private isConnected;
|
|
32
42
|
private messageQueue;
|
|
33
43
|
private requestTimeoutMs;
|
|
44
|
+
private subscriptionTimeoutMs;
|
|
34
45
|
private reconnectTimeout;
|
|
35
46
|
private isAuthenticated;
|
|
36
47
|
private authPromise;
|
|
@@ -53,19 +64,23 @@ export declare class RebaseWebSocketClient {
|
|
|
53
64
|
private isAuthError;
|
|
54
65
|
private handleAuthFailure;
|
|
55
66
|
/**
|
|
56
|
-
* Shared logic for re-subscribing a collection or
|
|
67
|
+
* Shared logic for re-subscribing a collection or row subscription
|
|
57
68
|
* after an auth error is resolved by refreshing credentials.
|
|
58
69
|
*/
|
|
59
70
|
private resubscribeAfterAuthRefresh;
|
|
60
71
|
private handleWebSocketMessage;
|
|
61
72
|
private ensureAuthenticated;
|
|
62
73
|
reauthenticate(): Promise<void>;
|
|
63
|
-
|
|
74
|
+
/**
|
|
75
|
+
* Public because `RebaseRealtimeChannel` sends channel frames through it.
|
|
76
|
+
* Not part of the stable surface — prefer `client.realtime.channel(name)`.
|
|
77
|
+
*/
|
|
78
|
+
sendMessage(message: Record<string, unknown>): Promise<unknown>;
|
|
64
79
|
private doSendMessage;
|
|
65
|
-
fetchCollection<M extends Record<string, unknown>>(props: FetchCollectionProps<M>): Promise<
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
80
|
+
fetchCollection<M extends Record<string, unknown>>(props: FetchCollectionProps<M>): Promise<Record<string, unknown>[]>;
|
|
81
|
+
fetchOne<M extends Record<string, unknown>>(props: FetchOneProps<M>): Promise<Record<string, unknown> | undefined>;
|
|
82
|
+
save<M extends Record<string, unknown>>(props: SaveProps<M>): Promise<Record<string, unknown>>;
|
|
83
|
+
delete<M extends Record<string, unknown>>(props: DeleteProps<M>): Promise<void>;
|
|
69
84
|
executeSql(sql: string, options?: {
|
|
70
85
|
database?: string;
|
|
71
86
|
role?: string;
|
|
@@ -73,8 +88,8 @@ export declare class RebaseWebSocketClient {
|
|
|
73
88
|
fetchAvailableDatabases(): Promise<string[]>;
|
|
74
89
|
fetchAvailableRoles(): Promise<string[]>;
|
|
75
90
|
fetchCurrentDatabase(): Promise<string | undefined>;
|
|
76
|
-
checkUniqueField(path: string, name: string, value: unknown,
|
|
77
|
-
|
|
91
|
+
checkUniqueField(path: string, name: string, value: unknown, id?: string, collection?: CollectionConfig): Promise<boolean>;
|
|
92
|
+
count<M extends Record<string, unknown>>(props: FetchCollectionProps<M>): Promise<number>;
|
|
78
93
|
fetchUnmappedTables(mappedPaths?: string[]): Promise<string[]>;
|
|
79
94
|
fetchTableMetadata(tableName: string): Promise<TableMetadata>;
|
|
80
95
|
createBranch(name: string, options?: {
|
|
@@ -89,14 +104,69 @@ export declare class RebaseWebSocketClient {
|
|
|
89
104
|
private deepEqual;
|
|
90
105
|
private normalizeForComparison;
|
|
91
106
|
/**
|
|
92
|
-
*
|
|
93
|
-
*
|
|
94
|
-
*
|
|
107
|
+
* The address of a row, for matching it against another copy of itself.
|
|
108
|
+
*
|
|
109
|
+
* A row is exactly its columns and carries no address, so it is derived
|
|
110
|
+
* from the key columns the server named — including the ordinary case where
|
|
111
|
+
* that key is `id`, which the server reports like any other.
|
|
112
|
+
*
|
|
113
|
+
* Undefined when there are no keys, which means the server could not
|
|
114
|
+
* resolve any: such rows genuinely cannot be recognised, and guessing at a
|
|
115
|
+
* column called `id` would be inventing an identity for a table that has
|
|
116
|
+
* none.
|
|
117
|
+
*/
|
|
118
|
+
private rowAddress;
|
|
119
|
+
/**
|
|
120
|
+
* Merge incoming rows with cached data, preserving cached references
|
|
121
|
+
* for rows whose values haven't changed. This avoids unnecessary
|
|
122
|
+
* React re-renders when the server refetches all rows but most
|
|
95
123
|
* haven't actually changed.
|
|
96
124
|
*/
|
|
97
|
-
private
|
|
98
|
-
listenCollection<M extends Record<string, unknown>>(props: FetchCollectionProps<M>, onUpdate: (
|
|
99
|
-
|
|
125
|
+
private mergeRows;
|
|
126
|
+
listenCollection<M extends Record<string, unknown>>(props: FetchCollectionProps<M>, onUpdate: (rows: Record<string, unknown>[]) => void, onError?: (error: Error) => void): () => void;
|
|
127
|
+
listenOne<M extends Record<string, unknown>>(props: FetchOneProps<M>, onUpdate: (row: Record<string, unknown> | null) => void, onError?: (error: Error) => void): () => void;
|
|
128
|
+
/**
|
|
129
|
+
* Send a `subscribe_collection` for an already-registered subscription and
|
|
130
|
+
* arm its watchdog.
|
|
131
|
+
*
|
|
132
|
+
* Every path that registers a collection subscription goes through here, so
|
|
133
|
+
* that a subscribe which never lands — a rejected send, or a server that
|
|
134
|
+
* never answers — always ends up in `failCollectionSubscription` rather than
|
|
135
|
+
* leaving the entry parked with `isInitialDataReceived === false` forever.
|
|
136
|
+
*/
|
|
137
|
+
private sendCollectionSubscribe;
|
|
138
|
+
/** The `listenOne` counterpart of {@link sendCollectionSubscribe}. */
|
|
139
|
+
private sendEntitySubscribe;
|
|
140
|
+
/**
|
|
141
|
+
* Report a subscribe failure to every listener and drop the registration.
|
|
142
|
+
*
|
|
143
|
+
* Dropping it is the point: the callbacks stay live (their components are
|
|
144
|
+
* still mounted and have been told), but the next `listenCollection` for
|
|
145
|
+
* these params finds no entry and issues a fresh subscribe instead of
|
|
146
|
+
* silently attaching to a dead one.
|
|
147
|
+
*/
|
|
148
|
+
private failCollectionSubscription;
|
|
149
|
+
/** The `listenOne` counterpart of {@link failCollectionSubscription}. */
|
|
150
|
+
private failEntitySubscription;
|
|
151
|
+
/**
|
|
152
|
+
* Stop the watchdogs without failing anything — used when the socket drops,
|
|
153
|
+
* since the reconnect path re-subscribes everything anyway and a watchdog
|
|
154
|
+
* firing mid-reconnect would tear down healthy subscriptions.
|
|
155
|
+
*/
|
|
156
|
+
private suspendSubscribeWatchdogs;
|
|
157
|
+
/**
|
|
158
|
+
* Arm watchdogs for subscribes that were requested while offline and have
|
|
159
|
+
* just been flushed to the socket. Their timers were deliberately not set at
|
|
160
|
+
* request time, so without this they would have no timeout at all.
|
|
161
|
+
*/
|
|
162
|
+
private armPendingSubscribeWatchdogs;
|
|
163
|
+
private sendCollectionSubscribeWatchdog;
|
|
164
|
+
private sendEntitySubscribeWatchdog;
|
|
165
|
+
/**
|
|
166
|
+
* Fail every subscription that never received data. Called when reconnection
|
|
167
|
+
* is given up on, so views surface an error instead of spinning forever.
|
|
168
|
+
*/
|
|
169
|
+
private failAllPendingSubscriptions;
|
|
100
170
|
/**
|
|
101
171
|
* Re-send all active subscriptions to the backend after a reconnect.
|
|
102
172
|
* The server wipes subscription state when a client disconnects, so
|
|
@@ -104,5 +174,5 @@ export declare class RebaseWebSocketClient {
|
|
|
104
174
|
*/
|
|
105
175
|
private resubscribeAll;
|
|
106
176
|
private createCollectionSubscriptionKey;
|
|
107
|
-
private
|
|
177
|
+
private createSingleSubscriptionKey;
|
|
108
178
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rebasepro/client",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.9.1-canary.09aaf62",
|
|
5
5
|
"description": "HTTP SDK client for the Rebase custom backend",
|
|
6
6
|
"funding": {
|
|
7
7
|
"url": "https://github.com/sponsors/rebaseco"
|
|
@@ -13,26 +13,25 @@
|
|
|
13
13
|
"url": "https://github.com/rebasepro/rebase.git",
|
|
14
14
|
"directory": "packages/client"
|
|
15
15
|
},
|
|
16
|
-
"main": "./dist/index.
|
|
16
|
+
"main": "./dist/index.es.js",
|
|
17
17
|
"module": "./dist/index.es.js",
|
|
18
18
|
"types": "./dist/index.d.ts",
|
|
19
19
|
"source": "src/index.ts",
|
|
20
20
|
"engines": {
|
|
21
|
-
"node": ">=
|
|
21
|
+
"node": ">=20"
|
|
22
22
|
},
|
|
23
23
|
"exports": {
|
|
24
24
|
".": {
|
|
25
25
|
"types": "./dist/index.d.ts",
|
|
26
26
|
"development": "./dist/index.es.js",
|
|
27
|
-
"import": "./dist/index.es.js"
|
|
28
|
-
"require": "./dist/index.umd.cjs"
|
|
27
|
+
"import": "./dist/index.es.js"
|
|
29
28
|
},
|
|
30
29
|
"./package.json": "./package.json"
|
|
31
30
|
},
|
|
32
31
|
"dependencies": {
|
|
33
|
-
"@rebasepro/common": "0.
|
|
34
|
-
"@rebasepro/
|
|
35
|
-
"@rebasepro/
|
|
32
|
+
"@rebasepro/common": "0.9.1-canary.09aaf62",
|
|
33
|
+
"@rebasepro/utils": "0.9.1-canary.09aaf62",
|
|
34
|
+
"@rebasepro/types": "0.9.1-canary.09aaf62"
|
|
36
35
|
},
|
|
37
36
|
"devDependencies": {
|
|
38
37
|
"@jest/globals": "^30.4.1",
|
|
@@ -75,7 +74,7 @@
|
|
|
75
74
|
},
|
|
76
75
|
"scripts": {
|
|
77
76
|
"watch": "vite build --watch",
|
|
78
|
-
"build": "vite build && tsc --emitDeclarationOnly -p tsconfig.prod.json",
|
|
77
|
+
"build": "vite build && tsc --emitDeclarationOnly -p tsconfig.prod.json && node ../../scripts/assert-build-output.mjs",
|
|
79
78
|
"test:lint": "eslint \"src/**\" --quiet",
|
|
80
79
|
"test": "jest --passWithNoTests --forceExit",
|
|
81
80
|
"clean": "rm -rf dist && find ./src -name '*.js' -type f | xargs rm -f"
|
package/src/admin.ts
CHANGED
|
@@ -54,7 +54,7 @@ export function createAdmin(transport: Transport, options?: CreateAdminOptions)
|
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
async function resetPassword(userId: string, options?: { password?: string }) {
|
|
57
|
-
return transport.request<{ user: AdminUser; temporaryPassword?: string; invitationSent?: boolean }>(
|
|
57
|
+
return transport.request<{ user: AdminUser; temporaryPassword?: string; invitationSent?: boolean; emailDeliveryFailed?: boolean }>(
|
|
58
58
|
adminPath + "/users/" + encodeURIComponent(userId) + "/reset-password",
|
|
59
59
|
{
|
|
60
60
|
method: "POST",
|
package/src/api-keys.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Transport } from "./transport";
|
|
2
2
|
|
|
3
|
-
// Re-define the types locally since they live in server
|
|
3
|
+
// Re-define the types locally since they live in server, not in @rebasepro/types.
|
|
4
4
|
// These match the server-side types exactly.
|
|
5
5
|
|
|
6
6
|
/** A single permission entry scoping an API key to a collection and its allowed operations. */
|