@rebasepro/client-postgresql 0.0.1-canary.4d4fb3e → 0.0.1-canary.ca2cb6e

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.
Files changed (52) hide show
  1. package/dist/client/src/admin.d.ts +94 -0
  2. package/dist/client/src/auth.d.ts +161 -0
  3. package/dist/client/src/collection.d.ts +19 -0
  4. package/dist/client/src/cron.d.ts +25 -0
  5. package/dist/client/src/index.d.ts +42 -0
  6. package/dist/client/src/query_builder.d.ts +53 -0
  7. package/dist/client/src/reviver.d.ts +1 -0
  8. package/dist/client/src/storage.d.ts +3 -0
  9. package/dist/client/src/transport.d.ts +33 -0
  10. package/dist/client/src/websocket.d.ts +99 -0
  11. package/dist/index.es.js +28 -17
  12. package/dist/index.es.js.map +1 -1
  13. package/dist/index.umd.js +28 -17
  14. package/dist/index.umd.js.map +1 -1
  15. package/dist/types/src/controllers/auth.d.ts +2 -0
  16. package/dist/types/src/controllers/client.d.ts +119 -7
  17. package/dist/types/src/controllers/collection_registry.d.ts +4 -3
  18. package/dist/types/src/controllers/customization_controller.d.ts +7 -1
  19. package/dist/types/src/controllers/data.d.ts +34 -7
  20. package/dist/types/src/controllers/data_driver.d.ts +20 -28
  21. package/dist/types/src/controllers/database_admin.d.ts +2 -2
  22. package/dist/types/src/controllers/email.d.ts +34 -0
  23. package/dist/types/src/controllers/index.d.ts +1 -0
  24. package/dist/types/src/controllers/local_config_persistence.d.ts +4 -4
  25. package/dist/types/src/controllers/navigation.d.ts +5 -5
  26. package/dist/types/src/controllers/registry.d.ts +6 -3
  27. package/dist/types/src/controllers/side_entity_controller.d.ts +7 -6
  28. package/dist/types/src/controllers/storage.d.ts +24 -26
  29. package/dist/types/src/rebase_context.d.ts +8 -4
  30. package/dist/types/src/types/backend.d.ts +4 -1
  31. package/dist/types/src/types/builders.d.ts +5 -4
  32. package/dist/types/src/types/chips.d.ts +1 -1
  33. package/dist/types/src/types/collections.d.ts +169 -125
  34. package/dist/types/src/types/cron.d.ts +102 -0
  35. package/dist/types/src/types/data_source.d.ts +1 -1
  36. package/dist/types/src/types/entity_actions.d.ts +8 -8
  37. package/dist/types/src/types/entity_callbacks.d.ts +15 -15
  38. package/dist/types/src/types/entity_link_builder.d.ts +1 -1
  39. package/dist/types/src/types/entity_overrides.d.ts +2 -1
  40. package/dist/types/src/types/entity_views.d.ts +8 -8
  41. package/dist/types/src/types/export_import.d.ts +3 -3
  42. package/dist/types/src/types/index.d.ts +1 -0
  43. package/dist/types/src/types/plugins.d.ts +72 -18
  44. package/dist/types/src/types/properties.d.ts +118 -33
  45. package/dist/types/src/types/relations.d.ts +1 -1
  46. package/dist/types/src/types/slots.d.ts +30 -6
  47. package/dist/types/src/types/translations.d.ts +44 -0
  48. package/dist/types/src/types/user_management_delegate.d.ts +1 -0
  49. package/package.json +83 -86
  50. package/src/usePostgresClientDriver.ts +57 -29
  51. package/tsconfig.json +1 -0
  52. package/vite.config.ts +4 -4
@@ -0,0 +1,94 @@
1
+ import { Transport } from "./transport";
2
+ export interface AdminUser {
3
+ uid: string;
4
+ email: string;
5
+ displayName: string | null;
6
+ photoURL: string | null;
7
+ provider: string;
8
+ roles: string[];
9
+ createdAt: string;
10
+ updatedAt: string;
11
+ }
12
+ export interface RebaseRole {
13
+ id: string;
14
+ name: string;
15
+ isAdmin: boolean;
16
+ defaultPermissions: Record<string, unknown> | null;
17
+ config: Record<string, unknown> | null;
18
+ }
19
+ export interface CreateAdminOptions {
20
+ adminPath?: string;
21
+ }
22
+ export declare function createAdmin(transport: Transport, options?: CreateAdminOptions): {
23
+ listUsers: () => Promise<{
24
+ users: AdminUser[];
25
+ }>;
26
+ listUsersPaginated: (options?: {
27
+ search?: string;
28
+ limit?: number;
29
+ offset?: number;
30
+ orderBy?: string;
31
+ orderDir?: "asc" | "desc";
32
+ }) => Promise<{
33
+ users: AdminUser[];
34
+ total: number;
35
+ limit: number;
36
+ offset: number;
37
+ }>;
38
+ getUser: (userId: string) => Promise<{
39
+ user: AdminUser;
40
+ }>;
41
+ createUser: (data: {
42
+ email: string;
43
+ displayName?: string;
44
+ password?: string;
45
+ roles?: string[];
46
+ }) => Promise<{
47
+ user: AdminUser;
48
+ }>;
49
+ updateUser: (userId: string, data: {
50
+ email?: string;
51
+ displayName?: string;
52
+ password?: string;
53
+ roles?: string[];
54
+ }) => Promise<{
55
+ user: AdminUser;
56
+ }>;
57
+ deleteUser: (userId: string) => Promise<{
58
+ success: boolean;
59
+ }>;
60
+ listRoles: () => Promise<{
61
+ roles: RebaseRole[];
62
+ }>;
63
+ getRole: (roleId: string) => Promise<{
64
+ role: RebaseRole;
65
+ }>;
66
+ createRole: (data: {
67
+ id: string;
68
+ name: string;
69
+ isAdmin?: boolean;
70
+ defaultPermissions?: Record<string, unknown>;
71
+ config?: Record<string, unknown>;
72
+ }) => Promise<{
73
+ role: RebaseRole;
74
+ }>;
75
+ updateRole: (roleId: string, data: {
76
+ name?: string;
77
+ isAdmin?: boolean;
78
+ defaultPermissions?: Record<string, unknown>;
79
+ config?: Record<string, unknown>;
80
+ }) => Promise<{
81
+ role: RebaseRole;
82
+ }>;
83
+ deleteRole: (roleId: string) => Promise<{
84
+ success: boolean;
85
+ }>;
86
+ bootstrap: () => Promise<{
87
+ success: boolean;
88
+ message: string;
89
+ user: {
90
+ uid: string;
91
+ roles: string[];
92
+ };
93
+ }>;
94
+ };
@@ -0,0 +1,161 @@
1
+ import { Transport } from "./transport";
2
+ export interface RebaseUser {
3
+ uid: string;
4
+ email: string | null;
5
+ displayName: string | null;
6
+ photoURL: string | null;
7
+ emailVerified?: boolean;
8
+ roles?: string[];
9
+ providerId: string;
10
+ isAnonymous: boolean;
11
+ }
12
+ export interface RebaseTokens {
13
+ accessToken: string;
14
+ refreshToken: string;
15
+ accessTokenExpiresAt: number;
16
+ }
17
+ export interface RebaseSession {
18
+ accessToken: string;
19
+ refreshToken: string;
20
+ expiresAt: number;
21
+ user: RebaseUser;
22
+ }
23
+ export type AuthChangeEvent = "SIGNED_IN" | "SIGNED_OUT" | "TOKEN_REFRESHED" | "USER_UPDATED";
24
+ export interface AuthConfig {
25
+ needsSetup: boolean;
26
+ registrationEnabled: boolean;
27
+ googleEnabled: boolean;
28
+ emailServiceEnabled: boolean;
29
+ }
30
+ export interface AuthStorage {
31
+ getItem: (key: string) => string | null;
32
+ setItem: (key: string, value: string) => void;
33
+ removeItem: (key: string) => void;
34
+ }
35
+ export declare function createMemoryStorage(): AuthStorage;
36
+ export interface CreateAuthOptions {
37
+ storage?: AuthStorage;
38
+ authPath?: string;
39
+ autoRefresh?: boolean;
40
+ persistSession?: boolean;
41
+ }
42
+ export declare function createAuth(transport: Transport, options?: CreateAuthOptions): {
43
+ signInWithEmail: (email: string, password: string) => Promise<{
44
+ user: RebaseUser;
45
+ accessToken: string;
46
+ refreshToken: string;
47
+ }>;
48
+ signUp: (email: string, password: string, displayName?: string) => Promise<{
49
+ user: RebaseUser;
50
+ accessToken: string;
51
+ refreshToken: string;
52
+ }>;
53
+ signInWithGoogle: (idToken: string) => Promise<{
54
+ user: RebaseUser;
55
+ accessToken: string;
56
+ refreshToken: string;
57
+ }>;
58
+ signInWithLinkedin: (code: string, redirectUri: string) => Promise<{
59
+ user: RebaseUser;
60
+ accessToken: string;
61
+ refreshToken: string;
62
+ }>;
63
+ signInWithOAuth: (providerId: string, payload: Record<string, unknown>) => Promise<{
64
+ user: RebaseUser;
65
+ accessToken: string;
66
+ refreshToken: string;
67
+ }>;
68
+ signInWithGitHub: (code: string, redirectUri: string) => Promise<{
69
+ user: RebaseUser;
70
+ accessToken: string;
71
+ refreshToken: string;
72
+ }>;
73
+ signInWithMicrosoft: (code: string, redirectUri: string) => Promise<{
74
+ user: RebaseUser;
75
+ accessToken: string;
76
+ refreshToken: string;
77
+ }>;
78
+ signInWithApple: (code: string, redirectUri: string, user?: {
79
+ name?: {
80
+ firstName?: string;
81
+ lastName?: string;
82
+ };
83
+ email?: string;
84
+ }) => Promise<{
85
+ user: RebaseUser;
86
+ accessToken: string;
87
+ refreshToken: string;
88
+ }>;
89
+ signInWithFacebook: (code: string, redirectUri: string) => Promise<{
90
+ user: RebaseUser;
91
+ accessToken: string;
92
+ refreshToken: string;
93
+ }>;
94
+ signInWithTwitter: (code: string, redirectUri: string, codeVerifier: string) => Promise<{
95
+ user: RebaseUser;
96
+ accessToken: string;
97
+ refreshToken: string;
98
+ }>;
99
+ signInWithDiscord: (code: string, redirectUri: string) => Promise<{
100
+ user: RebaseUser;
101
+ accessToken: string;
102
+ refreshToken: string;
103
+ }>;
104
+ signInWithGitLab: (code: string, redirectUri: string) => Promise<{
105
+ user: RebaseUser;
106
+ accessToken: string;
107
+ refreshToken: string;
108
+ }>;
109
+ signInWithBitbucket: (code: string, redirectUri: string) => Promise<{
110
+ user: RebaseUser;
111
+ accessToken: string;
112
+ refreshToken: string;
113
+ }>;
114
+ signInWithSlack: (code: string, redirectUri: string) => Promise<{
115
+ user: RebaseUser;
116
+ accessToken: string;
117
+ refreshToken: string;
118
+ }>;
119
+ signInWithSpotify: (code: string, redirectUri: string) => Promise<{
120
+ user: RebaseUser;
121
+ accessToken: string;
122
+ refreshToken: string;
123
+ }>;
124
+ signOut: () => Promise<void>;
125
+ refreshSession: () => Promise<RebaseSession>;
126
+ getUser: () => Promise<RebaseUser>;
127
+ updateUser: (updates: {
128
+ displayName?: string;
129
+ photoURL?: string;
130
+ }) => Promise<RebaseUser>;
131
+ resetPasswordForEmail: (email: string) => Promise<{
132
+ success: boolean;
133
+ message: string;
134
+ }>;
135
+ resetPassword: (token: string, password: string) => Promise<{
136
+ success: boolean;
137
+ message: string;
138
+ }>;
139
+ changePassword: (oldPassword: string, newPassword: string) => Promise<{
140
+ success: boolean;
141
+ message: string;
142
+ }>;
143
+ sendVerificationEmail: () => Promise<{
144
+ success: boolean;
145
+ message: string;
146
+ }>;
147
+ verifyEmail: (token: string) => Promise<{
148
+ success: boolean;
149
+ message: string;
150
+ }>;
151
+ getSessions: () => Promise<Record<string, unknown>[]>;
152
+ revokeSession: (sessionId: string) => Promise<{
153
+ success: boolean;
154
+ }>;
155
+ revokeAllSessions: () => Promise<{
156
+ success: boolean;
157
+ }>;
158
+ getAuthConfig: () => Promise<AuthConfig>;
159
+ getSession: () => RebaseSession | null;
160
+ onAuthStateChange: (callback: (event: AuthChangeEvent, session: RebaseSession | null) => void) => () => boolean;
161
+ };
@@ -0,0 +1,19 @@
1
+ import { Transport } from "./transport";
2
+ import { RebaseWebSocketClient } from "./websocket";
3
+ import { CollectionAccessor } from "@rebasepro/types";
4
+ import { FilterOperator, QueryBuilder } from "./query_builder";
5
+ /**
6
+ * CollectionClient extends `CollectionAccessor` from `@rebasepro/types` so that
7
+ * `client.data` can be passed directly to the core Rebase component.
8
+ *
9
+ * Additionally it exposes fluent query builder methods like `.where()`, `.orderBy()`.
10
+ */
11
+ export interface CollectionClient<M extends Record<string, unknown> = Record<string, unknown>> extends CollectionAccessor<M> {
12
+ where(column: keyof M & string, operator: FilterOperator, value: unknown): QueryBuilder<M>;
13
+ orderBy(column: keyof M & string, ascending?: "asc" | "desc"): QueryBuilder<M>;
14
+ limit(count: number): QueryBuilder<M>;
15
+ offset(count: number): QueryBuilder<M>;
16
+ search(searchString: string): QueryBuilder<M>;
17
+ include(...relations: string[]): QueryBuilder<M>;
18
+ }
19
+ export declare function createCollectionClient<M extends Record<string, unknown> = Record<string, unknown>>(transport: Transport, slug: string, ws?: RebaseWebSocketClient): CollectionClient<M>;
@@ -0,0 +1,25 @@
1
+ import { Transport } from "./transport";
2
+ import type { CronJobStatus, CronJobLogEntry } from "@rebasepro/types";
3
+ export interface CreateCronOptions {
4
+ cronPath?: string;
5
+ }
6
+ export declare function createCron(transport: Transport, options?: CreateCronOptions): {
7
+ listJobs: () => Promise<{
8
+ jobs: CronJobStatus[];
9
+ }>;
10
+ getJob: (jobId: string) => Promise<{
11
+ job: CronJobStatus;
12
+ }>;
13
+ triggerJob: (jobId: string) => Promise<{
14
+ log: CronJobLogEntry;
15
+ job: CronJobStatus;
16
+ }>;
17
+ getJobLogs: (jobId: string, options?: {
18
+ limit?: number;
19
+ }) => Promise<{
20
+ logs: CronJobLogEntry[];
21
+ }>;
22
+ toggleJob: (jobId: string, enabled: boolean) => Promise<{
23
+ job: CronJobStatus;
24
+ }>;
25
+ };
@@ -0,0 +1,42 @@
1
+ import { RebaseClientConfig } from "./transport";
2
+ import { createAuth, CreateAuthOptions } from "./auth";
3
+ import { createAdmin, CreateAdminOptions } from "./admin";
4
+ import { createCron, CreateCronOptions } from "./cron";
5
+ import { CollectionClient } from "./collection";
6
+ export * from "./transport";
7
+ export * from "./auth";
8
+ export * from "./admin";
9
+ export * from "./cron";
10
+ export * from "./collection";
11
+ export * from "./websocket";
12
+ export * from "./storage";
13
+ export * from "./reviver";
14
+ export interface CreateRebaseClientOptions extends RebaseClientConfig {
15
+ auth?: CreateAuthOptions;
16
+ admin?: CreateAdminOptions;
17
+ cron?: CreateCronOptions;
18
+ }
19
+ import { RebaseWebSocketClient } from "./websocket";
20
+ import { RebaseClient as BaseRebaseClient, RebaseData, StorageSource } from "@rebasepro/types";
21
+ export type RebaseClient<DB = Record<string, unknown>> = BaseRebaseClient<DB> & {
22
+ setToken: (token: string | null) => void;
23
+ setAuthTokenGetter: (getter: () => Promise<string | null>) => void;
24
+ setOnUnauthorized: (handler: () => Promise<boolean>) => void;
25
+ resolveToken: () => Promise<string | null>;
26
+ auth: ReturnType<typeof createAuth>;
27
+ admin: ReturnType<typeof createAdmin>;
28
+ cron: ReturnType<typeof createCron>;
29
+ ws?: RebaseWebSocketClient;
30
+ storage?: StorageSource;
31
+ call: <T = unknown>(endpoint: string, payload?: unknown) => Promise<T>;
32
+ data: RebaseData & {
33
+ collection<K extends keyof DB>(slug: Extract<K, string>): CollectionClient<DB[K] extends {
34
+ Row: infer R extends Record<string, unknown>;
35
+ } ? R : Record<string, unknown>>;
36
+ } & {
37
+ [K in keyof DB]: CollectionClient<DB[K] extends {
38
+ Row: infer R extends Record<string, unknown>;
39
+ } ? R : Record<string, unknown>>;
40
+ };
41
+ };
42
+ export declare function createRebaseClient<DB = Record<string, unknown>>(options: CreateRebaseClientOptions): RebaseClient<DB>;
@@ -0,0 +1,53 @@
1
+ import { FindResponse } from "@rebasepro/types";
2
+ import { CollectionClient } from "./collection";
3
+ export type FilterOperator = "eq" | "neq" | "gt" | "gte" | "lt" | "lte" | "in" | "nin" | "cs" | "csa" | "==" | "!=" | ">" | ">=" | "<" | "<=" | "array-contains" | "array-contains-any" | "not-in";
4
+ export declare class QueryBuilder<M extends Record<string, unknown> = Record<string, unknown>> {
5
+ private collection;
6
+ private params;
7
+ constructor(collection: CollectionClient<M>);
8
+ /**
9
+ * Add a filter condition to your query.
10
+ * @example
11
+ * client.collection('users').where('age', '>=', 18).find()
12
+ */
13
+ where(column: keyof M & string, operator: FilterOperator, value: unknown): this;
14
+ /**
15
+ * Order the results by a specific column.
16
+ * @example
17
+ * client.collection('users').orderBy('createdAt', 'desc').find()
18
+ */
19
+ orderBy(column: keyof M & string, ascending?: "asc" | "desc"): this;
20
+ /**
21
+ * Limit the number of results returned.
22
+ */
23
+ limit(count: number): this;
24
+ /**
25
+ * Skip the first N results.
26
+ */
27
+ offset(count: number): this;
28
+ /**
29
+ * Set a free-text search string if supported by the backend.
30
+ */
31
+ search(searchString: string): this;
32
+ /**
33
+ * Include related entities in the response.
34
+ * Relations will be populated with full entity data instead of just IDs.
35
+ *
36
+ * @param relations - Relation names to include, or "*" for all.
37
+ * @example
38
+ * // Include specific relations
39
+ * client.data.posts.include("tags", "author").find()
40
+ *
41
+ * // Include all relations
42
+ * client.data.posts.include("*").find()
43
+ */
44
+ include(...relations: string[]): this;
45
+ /**
46
+ * Execute the find query and return the results.
47
+ */
48
+ find(): Promise<FindResponse<M>>;
49
+ /**
50
+ * Listen to realtime updates matching this query.
51
+ */
52
+ listen(onUpdate: (data: FindResponse<M>) => void, onError?: (error: Error) => void): () => void;
53
+ }
@@ -0,0 +1 @@
1
+ export declare function rebaseReviver(_key: string, value: unknown): unknown;
@@ -0,0 +1,3 @@
1
+ import { StorageSource } from "@rebasepro/types";
2
+ import { Transport } from "./transport";
3
+ export declare function createStorage(transport: Transport): StorageSource;
@@ -0,0 +1,33 @@
1
+ import { FindParams as TypesFindParams, FindResponse as TypesFindResponse } from "@rebasepro/types";
2
+ export interface RebaseClientConfig {
3
+ baseUrl?: string;
4
+ token?: string;
5
+ apiPath?: string;
6
+ fetch?: typeof globalThis.fetch;
7
+ onUnauthorized?: () => Promise<boolean>;
8
+ websocketUrl?: string;
9
+ }
10
+ /**
11
+ * Re-export from `@rebasepro/types` for backward compatibility.
12
+ */
13
+ export type FindParams = TypesFindParams;
14
+ 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
+ export declare function buildQueryString(params?: FindParams): string;
22
+ export interface Transport {
23
+ request: <T = unknown>(path: string, init?: RequestInit) => Promise<T>;
24
+ setToken: (newToken: string | null) => void;
25
+ setAuthTokenGetter: (getter: () => Promise<string | null>) => void;
26
+ setOnUnauthorized: (handler: () => Promise<boolean>) => void;
27
+ readonly baseUrl: string;
28
+ readonly apiPath: string;
29
+ readonly fetchFn: typeof globalThis.fetch;
30
+ getHeaders: (init?: RequestInit) => Record<string, string>;
31
+ resolveToken: () => Promise<string | null>;
32
+ }
33
+ export declare function createTransport(config: RebaseClientConfig): Transport;
@@ -0,0 +1,99 @@
1
+ import { DeleteEntityProps, Entity, EntityCollection, FetchCollectionProps, FetchEntityProps, SaveEntityProps, TableMetadata, BranchInfo } from "@rebasepro/types";
2
+ export interface RebaseWebSocketConfig {
3
+ websocketUrl: string;
4
+ /** Optional auth token getter for WebSocket authentication */
5
+ getAuthToken?: () => Promise<string>;
6
+ /** Optional WebSocket constructor to override globalThis.WebSocket (e.g. for Node environments) */
7
+ WebSocket?: typeof WebSocket;
8
+ }
9
+ export declare class ApiError extends Error {
10
+ code?: string;
11
+ error?: string;
12
+ constructor(message: string, error?: string, code?: string);
13
+ }
14
+ export declare class RebaseWebSocketClient {
15
+ private websocketUrl;
16
+ private ws;
17
+ getAuthToken?: () => Promise<string>;
18
+ private subscriptions;
19
+ private listeners;
20
+ on(event: "connect" | "disconnect" | "reconnect" | "error", cb: (...args: unknown[]) => void): () => boolean;
21
+ private emit;
22
+ private collectionSubscriptions;
23
+ private entitySubscriptions;
24
+ private backendToCollectionKey;
25
+ private backendToEntityKey;
26
+ private pendingRequests;
27
+ private reconnectAttempts;
28
+ private maxReconnectAttempts;
29
+ private isConnected;
30
+ private messageQueue;
31
+ private reconnectTimeout;
32
+ private isAuthenticated;
33
+ private authPromise;
34
+ private WebSocketConstructor;
35
+ constructor(config: RebaseWebSocketConfig);
36
+ /**
37
+ * Authenticate the WebSocket connection
38
+ */
39
+ authenticate(token: string): Promise<void>;
40
+ /**
41
+ * Set the auth token getter function
42
+ */
43
+ setAuthTokenGetter(getAuthToken: () => Promise<string>): void;
44
+ disconnect(): void;
45
+ private initWebSocket;
46
+ private processMessageQueue;
47
+ private attemptReconnect;
48
+ private handleWebSocketMessage;
49
+ private ensureAuthenticated;
50
+ /**
51
+ * Force re-authentication (call after token refresh)
52
+ */
53
+ reauthenticate(): Promise<void>;
54
+ private sendMessage;
55
+ private doSendMessage;
56
+ fetchCollection<M extends Record<string, unknown>>(props: FetchCollectionProps<M>): Promise<Entity<M>[]>;
57
+ fetchEntity<M extends Record<string, unknown>>(props: FetchEntityProps<M>): Promise<Entity<M> | undefined>;
58
+ saveEntity<M extends Record<string, unknown>>(props: SaveEntityProps<M>): Promise<Entity<M>>;
59
+ deleteEntity<M extends Record<string, unknown>>(props: DeleteEntityProps<M>): Promise<void>;
60
+ executeSql(sql: string, options?: {
61
+ database?: string;
62
+ role?: string;
63
+ }): Promise<Record<string, unknown>[]>;
64
+ fetchAvailableDatabases(): Promise<string[]>;
65
+ fetchAvailableRoles(): Promise<string[]>;
66
+ fetchCurrentDatabase(): Promise<string | undefined>;
67
+ checkUniqueField(path: string, name: string, value: unknown, entityId?: string, collection?: EntityCollection): Promise<boolean>;
68
+ countEntities<M extends Record<string, unknown>>(props: FetchCollectionProps<M>): Promise<number>;
69
+ fetchUnmappedTables(mappedPaths?: string[]): Promise<string[]>;
70
+ fetchTableMetadata(tableName: string): Promise<TableMetadata>;
71
+ createBranch(name: string, options?: {
72
+ source?: string;
73
+ }): Promise<BranchInfo>;
74
+ deleteBranch(name: string): Promise<void>;
75
+ listBranches(): Promise<BranchInfo[]>;
76
+ /**
77
+ * Recursively compare two values for structural equality.
78
+ * Handles primitives, null, undefined, Date, RegExp, arrays, and plain objects.
79
+ */
80
+ private deepEqual;
81
+ private normalizeForComparison;
82
+ /**
83
+ * Merge incoming entities with cached data, preserving cached references
84
+ * for entities whose values haven't changed. This avoids unnecessary
85
+ * React re-renders when the server refetches all entities but most
86
+ * haven't actually changed.
87
+ */
88
+ private mergeEntities;
89
+ listenCollection<M extends Record<string, unknown>>(props: FetchCollectionProps<M>, onUpdate: (entities: Entity[]) => void, onError?: (error: Error) => void): () => void;
90
+ listenEntity<M extends Record<string, unknown>>(props: FetchEntityProps<M>, onUpdate: (entity: Entity | null) => void, onError?: (error: Error) => void): () => void;
91
+ /**
92
+ * Re-send all active subscriptions to the backend after a reconnect.
93
+ * The server wipes subscription state when a client disconnects, so
94
+ * we need to re-register everything to resume receiving updates.
95
+ */
96
+ private resubscribeAll;
97
+ private createCollectionSubscriptionKey;
98
+ private createEntitySubscriptionKey;
99
+ }
package/dist/index.es.js CHANGED
@@ -121,23 +121,34 @@ function usePostgresClientDriver(config) {
121
121
  isFilterCombinationValid() {
122
122
  return true;
123
123
  },
124
- async executeSql(sql, options) {
125
- return client.executeSql(sql, options);
126
- },
127
- async fetchAvailableDatabases() {
128
- return client.fetchAvailableDatabases();
129
- },
130
- async fetchAvailableRoles() {
131
- return client.fetchAvailableRoles();
132
- },
133
- async fetchCurrentDatabase() {
134
- return client.fetchCurrentDatabase();
135
- },
136
- async fetchUnmappedTables(mappedPaths) {
137
- return client.fetchUnmappedTables(mappedPaths);
138
- },
139
- async fetchTableMetadata(tableName) {
140
- return client.fetchTableMetadata(tableName);
124
+ admin: {
125
+ executeSql(sql, options) {
126
+ return client.executeSql(sql, options);
127
+ },
128
+ fetchAvailableDatabases() {
129
+ return client.fetchAvailableDatabases();
130
+ },
131
+ fetchAvailableRoles() {
132
+ return client.fetchAvailableRoles();
133
+ },
134
+ fetchCurrentDatabase() {
135
+ return client.fetchCurrentDatabase();
136
+ },
137
+ fetchUnmappedTables(mappedPaths) {
138
+ return client.fetchUnmappedTables(mappedPaths);
139
+ },
140
+ fetchTableMetadata(tableName) {
141
+ return client.fetchTableMetadata(tableName);
142
+ },
143
+ createBranch(name_0, options_0) {
144
+ return client.createBranch(name_0, options_0);
145
+ },
146
+ deleteBranch(name_1) {
147
+ return client.deleteBranch(name_1);
148
+ },
149
+ listBranches() {
150
+ return client.listBranches();
151
+ }
141
152
  }
142
153
  };
143
154
  $[0] = client;
@@ -1 +1 @@
1
- {"version":3,"file":"index.es.js","sources":["../src/usePostgresClientDriver.ts"],"sourcesContent":["import { useMemo, useEffect } from \"react\";\nimport {\n DataDriver,\n DeleteEntityProps,\n Entity,\n EntityCollection,\n EntityReference, EntityRelation,\n FetchCollectionProps,\n FetchEntityProps,\n ListenCollectionProps,\n ListenEntityProps,\n SaveEntityProps,\n TableMetadata\n} from \"@rebasepro/types\";\nimport { RebaseWebSocketClient } from \"@rebasepro/client\";\n\nexport interface PostgresDataDriverConfig {\n wsClient?: RebaseWebSocketClient;\n}\n\nexport interface PostgresDataDriver extends DataDriver {\n client?: RebaseWebSocketClient;\n}\n\n\nexport function usePostgresClientDriver(config: PostgresDataDriverConfig): PostgresDataDriver {\n const client = config.wsClient;\n\n return useMemo(() => {\n if (!client) throw new Error(\"RebaseWebSocketClient must be provided in config.wsClient\");\n \n return {\n\n key: \"postgres\",\n\n name: \"PostgreSQL\",\n\n client,\n\n async fetchCollection<M extends Record<string, any>>(props: FetchCollectionProps<M>): Promise<Entity<M>[]> {\n // Pick only the fields the client needs, ignoring extra fields from the CMS layer\n const { path, filter, limit, startAfter, orderBy, searchString, order } = props;\n return client.fetchCollection({ path, filter, limit, startAfter, orderBy, searchString, order }) as Promise<Entity<M>[]>;\n },\n\n async fetchEntity<M extends Record<string, any>>(props: FetchEntityProps<M>): Promise<Entity<M> | undefined> {\n const { path, entityId, databaseId } = props;\n return client.fetchEntity({ path, entityId, databaseId }) as Promise<Entity<M> | undefined>;\n },\n\n async saveEntity<M extends Record<string, any>>(props: SaveEntityProps<M>): Promise<Entity<M>> {\n return client.saveEntity({\n path: props.path,\n values: props.values,\n entityId: props.entityId,\n previousValues: props.previousValues,\n status: props.status\n }) as Promise<Entity<M>>;\n },\n\n async deleteEntity<M extends Record<string, any>>(props: DeleteEntityProps<M>): Promise<void> {\n const { entity } = props;\n return client.deleteEntity({ entity });\n },\n\n async checkUniqueField(path: string, name: string, value: any, entityId?: string, collection?: EntityCollection): Promise<boolean> {\n return client.checkUniqueField(path, name, value, entityId, collection);\n },\n\n async countEntities<M extends Record<string, any>>(props: FetchCollectionProps<M>): Promise<number> {\n const { path, filter, limit, startAfter, orderBy, searchString, order } = props;\n return client.countEntities({ path, filter, limit, startAfter, orderBy, searchString, order });\n },\n\n listenCollection<M extends Record<string, any>>(props: ListenCollectionProps<M>): () => void {\n const { path, filter, limit, startAfter, orderBy, searchString, order, onUpdate, onError } = props;\n return client.listenCollection(\n { path, filter, limit, startAfter, orderBy, searchString, order },\n (entities: Entity[]) => props.onUpdate(entities as Entity<M>[]),\n props.onError\n );\n },\n\n listenEntity<M extends Record<string, any>>(props: ListenEntityProps<M>): () => void {\n const { path, entityId, databaseId, onUpdate, onError } = props;\n return client.listenEntity(\n { path, entityId, databaseId },\n (entity: Entity | null) => {\n props.onUpdate(entity as Entity<M> | null);\n },\n props.onError\n );\n },\n\n isFilterCombinationValid(): boolean {\n return true; // PostgreSQL supports complex filter combinations\n },\n\n async executeSql(sql: string, options?: { database?: string, role?: string }): Promise<any[]> {\n return client.executeSql(sql, options);\n },\n\n async fetchAvailableDatabases(): Promise<string[]> {\n return client.fetchAvailableDatabases();\n },\n\n async fetchAvailableRoles(): Promise<string[]> {\n return client.fetchAvailableRoles();\n },\n\n async fetchCurrentDatabase(): Promise<string | undefined> {\n return client.fetchCurrentDatabase();\n },\n\n async fetchUnmappedTables(mappedPaths?: string[]): Promise<string[]> {\n return client.fetchUnmappedTables(mappedPaths);\n },\n\n async fetchTableMetadata(tableName: string): Promise<TableMetadata> {\n return client.fetchTableMetadata(tableName);\n }\n } as PostgresDataDriver;\n }, [client]);\n\n}\n"],"names":["usePostgresClientDriver","config","$","_c","client","wsClient","t0","Error","t1","key","name","fetchCollection","props","path","filter","limit","startAfter","orderBy","searchString","order","fetchEntity","props_0","path_0","entityId","databaseId","saveEntity","props_1","values","previousValues","status","deleteEntity","props_2","entity","checkUniqueField","path_1","value","entityId_0","collection","countEntities","props_3","path_2","filter_0","limit_0","startAfter_0","orderBy_0","searchString_0","order_0","listenCollection","props_4","path_3","filter_1","limit_1","startAfter_1","orderBy_1","searchString_1","order_1","entities","onUpdate","onError","listenEntity","props_5","path_4","entityId_1","databaseId_0","entity_0","isFilterCombinationValid","executeSql","sql","options","fetchAvailableDatabases","fetchAvailableRoles","fetchCurrentDatabase","fetchUnmappedTables","mappedPaths","fetchTableMetadata","tableName"],"mappings":"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"}
1
+ {"version":3,"file":"index.es.js","sources":["../src/usePostgresClientDriver.ts"],"sourcesContent":["import { useMemo, useEffect } from \"react\";\nimport {\n DataDriver,\n DeleteEntityProps,\n Entity,\n EntityCollection,\n EntityReference, EntityRelation,\n FetchCollectionProps,\n FetchEntityProps,\n ListenCollectionProps,\n ListenEntityProps,\n SaveEntityProps,\n BranchInfo\n} from \"@rebasepro/types\";\nimport { RebaseWebSocketClient } from \"@rebasepro/client\";\n\nexport interface PostgresDataDriverConfig {\n wsClient?: RebaseWebSocketClient;\n}\n\nexport interface PostgresDataDriver extends DataDriver {\n client?: RebaseWebSocketClient;\n}\n\n\nexport function usePostgresClientDriver(config: PostgresDataDriverConfig): PostgresDataDriver {\n const client = config.wsClient;\n\n return useMemo(() => {\n if (!client) throw new Error(\"RebaseWebSocketClient must be provided in config.wsClient\");\n\n return {\n\n key: \"postgres\",\n\n name: \"PostgreSQL\",\n\n client,\n\n async fetchCollection<M extends Record<string, any>>(props: FetchCollectionProps<M>): Promise<Entity<M>[]> {\n // Pick only the fields the client needs, ignoring extra fields from the CMS layer\n const { path, filter, limit, startAfter, orderBy, searchString, order } = props;\n return client.fetchCollection({ path,\nfilter,\nlimit,\nstartAfter,\norderBy,\nsearchString,\norder }) as Promise<Entity<M>[]>;\n },\n\n async fetchEntity<M extends Record<string, any>>(props: FetchEntityProps<M>): Promise<Entity<M> | undefined> {\n const { path, entityId, databaseId } = props;\n return client.fetchEntity({ path,\nentityId,\ndatabaseId }) as Promise<Entity<M> | undefined>;\n },\n\n async saveEntity<M extends Record<string, any>>(props: SaveEntityProps<M>): Promise<Entity<M>> {\n return client.saveEntity({\n path: props.path,\n values: props.values,\n entityId: props.entityId,\n previousValues: props.previousValues,\n status: props.status\n }) as Promise<Entity<M>>;\n },\n\n async deleteEntity<M extends Record<string, any>>(props: DeleteEntityProps<M>): Promise<void> {\n const { entity } = props;\n return client.deleteEntity({ entity });\n },\n\n async checkUniqueField(path: string, name: string, value: any, entityId?: string, collection?: EntityCollection): Promise<boolean> {\n return client.checkUniqueField(path, name, value, entityId, collection);\n },\n\n async countEntities<M extends Record<string, any>>(props: FetchCollectionProps<M>): Promise<number> {\n const { path, filter, limit, startAfter, orderBy, searchString, order } = props;\n return client.countEntities({ path,\nfilter,\nlimit,\nstartAfter,\norderBy,\nsearchString,\norder });\n },\n\n listenCollection<M extends Record<string, any>>(props: ListenCollectionProps<M>): () => void {\n const { path, filter, limit, startAfter, orderBy, searchString, order, onUpdate, onError } = props;\n return client.listenCollection(\n { path,\nfilter,\nlimit,\nstartAfter,\norderBy,\nsearchString,\norder },\n (entities: Entity[]) => props.onUpdate(entities as Entity<M>[]),\n props.onError\n );\n },\n\n listenEntity<M extends Record<string, any>>(props: ListenEntityProps<M>): () => void {\n const { path, entityId, databaseId, onUpdate, onError } = props;\n return client.listenEntity(\n { path,\nentityId,\ndatabaseId },\n (entity: Entity | null) => {\n props.onUpdate(entity as Entity<M> | null);\n },\n props.onError\n );\n },\n\n isFilterCombinationValid(): boolean {\n return true; // PostgreSQL supports complex filter combinations\n },\n\n admin: {\n executeSql(sql: string, options?: { database?: string; role?: string }): Promise<Record<string, unknown>[]> {\n return client.executeSql(sql, options);\n },\n fetchAvailableDatabases(): Promise<string[]> {\n return client.fetchAvailableDatabases();\n },\n fetchAvailableRoles(): Promise<string[]> {\n return client.fetchAvailableRoles();\n },\n fetchCurrentDatabase(): Promise<string | undefined> {\n return client.fetchCurrentDatabase();\n },\n fetchUnmappedTables(mappedPaths?: string[]): Promise<string[]> {\n return client.fetchUnmappedTables(mappedPaths);\n },\n fetchTableMetadata(tableName: string): Promise<unknown> {\n return client.fetchTableMetadata(tableName);\n },\n createBranch(name: string, options?: { source?: string }): Promise<BranchInfo> {\n return client.createBranch(name, options);\n },\n deleteBranch(name: string): Promise<void> {\n return client.deleteBranch(name);\n },\n listBranches(): Promise<BranchInfo[]> {\n return client.listBranches();\n }\n }\n } as PostgresDataDriver;\n }, [client]);\n\n}\n"],"names":["usePostgresClientDriver","config","$","_c","client","wsClient","t0","Error","t1","key","name","fetchCollection","props","path","filter","limit","startAfter","orderBy","searchString","order","fetchEntity","props_0","path_0","entityId","databaseId","saveEntity","props_1","values","previousValues","status","deleteEntity","props_2","entity","checkUniqueField","path_1","value","entityId_0","collection","countEntities","props_3","path_2","filter_0","limit_0","startAfter_0","orderBy_0","searchString_0","order_0","listenCollection","props_4","path_3","filter_1","limit_1","startAfter_1","orderBy_1","searchString_1","order_1","entities","onUpdate","onError","listenEntity","props_5","path_4","entityId_1","databaseId_0","entity_0","isFilterCombinationValid","admin","executeSql","sql","options","fetchAvailableDatabases","fetchAvailableRoles","fetchCurrentDatabase","fetchUnmappedTables","mappedPaths","fetchTableMetadata","tableName","createBranch","name_0","options_0","deleteBranch","name_1","listBranches"],"mappings":"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"}