@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.
- package/LICENSE +21 -0
- package/README.md +10 -10
- package/dist/api-keys.d.ts +1 -0
- package/dist/auth.d.ts +35 -38
- package/dist/collection.d.ts +9 -13
- package/dist/data-proxy.test.d.ts +1 -0
- package/dist/errors.d.ts +9 -0
- package/dist/index.d.ts +41 -21
- package/dist/index.es.js +605 -368
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +616 -379
- package/dist/index.umd.js.map +1 -1
- package/dist/sdk_query_builder.d.ts +63 -0
- package/dist/storage-registry.d.ts +42 -0
- package/dist/storage.d.ts +9 -1
- package/dist/transport.d.ts +2 -6
- package/dist/websocket.d.ts +25 -21
- package/package.json +13 -12
- package/src/api-keys.ts +1 -0
- package/src/auth.ts +188 -64
- package/src/collection.test.ts +94 -5
- package/src/collection.ts +103 -184
- package/src/data-proxy.test.ts +167 -0
- package/src/errors.ts +9 -0
- package/src/index.ts +218 -24
- package/src/reviver.ts +2 -2
- package/src/sdk_query_builder.ts +138 -0
- package/src/storage-registry.ts +102 -0
- package/src/storage.ts +92 -50
- package/src/transport.ts +31 -105
- package/src/websocket.ts +133 -135
|
@@ -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
|
-
|
|
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;
|
package/dist/transport.d.ts
CHANGED
|
@@ -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>;
|
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,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
|
-
|
|
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-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
|
|
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
|
|
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<
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
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,
|
|
77
|
-
|
|
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
|
|
93
|
-
* for
|
|
94
|
-
* React re-renders when the server refetches all
|
|
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
|
|
98
|
-
listenCollection<M extends Record<string, unknown>>(props: FetchCollectionProps<M>, onUpdate: (
|
|
99
|
-
|
|
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
|
|
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.
|
|
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/
|
|
41
|
-
"@rebasepro/
|
|
42
|
-
"@rebasepro/
|
|
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
|
+
}
|