@rebasepro/client 0.23.0 → 0.24.1-canary.g19596ef

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 CHANGED
@@ -34,22 +34,37 @@ of it resolves too: Node has supported `require(esm)` since 22.12.
34
34
  |---|---|
35
35
  | `createRebaseClient<DB>(options)` | Create a client instance. Generic `DB` parameter enables type-safe `client.data.*` access. |
36
36
  | `CreateRebaseClientResult<DB>` | The client type it returns (`RebaseClient<DB>` from `@rebasepro/types`, narrowed) — includes `auth`, `admin`, `cron`, `functions`, `storage`, `ws`, `data`, `call`, and token management methods. |
37
- | `CreateRebaseClientOptions` | Extends `RebaseClientConfig` with `auth`, `admin`, and `cron` sub-configs. |
37
+ | `CreateRebaseClientOptions` | Extends `RebaseClientConfig` with the `auth`, `admin`, `cron`, `apiKeys` and `personalKeys` sub-configs, plus `storageSources`, `collections` and `offline`. |
38
38
 
39
39
  ### Config
40
40
 
41
41
  | Option | Type | Default | Description |
42
42
  |---|---|---|---|
43
43
  | `baseUrl` | `string` | `""` | Backend URL (e.g. `http://localhost:3001`) |
44
- | `token` | `string` | — | Static auth token |
44
+ | `token` | `string` | — | Auth token, read each time one is needed (so it may be declared as a getter) until `setToken()` or a sign-in replaces it |
45
45
  | `apiPath` | `string` | `"/api"` | API path prefix |
46
46
  | `fetch` | `typeof fetch` | `globalThis.fetch` | Custom fetch implementation |
47
- | `onUnauthorized` | `() => Promise<boolean>` | auto-refresh | Handler for 401 responses |
47
+ | `onUnauthorized` | `() => Promise<boolean>` | auto-refresh | Handler for a refused token, over HTTP (401) and on the realtime socket |
48
48
  | `websocketUrl` | `string` | derived from `baseUrl` | WebSocket URL for realtime |
49
49
  | `realtime` | `boolean` | `true` | Open the WebSocket — `false` lets a one-shot script exit |
50
50
  | `collections` | `Record<string, string>` | — | Maps accessor names to collection slugs |
51
51
  | `offline` | `boolean \| OfflineConfig` | `false` | Local-first sync — see [the docs](https://rebase.pro/docs/sdk/offline) |
52
52
 
53
+ ### Tokens
54
+
55
+ | Method | Description |
56
+ |---|---|
57
+ | `setAuthTokenGetter(getter)` | Ask `getter` for the token each time one is needed: every HTTP request and every time the realtime socket authenticates. This is how a host signing users in with its own provider (Clerk, Firebase Auth, its own session) authenticates the client. It comes before the client's own session and the `token` option |
58
+ | `setToken(token)` | Send this token from now on, over HTTP and on the socket |
59
+ | `setOnUnauthorized(handler)` | Answer a refused token, on HTTP and the socket; resolve `true` to retry |
60
+ | `resolveToken()` | The token the next request would carry |
61
+
62
+ Installing a getter or calling `setToken()` rebuilds an open socket so it authenticates as the new credential. `client.ws.setAuthTokenGetter()` is deprecated: it still works, warns once, and reaches only the socket.
63
+
64
+ ```ts
65
+ client.setAuthTokenGetter(() => clerk.session?.getToken() ?? Promise.resolve(null));
66
+ ```
67
+
53
68
  ### Collection Client
54
69
 
55
70
  `client.data.collection("slug")` or `client.data.myCollection` returns a `CollectionClient<M>`:
@@ -62,11 +77,11 @@ of it resolves too: Node has supported `require(esm)` since 22.12.
62
77
  | `update(id, data)` | Update a row. Returns `M` |
63
78
  | `delete(id)` | Delete a row |
64
79
  | `count(params?)` | Count matching rows |
65
- | `where(col, op, val)` | Start a fluent query — returns `QueryBuilder` |
66
- | `orderBy(col, dir?)` | Order results — returns `QueryBuilder` |
67
- | `limit(n)` / `offset(n)` | Pagination — returns `QueryBuilder` |
68
- | `search(str)` | Full-text search — returns `QueryBuilder` |
69
- | `include(...rels)` | Include related rows — returns `QueryBuilder` |
80
+ | `where(col, op, val)` | Start a fluent query — returns a query builder |
81
+ | `orderBy(col, dir?)` | Order results — returns a query builder |
82
+ | `limit(n)` / `offset(n)` | Pagination — returns a query builder |
83
+ | `search(str)` | Text search: a case-insensitive substring match by default, ranked full-text where the collection opts in — returns a query builder |
84
+ | `include(...rels)` | Include related rows — returns a query builder |
70
85
  | `listen(params, onUpdate, onError?)` | Realtime subscription (requires WebSocket) |
71
86
  | `listenById(id, onUpdate, onError?)` | Realtime single-row subscription |
72
87
  | `observe(params, onResult, onError?, options?)` | Live query — local-first when `offline` is on, otherwise fetch + `listen` |
@@ -107,7 +122,7 @@ of it resolves too: Node has supported `require(esm)` since 22.12.
107
122
 
108
123
  | Method | Description |
109
124
  |---|---|
110
- | `listUsers()` / `listUsersPaginated(options?)` | List all users |
125
+ | `listUsers(options?)` / `listUsersPaginated(options?)` | One page of users (25 by default; `limit`, `offset`, `search`, `orderBy`, `orderDir`) with `total` |
111
126
  | `getUser(userId)` | Get a single user |
112
127
  | `createUser(data)` | Create a user |
113
128
  | `updateUser(userId, data)` | Update a user |
@@ -130,7 +145,7 @@ of it resolves too: Node has supported `require(esm)` since 22.12.
130
145
  | `MemoryOfflineStore` | Reference `OfflineStore`; the IndexedDB one is wired automatically |
131
146
  | `createCookieStorage(options?)` | Cookie-based auth storage adapter |
132
147
  | `createMemoryStorage()` | In-memory auth storage adapter |
133
- | `QueryBuilder` | Fluent query builder (also re-exported from `@rebasepro/common`) |
148
+ | `or`, `and`, `not`, `cond` | Logical-condition helpers for `.where(…)` |
134
149
  | `FindResult`, `FindParams`, `User`, … | Re-exported from `@rebasepro/types` |
135
150
 
136
151
  ## Quick Start
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Compile-time assertions about the admin client's answers.
3
+ *
4
+ * A plain module under `src`, imported by nothing, for the reason
5
+ * `query-contract.types.ts` gives: a type assertion in a jest test is checked
6
+ * by nothing here, and `pnpm typecheck` reads `src`.
7
+ */
8
+ import type { createAdmin } from "./admin.js";
9
+ type Admin = ReturnType<typeof createAdmin>;
10
+ /**
11
+ * `POST /admin/users` answers `{ user, invitationSent, temporaryPassword?,
12
+ * emailDeliveryFailed? }`, and the temporary password is returned exactly
13
+ * once. Typed `{ user }`, it was a compile error to read — while the sibling
14
+ * `resetPassword` typed the same three fields.
15
+ */
16
+ export declare const createUserDelivery: (admin: Admin) => Promise<{
17
+ temporaryPassword: string | undefined;
18
+ invitationSent: boolean | undefined;
19
+ emailDeliveryFailed: boolean | undefined;
20
+ }>;
21
+ export {};
package/dist/admin.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import type { Transport } from "./transport.js";
2
- import { AdminUser } from "@rebasepro/types";
2
+ import type { AdminUser, RoleSummary } from "@rebasepro/types";
3
3
  export type { AdminUser };
4
4
  export interface CreateAdminOptions {
5
5
  adminPath?: string;
@@ -33,20 +33,29 @@ export declare function createAdmin(transport: Transport, options?: CreateAdminO
33
33
  displayName?: string;
34
34
  password?: string;
35
35
  roles?: string[];
36
+ skipPasswordPolicy?: boolean;
36
37
  }) => Promise<{
37
38
  user: AdminUser;
39
+ temporaryPassword?: string;
40
+ invitationSent?: boolean;
41
+ emailDeliveryFailed?: boolean;
38
42
  }>;
39
43
  updateUser: (userId: string, data: {
40
44
  email?: string;
41
45
  displayName?: string;
42
46
  password?: string;
43
47
  roles?: string[];
48
+ disabled?: boolean;
44
49
  }) => Promise<{
45
50
  user: AdminUser;
46
51
  }>;
47
52
  deleteUser: (userId: string) => Promise<{
48
53
  success: boolean;
49
54
  }>;
55
+ resetMfa: (userId: string) => Promise<{
56
+ success: boolean;
57
+ removedFactors: number;
58
+ }>;
50
59
  resetPassword: (userId: string, options?: {
51
60
  password?: string;
52
61
  }) => Promise<{
@@ -56,10 +65,7 @@ export declare function createAdmin(transport: Transport, options?: CreateAdminO
56
65
  emailDeliveryFailed?: boolean;
57
66
  }>;
58
67
  listRoles: () => Promise<{
59
- roles: Array<{
60
- id: string;
61
- name: string;
62
- }>;
68
+ roles: RoleSummary[];
63
69
  }>;
64
70
  bootstrap: () => Promise<{
65
71
  success: boolean;
@@ -1,20 +1,13 @@
1
1
  import type { Transport } from "./transport.js";
2
- /**
3
- * These were re-declared here, under a comment saying they lived in the server
4
- * package rather than in `@rebasepro/types`. That stopped being true, and the
5
- * copy drifted: it never gained `admin`, the flag that grants a key the `admin`
6
- * role — admin routes plus the RLS `default_admin` policies — so the SDK could
7
- * describe every kind of key except a privileged one, and
8
- * `createKey({ …, admin: true })` was an excess-property error.
9
- */
10
- export type { ApiKeyPermission, ApiKeyMasked, ApiKeyWithSecret, CreateApiKeyRequest, UpdateApiKeyRequest } from "@rebasepro/types";
11
- import type { ApiKeyMasked, ApiKeyWithSecret, CreateApiKeyRequest, UpdateApiKeyRequest } from "@rebasepro/types";
2
+ export type { ApiKeyKind, ApiKeyMasked, ApiKeyWithSecret, CreateApiKeyRequest, CreatePersonalKeyRequest, UpdateApiKeyRequest } from "@rebasepro/types";
3
+ import type { ApiKeyMasked, ApiKeyWithSecret, CreateApiKeyRequest, CreatePersonalKeyRequest, ScopeSummary, UpdateApiKeyRequest } from "@rebasepro/types";
12
4
  /** Options for the `createApiKeys` factory. */
13
5
  export interface CreateApiKeysOptions {
14
6
  apiKeysPath?: string;
15
7
  }
16
8
  /**
17
- * Creates a client for managing API keys via the admin routes.
9
+ * Creates a client for the project's service keys, via the admin routes.
10
+ * Needs `keys:read` / `keys:write`.
18
11
  *
19
12
  * @param transport - The shared HTTP transport created by `createTransport`.
20
13
  * @param options - Optional overrides (e.g. a custom base path).
@@ -36,3 +29,28 @@ export declare function createApiKeys(transport: Transport, options?: CreateApiK
36
29
  success: boolean;
37
30
  }>;
38
31
  };
32
+ /** Options for the `createPersonalKeys` factory. */
33
+ export interface CreatePersonalKeysOptions {
34
+ personalKeysPath?: string;
35
+ scopesPath?: string;
36
+ }
37
+ /**
38
+ * Creates a client for the signed-in account's own API keys — each acts as the
39
+ * account and holds no scope it does not. Answers `PERSONAL_KEYS_DISABLED`
40
+ * unless the backend sets `personalKeys: true` on the users collection.
41
+ */
42
+ export declare function createPersonalKeys(transport: Transport, options?: CreatePersonalKeysOptions): {
43
+ listKeys: () => Promise<{
44
+ keys: ApiKeyMasked[];
45
+ }>;
46
+ createKey: (data: CreatePersonalKeyRequest) => Promise<{
47
+ key: ApiKeyWithSecret;
48
+ }>;
49
+ revokeKey: (id: string) => Promise<{
50
+ success: boolean;
51
+ }>;
52
+ listScopes: () => Promise<{
53
+ scopes: ScopeSummary[];
54
+ held: string[];
55
+ }>;
56
+ };
package/dist/auth.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Transport } from "./transport.js";
2
- import type { AuthAdapterCapabilities, AuthChangeEvent, RebaseSession, DeviceSession, User } from "@rebasepro/types";
2
+ import type { AuthConfigDocument, AuthChangeEvent, RebaseSession, DeviceSession, User } from "@rebasepro/types";
3
3
  export type { RebaseSession, AuthTokens, AuthChangeEvent, DeviceSession } from "@rebasepro/types";
4
4
  /** Minimal, non-sensitive user profile returned by {@link findUserByEmail}. */
5
5
  export interface PublicUserProfile {
@@ -8,14 +8,15 @@ export interface PublicUserProfile {
8
8
  photoURL: string | null;
9
9
  }
10
10
  /**
11
- * What `GET /auth/config` answers: the backend's auth capability document.
11
+ * What `GET /auth/config` answers: the backend's auth capability document, and
12
+ * whether it serves storage.
12
13
  *
13
14
  * Declared once, in `@rebasepro/types`, and re-exported here under the name the
14
15
  * endpoint uses. The SDK used to carry its own near-copy of it, which listed an
15
16
  * `emailServiceEnabled` flag no backend has ever sent and omitted half of what
16
17
  * every backend does send.
17
18
  */
18
- export type AuthConfig = AuthAdapterCapabilities;
19
+ export type AuthConfig = AuthConfigDocument;
19
20
  export interface AuthStorage {
20
21
  getItem: (key: string) => string | null;
21
22
  setItem: (key: string, value: string) => void;
@@ -52,6 +53,12 @@ export declare function createAuth(transport: Transport, options?: CreateAuthOpt
52
53
  refreshToken: string;
53
54
  }>;
54
55
  signUp: (email: string, password: string, displayName?: string) => Promise<{
56
+ confirmationRequired: true;
57
+ user: null;
58
+ accessToken: null;
59
+ refreshToken: null;
60
+ } | {
61
+ confirmationRequired: false;
55
62
  user: User;
56
63
  accessToken: string;
57
64
  refreshToken: string;
@@ -149,8 +156,11 @@ export declare function createAuth(transport: Transport, options?: CreateAuthOpt
149
156
  * Start enrolling a TOTP factor.
150
157
  *
151
158
  * Returns the secret and an `otpauth://` URI to render as a QR code,
152
- * plus ten single-use recovery codes. **Show the recovery codes once
153
- * and never again** — only their hashes are stored.
159
+ * plus — with the account's first factor — ten single-use recovery
160
+ * codes. **Show the recovery codes once and never again**: only their
161
+ * hashes are stored. Adding another factor keeps the codes the account
162
+ * has, and `recoveryCodes` is then `null`; `regenerateRecoveryCodes()`
163
+ * replaces them.
154
164
  *
155
165
  * The factor is not usable until `verify` confirms the user's
156
166
  * authenticator produced a correct code from it.
@@ -169,7 +179,7 @@ export declare function createAuth(transport: Transport, options?: CreateAuthOpt
169
179
  uri: string;
170
180
  qrUri: string;
171
181
  };
172
- recoveryCodes: string[];
182
+ recoveryCodes: string[] | null;
173
183
  }>;
174
184
  /** Confirm an enrolment with a code from the authenticator app. */
175
185
  verify(factorId: string, code: string): Promise<{
@@ -188,8 +198,18 @@ export declare function createAuth(transport: Transport, options?: CreateAuthOpt
188
198
  createdAt: string;
189
199
  }[]>;
190
200
  /**
191
- * Remove a factor. Requires an `aal2` session — one that has already
192
- * answered a challenge — so a stolen `aal1` token cannot turn MFA off.
201
+ * Replace the account's recovery codes with ten new ones, shown once.
202
+ * Needs an `aal2` session. Adding a second factor keeps the codes the
203
+ * account already has; this is how to get new ones.
204
+ */
205
+ regenerateRecoveryCodes(): Promise<{
206
+ recoveryCodes: string[];
207
+ }>;
208
+ /**
209
+ * Remove a factor. Once the account has a verified factor this
210
+ * requires an `aal2` session — one that has already answered a
211
+ * challenge — so a stolen `aal1` token cannot turn MFA off. An
212
+ * unfinished first enrolment can be removed from any session.
193
213
  */
194
214
  unenroll(factorId: string): Promise<{
195
215
  success: boolean;
@@ -258,9 +278,23 @@ export declare function createAuth(transport: Transport, options?: CreateAuthOpt
258
278
  success: boolean;
259
279
  message: string;
260
280
  }>;
261
- verifyEmail: (token: string) => Promise<{
281
+ verifyEmail: (token: string, options?: {
282
+ password?: string;
283
+ removeUnproven?: boolean;
284
+ }) => Promise<{
262
285
  success: boolean;
263
- message: string;
286
+ passwordRemoved: boolean;
287
+ removedProviders: string[];
288
+ session: RebaseSession | null;
289
+ }>;
290
+ changeEmail: (newEmail: string) => Promise<{
291
+ pendingEmail: string;
292
+ expiresAt: string;
293
+ }>;
294
+ confirmEmailChange: (token: string) => Promise<{
295
+ uid: string;
296
+ email: string;
297
+ removedProviders: string[];
264
298
  }>;
265
299
  sendMagicLink: (email: string) => Promise<{
266
300
  success: boolean;
@@ -288,12 +322,32 @@ export declare function createAuth(transport: Transport, options?: CreateAuthOpt
288
322
  revokeAllSessions: () => Promise<{
289
323
  success: boolean;
290
324
  }>;
291
- getAuthConfig: () => Promise<AuthAdapterCapabilities>;
325
+ getAuthConfig: () => Promise<AuthConfigDocument>;
292
326
  getSession: () => RebaseSession | null;
293
327
  onAuthStateChange: (callback: (event: AuthChangeEvent, session: RebaseSession | null) => void) => () => boolean;
294
328
  canRestoreSession: () => boolean;
295
329
  isInitialized: () => Promise<void>;
330
+ /**
331
+ * How restoring the session on load ended — see
332
+ * {@link SessionRestoreOutcome}. `"unreachable"` with no session is
333
+ * the one case where "signed out" is not known to be true: the
334
+ * device could not ask.
335
+ */
336
+ restoreOutcome: () => SessionRestoreOutcome;
296
337
  };
338
+ /**
339
+ * How restoring the session on load ended — `auth.restoreOutcome()`.
340
+ *
341
+ * - `"pending"`: still restoring (`isInitialized()` has not settled).
342
+ * - `"restored"`: a session was restored, from storage or from the server.
343
+ * - `"none"`: there was nothing to restore.
344
+ * - `"refused"`: there was a session to restore, and the server refused it.
345
+ * - `"unreachable"`: the server could not be reached (or answered 5xx), so the
346
+ * session was neither confirmed nor refused. With a stored session the
347
+ * client keeps it and retries; in cookie mode, where nothing is stored on the
348
+ * device, it has no session until a later refresh or sign-in succeeds.
349
+ */
350
+ export type SessionRestoreOutcome = "pending" | "restored" | "none" | "refused" | "unreachable";
297
351
  export interface CookieStorageOptions {
298
352
  path?: string;
299
353
  domain?: string;
package/dist/backups.d.ts CHANGED
@@ -1,13 +1,20 @@
1
1
  import { Transport } from "./transport.js";
2
- import { type BackupInfo, type BackupDestinationKind } from "@rebasepro/types";
2
+ import { type BackupDownloadLink, type BackupListing } from "@rebasepro/types";
3
3
  export interface CreateBackupsOptions {
4
4
  backupsPath?: string;
5
5
  }
6
+ /** One backup's bytes, as {@link createBackups}' `stream()` answers them. */
7
+ export interface BackupStream {
8
+ /** The dump, read from the server as it is consumed. */
9
+ stream: ReadableStream<Uint8Array>;
10
+ /** Its size in bytes, when the server said. */
11
+ size?: number;
12
+ /** Its file name: the key's last segment, as the server names the download. */
13
+ name: string;
14
+ }
6
15
  export declare function createBackups(transport: Transport, options?: CreateBackupsOptions): {
7
- list: () => Promise<{
8
- backups: BackupInfo[];
9
- destinationKind: BackupDestinationKind;
10
- configured: boolean;
11
- }>;
12
- download: (key: string) => Promise<Blob>;
16
+ list: () => Promise<BackupListing>;
17
+ download: (key: string) => Promise<void>;
18
+ downloadUrl: (key: string) => Promise<BackupDownloadLink>;
19
+ stream: (key: string) => Promise<BackupStream>;
13
20
  };
@@ -1,22 +1,14 @@
1
1
  import { FindParams, Transport } from "./transport.js";
2
2
  import { RebaseWebSocketClient } from "./websocket.js";
3
- import { FindResult, SDKCollectionClient } from "@rebasepro/types";
3
+ import { FindResult, SDKCollectionClient, type ByIdReadOptions, type IncludeSpec, type RestoreOptions, type TrashClient, RebaseClientError } from "@rebasepro/types";
4
+ import { etagOf } from "@rebasepro/common";
4
5
  /**
5
- * The version of a row, when it came straight from a read that reported one.
6
- *
7
- * ```ts
8
- * const post = await client.data.posts.get(1);
9
- * await client.data.posts.update(1, { title: "New" }, { ifMatch: etagOf(post) });
10
- * ```
11
- *
12
- * `undefined` for a row from `find()` (a list response carries one ETag at
13
- * most, and it would not be this row's), from the offline cache, or from a
14
- * server that does not send them. Passing `undefined` as `ifMatch` sends no
15
- * precondition, so the call above degrades to an ordinary update rather than
16
- * failing — which is the right default, and the reason to read this at the call
17
- * site where the choice is visible.
6
+ * A bulk call given something other than an array. A `RebaseClientError` with
7
+ * the code the server uses for the same mistake in a request body, so one
8
+ * `case "INVALID_BULK_BODY"` covers both.
18
9
  */
19
- export declare function etagOf(row: unknown): string | undefined;
10
+ export declare function invalidBulkBody(message: string): RebaseClientError;
11
+ export { etagOf };
20
12
  /**
21
13
  * A live query result: a normal {@link FindResult} plus what an interface
22
14
  * needs to decide whether to show a "saving…" or "offline" affordance over it.
@@ -51,6 +43,25 @@ export interface ObserveOptions {
51
43
  */
52
44
  realtime?: boolean;
53
45
  }
46
+ /**
47
+ * Options for `observeById`: {@link ObserveOptions}, plus the relations to load
48
+ * into the row. `include` reaches both of its reads — the one-shot
49
+ * `findById` and the `listenById` subscription — so every emission carries
50
+ * the same relations.
51
+ */
52
+ export interface ObserveByIdOptions<Inc = IncludeSpec> extends ObserveOptions, ByIdReadOptions<Inc> {
53
+ }
54
+ /**
55
+ * {@link TrashClient} and {@link RestoreOptions} are the transport-agnostic
56
+ * contract in `@rebasepro/types`. On this client every call goes to the
57
+ * server. With `offline` enabled the trash is not cached and nothing in it is
58
+ * queued: the local database never holds a trashed row, so it cannot answer
59
+ * for one, and a restore or a purge made offline would act on a row this
60
+ * device cannot see. They reject with `OFFLINE` instead (see
61
+ * `isOfflineError`). A restored row joins the local database; a purged one
62
+ * leaves it.
63
+ */
64
+ export type { RestoreOptions, TrashClient };
54
65
  /**
55
66
  * The concrete, HTTP-backed implementation of the public
56
67
  * {@link SDKCollectionClient} contract — flat rows (no Entity wrapper), plus
@@ -61,8 +72,13 @@ export interface ObserveOptions {
61
72
  * `count()` and the reactive `observe()` pair. Program against
62
73
  * {@link SDKCollectionClient} when you want a transport-agnostic type.
63
74
  */
64
- export interface CollectionClient<M extends Record<string, unknown> = Record<string, unknown>, I = Partial<M>, U = Partial<M>> extends SDKCollectionClient<M, I, U> {
65
- count(params?: FindParams<M>): Promise<number>;
75
+ export interface CollectionClient<M extends Record<string, unknown> = Record<string, unknown>, I = Partial<M>, U = Partial<M>, Inc = IncludeSpec> extends SDKCollectionClient<M, I, U, Inc> {
76
+ count(params?: FindParams<M, Inc>): Promise<number>;
77
+ /**
78
+ * The collection's trash: list, count, restore and purge the rows a soft
79
+ * delete stamped. See {@link TrashClient}.
80
+ */
81
+ trash: TrashClient<M, Inc>;
66
82
  /**
67
83
  * Subscribe to a query's results.
68
84
  *
@@ -78,8 +94,13 @@ export interface CollectionClient<M extends Record<string, unknown> = Record<str
78
94
  *
79
95
  * @returns An unsubscribe function.
80
96
  */
81
- observe(params: FindParams<M> | undefined, onResult: (result: LiveResult<M>) => void, onError?: (error: Error) => void, options?: ObserveOptions): () => void;
97
+ observe(params: FindParams<M, Inc> | undefined, onResult: (result: LiveResult<M>) => void, onError?: (error: Error) => void, options?: ObserveOptions): () => void;
82
98
  /** {@link CollectionClient.observe} for a single row. */
83
- observeById(id: string | number, onResult: (row: M | undefined, meta: RowSnapshotMeta) => void, onError?: (error: Error) => void, options?: ObserveOptions): () => void;
99
+ observeById(id: string | number, onResult: (row: M | undefined, meta: RowSnapshotMeta) => void, onError?: (error: Error) => void, options?: ObserveByIdOptions<Inc>): () => void;
84
100
  }
101
+ /**
102
+ * The part of {@link ObserveByIdOptions} that is a read option: `include`, and
103
+ * nothing else, so `realtime` never travels as a query parameter.
104
+ */
105
+ export declare function byIdRead<Inc>(options: ObserveByIdOptions<Inc> | undefined): ByIdReadOptions<Inc> | undefined;
85
106
  export declare function createCollectionClient<M extends Record<string, unknown> = Record<string, unknown>>(transport: Transport, slug: string, ws?: RebaseWebSocketClient): CollectionClient<M>;
package/dist/cron.d.ts CHANGED
@@ -1,19 +1,24 @@
1
1
  import { Transport } from "./transport.js";
2
- import type { CronJobStatus, CronJobLogEntry } from "@rebasepro/types";
2
+ import type { CronJobStatus, CronJobLogEntry, CronJobListing, CronJobStarted } from "@rebasepro/types";
3
3
  export interface CreateCronOptions {
4
4
  cronPath?: string;
5
5
  }
6
6
  export declare function createCron(transport: Transport, options?: CreateCronOptions): {
7
- listJobs: () => Promise<{
8
- jobs: CronJobStatus[];
9
- }>;
7
+ listJobs: () => Promise<CronJobListing>;
10
8
  getJob: (jobId: string) => Promise<{
11
9
  job: CronJobStatus;
12
10
  }>;
13
- triggerJob: (jobId: string) => Promise<{
14
- log: CronJobLogEntry;
15
- job: CronJobStatus;
16
- }>;
11
+ triggerJob: {
12
+ (jobId: string, options?: {
13
+ async?: false;
14
+ }): Promise<{
15
+ log: CronJobLogEntry;
16
+ job: CronJobStatus;
17
+ }>;
18
+ (jobId: string, options: {
19
+ async: true;
20
+ }): Promise<CronJobStarted>;
21
+ };
17
22
  getJobLogs: (jobId: string, options?: {
18
23
  limit?: number;
19
24
  }) => Promise<{
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Compile-time assertion that a consumer can name, from `@rebasepro/client`
3
+ * alone, the types its own calls are written in.
4
+ *
5
+ * A plain module under `src`, imported by nothing, for the reason
6
+ * `query-contract.types.ts` gives: `pnpm typecheck` reads `src`, and a type
7
+ * assertion in a jest test is checked by nothing. A browser app installs this
8
+ * package only, so an argument type missing from the barrel is one it has to
9
+ * spell out by hand or reach into a package it never installed.
10
+ */
11
+ import type { AggregateMeta, AggregateParams, AggregateResult, AggregateRow, AggregateSelect, FieldPath, FilterCondition, FilterConditionFor, FilterValues, IncludeOptions, IncludeSpec, InsertOf, LogicalCondition, LogicalConditionFor, OrderBySpec, QueryComputedFields, RestoreOptions, RowOf, StorageSource, TrashClient, UpdateOf, WhereConditionFor, WhereFilterOp, WhereFor, WhereValueFor, WriteOptions } from "./index.js";
12
+ export type ConsumerCanName = [
13
+ AggregateMeta,
14
+ AggregateParams,
15
+ AggregateResult,
16
+ AggregateRow,
17
+ AggregateSelect,
18
+ FieldPath,
19
+ FilterCondition,
20
+ FilterValues<string>,
21
+ IncludeOptions,
22
+ IncludeSpec,
23
+ InsertOf<Record<string, unknown>>,
24
+ LogicalCondition,
25
+ OrderBySpec,
26
+ FilterConditionFor<Record<string, unknown>>,
27
+ LogicalConditionFor<Record<string, unknown>>,
28
+ QueryComputedFields,
29
+ RowOf<Record<string, unknown>>,
30
+ StorageSource,
31
+ UpdateOf<Record<string, unknown>>,
32
+ WhereConditionFor<string>,
33
+ WhereFilterOp,
34
+ WhereFor<Record<string, unknown>>,
35
+ WhereValueFor<"==", string>,
36
+ WriteOptions,
37
+ RestoreOptions,
38
+ TrashClient
39
+ ];
@@ -28,21 +28,11 @@ export interface FunctionsClient {
28
28
  * One path segment: a sub-path goes in `options.path`.
29
29
  * @param payload - Optional JSON-serialisable body. Dropped for `GET`.
30
30
  * @param options - Optional overrides (HTTP method, sub-path, extra headers).
31
- * @returns The parsed JSON response from the function.
31
+ * @returns The parsed JSON response from the function, or — with
32
+ * `options.responseType` — its text, a `Blob`, or the raw `Response`.
32
33
  */
33
34
  invoke<T = unknown>(name: string, payload?: unknown, options?: FunctionInvokeOptions): Promise<T>;
34
35
  }
35
36
  export type { FunctionInvokeOptions } from "@rebasepro/types";
36
37
  import type { FunctionInvokeOptions } from "@rebasepro/types";
37
- /**
38
- * Create a `FunctionsClient` backed by the given transport.
39
- *
40
- * The transport already handles:
41
- * - Base URL resolution
42
- * - JWT injection via `Authorization: Bearer`
43
- * - 401 retry / `onUnauthorized` flow
44
- * - Consistent error throwing via `RebaseApiError`
45
- *
46
- * @internal
47
- */
48
38
  export declare function createFunctionsClient(transport: Transport): FunctionsClient;