@rebasepro/client 0.23.0 → 0.24.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/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;
@@ -41,12 +41,17 @@ export declare function createAdmin(transport: Transport, options?: CreateAdminO
41
41
  displayName?: string;
42
42
  password?: string;
43
43
  roles?: string[];
44
+ disabled?: boolean;
44
45
  }) => Promise<{
45
46
  user: AdminUser;
46
47
  }>;
47
48
  deleteUser: (userId: string) => Promise<{
48
49
  success: boolean;
49
50
  }>;
51
+ resetMfa: (userId: string) => Promise<{
52
+ success: boolean;
53
+ removedFactors: number;
54
+ }>;
50
55
  resetPassword: (userId: string, options?: {
51
56
  password?: string;
52
57
  }) => Promise<{
@@ -56,10 +61,7 @@ export declare function createAdmin(transport: Transport, options?: CreateAdminO
56
61
  emailDeliveryFailed?: boolean;
57
62
  }>;
58
63
  listRoles: () => Promise<{
59
- roles: Array<{
60
- id: string;
61
- name: string;
62
- }>;
64
+ roles: RoleSummary[];
63
65
  }>;
64
66
  bootstrap: () => Promise<{
65
67
  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<{
@@ -191,6 +201,14 @@ export declare function createAuth(transport: Transport, options?: CreateAuthOpt
191
201
  * Remove a factor. Requires an `aal2` session — one that has already
192
202
  * answered a challenge — so a stolen `aal1` token cannot turn MFA off.
193
203
  */
204
+ /**
205
+ * Replace the account's recovery codes with ten new ones, shown once.
206
+ * Needs an `aal2` session. Adding a second factor keeps the codes the
207
+ * account already has; this is how to get new ones.
208
+ */
209
+ regenerateRecoveryCodes(): Promise<{
210
+ recoveryCodes: string[];
211
+ }>;
194
212
  unenroll(factorId: string): Promise<{
195
213
  success: boolean;
196
214
  message: string;
@@ -258,9 +276,23 @@ export declare function createAuth(transport: Transport, options?: CreateAuthOpt
258
276
  success: boolean;
259
277
  message: string;
260
278
  }>;
261
- verifyEmail: (token: string) => Promise<{
279
+ verifyEmail: (token: string, options?: {
280
+ password?: string;
281
+ removeUnproven?: boolean;
282
+ }) => Promise<{
262
283
  success: boolean;
263
- message: string;
284
+ passwordRemoved: boolean;
285
+ removedProviders: string[];
286
+ session: RebaseSession | null;
287
+ }>;
288
+ changeEmail: (newEmail: string) => Promise<{
289
+ pendingEmail: string;
290
+ expiresAt: string;
291
+ }>;
292
+ confirmEmailChange: (token: string) => Promise<{
293
+ uid: string;
294
+ email: string;
295
+ removedProviders: string[];
264
296
  }>;
265
297
  sendMagicLink: (email: string) => Promise<{
266
298
  success: boolean;
@@ -288,7 +320,7 @@ export declare function createAuth(transport: Transport, options?: CreateAuthOpt
288
320
  revokeAllSessions: () => Promise<{
289
321
  success: boolean;
290
322
  }>;
291
- getAuthConfig: () => Promise<AuthAdapterCapabilities>;
323
+ getAuthConfig: () => Promise<AuthConfigDocument>;
292
324
  getSession: () => RebaseSession | null;
293
325
  onAuthStateChange: (callback: (event: AuthChangeEvent, session: RebaseSession | null) => void) => () => boolean;
294
326
  canRestoreSession: () => boolean;
package/dist/backups.d.ts CHANGED
@@ -1,13 +1,9 @@
1
1
  import { Transport } from "./transport.js";
2
- import { type BackupInfo, type BackupDestinationKind } from "@rebasepro/types";
2
+ import { type BackupListing } from "@rebasepro/types";
3
3
  export interface CreateBackupsOptions {
4
4
  backupsPath?: string;
5
5
  }
6
6
  export declare function createBackups(transport: Transport, options?: CreateBackupsOptions): {
7
- list: () => Promise<{
8
- backups: BackupInfo[];
9
- destinationKind: BackupDestinationKind;
10
- configured: boolean;
11
- }>;
7
+ list: () => Promise<BackupListing>;
12
8
  download: (key: string) => Promise<Blob>;
13
9
  };
@@ -1,6 +1,6 @@
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 IncludeSpec } from "@rebasepro/types";
4
4
  /**
5
5
  * The version of a row, when it came straight from a read that reported one.
6
6
  *
@@ -61,8 +61,8 @@ export interface ObserveOptions {
61
61
  * `count()` and the reactive `observe()` pair. Program against
62
62
  * {@link SDKCollectionClient} when you want a transport-agnostic type.
63
63
  */
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>;
64
+ 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> {
65
+ count(params?: FindParams<M, Inc>): Promise<number>;
66
66
  /**
67
67
  * Subscribe to a query's results.
68
68
  *
@@ -78,7 +78,7 @@ export interface CollectionClient<M extends Record<string, unknown> = Record<str
78
78
  *
79
79
  * @returns An unsubscribe function.
80
80
  */
81
- observe(params: FindParams<M> | undefined, onResult: (result: LiveResult<M>) => void, onError?: (error: Error) => void, options?: ObserveOptions): () => void;
81
+ observe(params: FindParams<M, Inc> | undefined, onResult: (result: LiveResult<M>) => void, onError?: (error: Error) => void, options?: ObserveOptions): () => void;
82
82
  /** {@link CollectionClient.observe} for a single row. */
83
83
  observeById(id: string | number, onResult: (row: M | undefined, meta: RowSnapshotMeta) => void, onError?: (error: Error) => void, options?: ObserveOptions): () => void;
84
84
  }
package/dist/cron.d.ts CHANGED
@@ -1,12 +1,10 @@
1
1
  import { Transport } from "./transport.js";
2
- import type { CronJobStatus, CronJobLogEntry } from "@rebasepro/types";
2
+ import type { CronJobStatus, CronJobLogEntry, CronJobListing } 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
  }>;
package/dist/index.d.ts CHANGED
@@ -3,13 +3,13 @@ import { createAuth, CreateAuthOptions } from "./auth.js";
3
3
  import { createAdmin, CreateAdminOptions } from "./admin.js";
4
4
  import { createCron, CreateCronOptions } from "./cron.js";
5
5
  import { createBackups } from "./backups.js";
6
- import { createApiKeys, CreateApiKeysOptions } from "./api-keys.js";
6
+ import { createApiKeys, CreateApiKeysOptions, createPersonalKeys, CreatePersonalKeysOptions } from "./api-keys.js";
7
7
  import { CollectionClient } from "./collection.js";
8
8
  import { createFunctionsClient } from "./functions.js";
9
9
  import { RebaseWebSocketClient } from "./websocket.js";
10
10
  import { RebaseRealtimeChannel, type ChannelOptions } from "./realtime-channel.js";
11
11
  import { type OfflineApi, type OfflineConfig } from "./offline.js";
12
- import { type BatchOperation, type BatchResult, InsertOf, RebaseClient, RebaseSdkData, RowOf, StorageSource, StorageSourceDefinition, StorageSourceRegistry, UpdateOf, type WriteOptions } from "@rebasepro/types";
12
+ import { type BatchOperation, type BatchResult, type IncludeOf, InsertOf, RebaseClient, RebaseSdkData, RowOf, StorageSource, StorageSourceDefinition, StorageSourceRegistry, UpdateOf, type WriteOptions } from "@rebasepro/types";
13
13
  export { RebaseApiError } from "./transport.js";
14
14
  export { RebaseClientError } from "./errors.js";
15
15
  export type { RebaseErrorCode } from "@rebasepro/types";
@@ -20,6 +20,8 @@ export type { IterateParams, FindAllParams, PageWalkOptions, CursorSpec } from "
20
20
  export { RebasePaginationError } from "@rebasepro/common";
21
21
  export type { PaginationErrorCode } from "@rebasepro/common";
22
22
  export { QueryBuilder, or, and, not, cond } from "@rebasepro/common";
23
+ export { resolveStorageReferences, storageReference, parseStorageReference, isStorageReference, STORAGE_REFERENCE_SCHEME } from "@rebasepro/types";
24
+ export type { StorageReferenceTarget, StorageReferenceResolver } from "@rebasepro/types";
23
25
  export { createCookieStorage, createMemoryStorage } from "./auth.js";
24
26
  export type { AuthConfig, AuthStorage, CookieStorageOptions, CreateAuthOptions } from "./auth.js";
25
27
  export type { User, RebaseSession, AuthTokens, AuthChangeEvent, DeviceSession } from "@rebasepro/types";
@@ -28,12 +30,12 @@ export type { AdminUser } from "./admin.js";
28
30
  export type { CreateCronOptions } from "./cron.js";
29
31
  export { createBackups } from "./backups.js";
30
32
  export type { CreateBackupsOptions } from "./backups.js";
31
- export type { ApiKeyMasked, ApiKeyPermission, ApiKeyWithSecret, CreateApiKeyRequest, CreateApiKeysOptions, UpdateApiKeyRequest } from "./api-keys.js";
33
+ export type { ApiKeyKind, ApiKeyMasked, ApiKeyWithSecret, CreateApiKeyRequest, CreateApiKeysOptions, CreatePersonalKeyRequest, CreatePersonalKeysOptions, UpdateApiKeyRequest } from "./api-keys.js";
32
34
  export type { FunctionInvokeOptions, FunctionsClient } from "./functions.js";
33
35
  export { RebaseWebSocketClient } from "./websocket.js";
34
36
  export { RebaseRealtimeChannel } from "./realtime-channel.js";
35
37
  export type { PresenceState, PresenceDiff, BroadcastEvent, ChannelTransport, ChannelOptions, ChannelHistoryEntry, ChannelHistoryResult } from "./realtime-channel.js";
36
- export type { OfflineApi, OfflineConfig, OfflineStatus } from "./offline.js";
38
+ export type { OfflineApi, OfflineConfig, OfflineQueueOptions, OfflineStatus } from "./offline.js";
37
39
  export { isOfflineError } from "./offline.js";
38
40
  export type { LiveResult, ObserveOptions, RowSnapshotMeta } from "./collection.js";
39
41
  export { etagOf } from "./collection.js";
@@ -45,6 +47,7 @@ export interface CreateRebaseClientOptions extends RebaseClientConfig {
45
47
  admin?: CreateAdminOptions;
46
48
  cron?: CreateCronOptions;
47
49
  apiKeys?: CreateApiKeysOptions;
50
+ personalKeys?: CreatePersonalKeysOptions;
48
51
  /**
49
52
  * Declared storage sources for multi-backend support. Server-transport
50
53
  * entries are auto-wired into `client.storageRegistry`; `direct` sources
@@ -77,12 +80,20 @@ export interface CreateRebaseClientOptions extends RebaseClientConfig {
77
80
  offline?: boolean | OfflineConfig;
78
81
  }
79
82
  type KebabToCamelCase<S extends string> = S extends `${infer T}-${infer U}` ? `${T}${Capitalize<KebabToCamelCase<U>>}` : S;
80
- type DBEntry<DB, S extends string> = KebabToCamelCase<S> extends keyof DB ? DB[KebabToCamelCase<S>] : unknown;
83
+ /** The accessor whose generated entry declares `Slug: S`, or `never`. */
84
+ type AccessorOfSlug<DB, S extends string> = {
85
+ [K in keyof DB]: DB[K] extends {
86
+ Slug: S;
87
+ } ? K : never;
88
+ }[keyof DB];
89
+ type DBEntry<DB, S extends string> = [
90
+ AccessorOfSlug<DB, S>
91
+ ] extends [never] ? (KebabToCamelCase<S> extends keyof DB ? DB[KebabToCamelCase<S>] : unknown) : DB[AccessorOfSlug<DB, S>];
81
92
  type TypedDataLayer<DB> = {
82
- collection<S extends string>(slug: S): CollectionClient<RowOf<DBEntry<DB, S>>, InsertOf<DBEntry<DB, S>>, UpdateOf<DBEntry<DB, S>>>;
93
+ collection<S extends string>(slug: S): CollectionClient<RowOf<DBEntry<DB, S>>, InsertOf<DBEntry<DB, S>>, UpdateOf<DBEntry<DB, S>>, IncludeOf<DBEntry<DB, S>, DB>>;
83
94
  } & {
84
- [K in keyof DB]: CollectionClient<RowOf<DB[K]>, InsertOf<DB[K]>, UpdateOf<DB[K]>>;
85
- } & RebaseSdkData;
95
+ [K in keyof DB]: CollectionClient<RowOf<DB[K]>, InsertOf<DB[K]>, UpdateOf<DB[K]>, IncludeOf<DB[K], DB>>;
96
+ } & (string extends keyof DB ? RebaseSdkData : Pick<RebaseSdkData, "collection">);
86
97
  /**
87
98
  * The return type of `createRebaseClient<DB>()`.
88
99
  *
@@ -100,6 +111,7 @@ export type CreateRebaseClientResult<DB = Record<string, unknown>> = Omit<Rebase
100
111
  cron: ReturnType<typeof createCron>;
101
112
  backups: ReturnType<typeof createBackups>;
102
113
  apiKeys: ReturnType<typeof createApiKeys>;
114
+ personalKeys: ReturnType<typeof createPersonalKeys>;
103
115
  functions: ReturnType<typeof createFunctionsClient>;
104
116
  ws?: RebaseWebSocketClient;
105
117
  /**
@@ -147,7 +159,15 @@ export type CreateRebaseClientResult<DB = Record<string, unknown>> = Omit<Rebase
147
159
  * Neither reaches into the response for a `data` key.
148
160
  */
149
161
  call: <T = unknown>(endpoint: string, payload?: unknown) => Promise<T>;
150
- collection: <M extends Record<string, unknown> = Record<string, unknown>>(slug: string) => CollectionClient<M>;
162
+ /**
163
+ * A collection by slug — the same client `data.collection(slug)` returns,
164
+ * typed from the generated `Database` when the slug is one of its
165
+ * collections, or by the row type passed explicitly.
166
+ */
167
+ collection: {
168
+ <S extends string>(slug: S): CollectionClient<RowOf<DBEntry<DB, S>>, InsertOf<DBEntry<DB, S>>, UpdateOf<DBEntry<DB, S>>, IncludeOf<DBEntry<DB, S>, DB>>;
169
+ <M extends Record<string, unknown> = Record<string, unknown>>(slug: string): CollectionClient<M>;
170
+ };
151
171
  /**
152
172
  * Write across collections in one transaction.
153
173
  *
@@ -170,12 +190,17 @@ export type CreateRebaseClientResult<DB = Record<string, unknown>> = Omit<Rebase
170
190
  * `data` is aligned to `operations`: the written row for a create, upsert
171
191
  * or update, and `null` for a delete.
172
192
  *
193
+ * `collection` is the accessor `client.data.<accessor>` takes — `orderItems`
194
+ * for the slug `order_items` — and is sent as the slug through the
195
+ * `collections` dictionary. A name that is not an accessor goes out as
196
+ * written, so an untyped client can still pass the slug.
197
+ *
173
198
  * @example
174
199
  * ```ts
175
200
  * await client.batch([
176
201
  * { op: "create", collection: "orders", values: { total: 40 }, ref: "order" },
177
- * { op: "create", collection: "order_items",
178
- * values: { order_id: { $ref: "order.id" }, sku: "A-1" } },
202
+ * { op: "create", collection: "orderItems",
203
+ * values: { orderId: { $ref: "order.id" }, sku: "A-1" } },
179
204
  * { op: "update", collection: "stock", id: "A-1", values: { count: { $inc: -1 } } }
180
205
  * ]);
181
206
  * ```