@rebasepro/client 0.7.0 → 0.9.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.
@@ -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
+ }
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Client-side storage source registry.
3
+ *
4
+ * Manages multiple `StorageSource` instances keyed by
5
+ * `StorageSourceDefinition.key`. Collection properties reference
6
+ * a source by key via `StorageConfig.storageSource`.
7
+ *
8
+ * Typical bootstrap flow:
9
+ * 1. Fetch definitions from `GET /api/storage/sources`
10
+ * 2. Build server-backed sources automatically via `createStorage(transport, key)`
11
+ * 3. Register "direct" sources manually (e.g. Firebase Storage hook)
12
+ */
13
+ import type { StorageSource, StorageSourceRegistry, StorageSourceDefinition } from "@rebasepro/types";
14
+ import type { Transport } from "./transport";
15
+ /**
16
+ * Default implementation of the client-side `StorageSourceRegistry`.
17
+ */
18
+ export declare class ClientStorageSourceRegistry implements StorageSourceRegistry {
19
+ private sources;
20
+ /**
21
+ * Register a storage source.
22
+ * @param key - Unique key matching a `StorageSourceDefinition.key`
23
+ * @param source - The `StorageSource` instance
24
+ */
25
+ register(key: string, source: StorageSource): void;
26
+ getDefault(): StorageSource;
27
+ get(key: string | undefined | null): StorageSource | undefined;
28
+ getOrDefault(key: string | undefined | null): StorageSource;
29
+ has(key: string): boolean;
30
+ list(): string[];
31
+ /**
32
+ * Build a registry from `StorageSourceDefinition[]` and an HTTP transport.
33
+ *
34
+ * - Sources with `transport: "server"` are auto-wired via `createStorage(transport, key)`.
35
+ * - Sources with `transport: "direct"` are **not** auto-wired — they must
36
+ * be registered manually after this call (e.g. via a Firebase hook).
37
+ *
38
+ * @param definitions - Array of storage source definitions
39
+ * @param transport - HTTP transport for server-backed sources
40
+ */
41
+ static fromDefinitions(definitions: StorageSourceDefinition[], transport: Transport): ClientStorageSourceRegistry;
42
+ }
package/dist/storage.d.ts CHANGED
@@ -1,3 +1,11 @@
1
1
  import { StorageSource } from "@rebasepro/types";
2
2
  import { Transport } from "./transport";
3
- export declare function createStorage(transport: Transport): StorageSource;
3
+ /**
4
+ * Create a StorageSource that talks to the Rebase backend REST API.
5
+ *
6
+ * @param transport - HTTP transport instance
7
+ * @param storageId - Optional storage-source key for multi-backend routing.
8
+ * When set, it is forwarded to the server so the correct
9
+ * `StorageController` is resolved from the registry.
10
+ */
11
+ export declare function createStorage(transport: Transport, storageId?: string): StorageSource;
@@ -1,4 +1,6 @@
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 {
3
5
  baseUrl?: string;
4
6
  token?: string;
@@ -12,12 +14,6 @@ export interface RebaseClientConfig {
12
14
  */
13
15
  export type FindParams = TypesFindParams;
14
16
  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
17
  export declare function buildQueryString(params?: FindParams): string;
22
18
  export interface Transport {
23
19
  request: <T = unknown>(path: string, init?: RequestInit) => Promise<T>;
@@ -1,4 +1,4 @@
1
- import { DeleteEntityProps, Entity, EntityCollection, FetchCollectionProps, FetchEntityProps, SaveEntityProps, TableMetadata, BranchInfo } from "@rebasepro/types";
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,11 +8,15 @@ export interface RebaseWebSocketConfig {
8
8
  /** Callback to handle unauthorized requests or token expiration (refreshes auth session) */
9
9
  onUnauthorized?: () => Promise<boolean>;
10
10
  }
11
- export declare class ApiError extends Error {
12
- code?: string;
13
- error?: string;
14
- constructor(message: string, error?: string, code?: string);
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-postgresql` 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;
@@ -22,7 +26,7 @@ export declare class RebaseWebSocketClient {
22
26
  on(event: "connect" | "disconnect" | "reconnect" | "error", cb: (...args: unknown[]) => void): () => boolean;
23
27
  private emit;
24
28
  private collectionSubscriptions;
25
- private entitySubscriptions;
29
+ private singleSubscriptions;
26
30
  private backendToCollectionKey;
27
31
  private backendToEntityKey;
28
32
  private pendingRequests;
@@ -53,7 +57,7 @@ export declare class RebaseWebSocketClient {
53
57
  private isAuthError;
54
58
  private handleAuthFailure;
55
59
  /**
56
- * Shared logic for re-subscribing a collection or entity subscription
60
+ * Shared logic for re-subscribing a collection or row subscription
57
61
  * after an auth error is resolved by refreshing credentials.
58
62
  */
59
63
  private resubscribeAfterAuthRefresh;
@@ -62,10 +66,10 @@ export declare class RebaseWebSocketClient {
62
66
  reauthenticate(): Promise<void>;
63
67
  private sendMessage;
64
68
  private doSendMessage;
65
- fetchCollection<M extends Record<string, unknown>>(props: FetchCollectionProps<M>): Promise<Entity<M>[]>;
66
- fetchEntity<M extends Record<string, unknown>>(props: FetchEntityProps<M>): Promise<Entity<M> | undefined>;
67
- saveEntity<M extends Record<string, unknown>>(props: SaveEntityProps<M>): Promise<Entity<M>>;
68
- deleteEntity<M extends Record<string, unknown>>(props: DeleteEntityProps<M>): Promise<void>;
69
+ fetchCollection<M extends Record<string, unknown>>(props: FetchCollectionProps<M>): Promise<Record<string, unknown>[]>;
70
+ fetchOne<M extends Record<string, unknown>>(props: FetchOneProps<M>): Promise<Record<string, unknown> | undefined>;
71
+ save<M extends Record<string, unknown>>(props: SaveProps<M>): Promise<Record<string, unknown>>;
72
+ delete<M extends Record<string, unknown>>(props: DeleteProps<M>): Promise<void>;
69
73
  executeSql(sql: string, options?: {
70
74
  database?: string;
71
75
  role?: string;
@@ -73,8 +77,8 @@ export declare class RebaseWebSocketClient {
73
77
  fetchAvailableDatabases(): Promise<string[]>;
74
78
  fetchAvailableRoles(): Promise<string[]>;
75
79
  fetchCurrentDatabase(): Promise<string | undefined>;
76
- checkUniqueField(path: string, name: string, value: unknown, entityId?: string, collection?: EntityCollection): Promise<boolean>;
77
- countEntities<M extends Record<string, unknown>>(props: FetchCollectionProps<M>): Promise<number>;
80
+ checkUniqueField(path: string, name: string, value: unknown, id?: string, collection?: CollectionConfig): Promise<boolean>;
81
+ count<M extends Record<string, unknown>>(props: FetchCollectionProps<M>): Promise<number>;
78
82
  fetchUnmappedTables(mappedPaths?: string[]): Promise<string[]>;
79
83
  fetchTableMetadata(tableName: string): Promise<TableMetadata>;
80
84
  createBranch(name: string, options?: {
@@ -89,14 +93,14 @@ export declare class RebaseWebSocketClient {
89
93
  private deepEqual;
90
94
  private normalizeForComparison;
91
95
  /**
92
- * Merge incoming entities with cached data, preserving cached references
93
- * for entities whose values haven't changed. This avoids unnecessary
94
- * React re-renders when the server refetches all entities but most
96
+ * Merge incoming rows with cached data, preserving cached references
97
+ * for rows whose values haven't changed. This avoids unnecessary
98
+ * React re-renders when the server refetches all rows but most
95
99
  * haven't actually changed.
96
100
  */
97
- private mergeEntities;
98
- listenCollection<M extends Record<string, unknown>>(props: FetchCollectionProps<M>, onUpdate: (entities: Entity[]) => void, onError?: (error: Error) => void): () => void;
99
- listenEntity<M extends Record<string, unknown>>(props: FetchEntityProps<M>, onUpdate: (entity: Entity | null) => void, onError?: (error: Error) => void): () => void;
101
+ private mergeRows;
102
+ listenCollection<M extends Record<string, unknown>>(props: FetchCollectionProps<M>, onUpdate: (rows: Record<string, unknown>[]) => void, onError?: (error: Error) => void): () => void;
103
+ listenOne<M extends Record<string, unknown>>(props: FetchOneProps<M>, onUpdate: (row: Record<string, unknown> | null) => void, onError?: (error: Error) => void): () => void;
100
104
  /**
101
105
  * Re-send all active subscriptions to the backend after a reconnect.
102
106
  * The server wipes subscription state when a client disconnects, so
@@ -104,5 +108,5 @@ export declare class RebaseWebSocketClient {
104
108
  */
105
109
  private resubscribeAll;
106
110
  private createCollectionSubscriptionKey;
107
- private createEntitySubscriptionKey;
111
+ private createSingleSubscriptionKey;
108
112
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@rebasepro/client",
3
3
  "type": "module",
4
- "version": "0.7.0",
4
+ "version": "0.9.0",
5
5
  "description": "HTTP SDK client for the Rebase custom backend",
6
6
  "funding": {
7
7
  "url": "https://github.com/sponsors/rebaseco"
@@ -20,13 +20,6 @@
20
20
  "engines": {
21
21
  "node": ">=14"
22
22
  },
23
- "scripts": {
24
- "watch": "vite build --watch",
25
- "build": "vite build && tsc --emitDeclarationOnly -p tsconfig.prod.json",
26
- "test:lint": "eslint \"src/**\" --quiet",
27
- "test": "jest --passWithNoTests --forceExit",
28
- "clean": "rm -rf dist && find ./src -name '*.js' -type f | xargs rm -f"
29
- },
30
23
  "exports": {
31
24
  ".": {
32
25
  "types": "./dist/index.d.ts",
@@ -37,9 +30,9 @@
37
30
  "./package.json": "./package.json"
38
31
  },
39
32
  "dependencies": {
40
- "@rebasepro/common": "workspace:*",
41
- "@rebasepro/types": "workspace:*",
42
- "@rebasepro/utils": "workspace:*"
33
+ "@rebasepro/types": "0.9.0",
34
+ "@rebasepro/utils": "0.9.0",
35
+ "@rebasepro/common": "0.9.0"
43
36
  },
44
37
  "devDependencies": {
45
38
  "@jest/globals": "^30.4.1",
@@ -75,8 +68,16 @@
75
68
  ],
76
69
  "testEnvironment": "node",
77
70
  "moduleNameMapper": {
71
+ "^@rebasepro/common$": "<rootDir>/../common/src/index.ts",
78
72
  "^@rebasepro/types$": "<rootDir>/../types/src/index.ts",
79
73
  "^@rebasepro/utils$": "<rootDir>/../utils/src/index.ts"
80
74
  }
75
+ },
76
+ "scripts": {
77
+ "watch": "vite build --watch",
78
+ "build": "vite build && tsc --emitDeclarationOnly -p tsconfig.prod.json",
79
+ "test:lint": "eslint \"src/**\" --quiet",
80
+ "test": "jest --passWithNoTests --forceExit",
81
+ "clean": "rm -rf dist && find ./src -name '*.js' -type f | xargs rm -f"
81
82
  }
82
- }
83
+ }
package/src/api-keys.ts CHANGED
@@ -15,6 +15,7 @@ export interface ApiKeyMasked {
15
15
  name: string;
16
16
  key_prefix: string;
17
17
  permissions: ApiKeyPermission[];
18
+ admin: boolean;
18
19
  rate_limit: number | null;
19
20
  created_by: string;
20
21
  created_at: string;