@rebasepro/client-postgresql 0.8.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/README.md CHANGED
@@ -12,7 +12,7 @@ pnpm add @rebasepro/client-postgresql
12
12
 
13
13
  ## What This Package Does
14
14
 
15
- This package provides a `DataDriver` implementation that bridges Rebase's data layer to a PostgreSQL backend through `@rebasepro/client`'s WebSocket client. It supports full CRUD, realtime collection/entity listeners, unique field validation, entity counting, and admin operations (SQL execution, branch management, table introspection).
15
+ This package provides a `DataDriver` implementation that bridges Rebase's data layer to a PostgreSQL backend through `@rebasepro/client`'s WebSocket client. It supports full CRUD, realtime collection/snapshot listeners, unique field validation, snapshot counting, and admin operations (SQL execution, branch management, table introspection).
16
16
 
17
17
  ## Key Exports
18
18
 
@@ -26,14 +26,14 @@ This package provides a `DataDriver` implementation that bridges Rebase's data l
26
26
 
27
27
  | Method | Description |
28
28
  |---|---|
29
- | `fetchCollection(props)` | Fetch a list of entities with filtering, sorting, pagination, and search |
30
- | `fetchEntity(props)` | Fetch a single entity by path and ID |
31
- | `saveEntity(props)` | Create or update an entity |
32
- | `deleteEntity(props)` | Delete an entity |
33
- | `checkUniqueField(path, name, value, entityId?, collection?)` | Check if a field value is unique |
34
- | `countEntities(props)` | Count entities matching filter criteria |
29
+ | `fetchCollection(props)` | Fetch a list of snapshots with filtering, sorting, pagination, and search |
30
+ | `fetchSnapshot(props)` | Fetch a single snapshot by path and ID |
31
+ | `saveSnapshot(props)` | Create or update a snapshot |
32
+ | `deleteSnapshot(props)` | Delete a snapshot |
33
+ | `checkUniqueField(path, name, value, snapshotId?, collection?)` | Check if a field value is unique |
34
+ | `countSnapshots(props)` | Count snapshots matching filter criteria |
35
35
  | `listenCollection(props)` | Subscribe to realtime collection updates. Returns an unsubscribe function |
36
- | `listenEntity(props)` | Subscribe to realtime entity updates. Returns an unsubscribe function |
36
+ | `listenSnapshot(props)` | Subscribe to realtime snapshot updates. Returns an unsubscribe function |
37
37
  | `isFilterCombinationValid()` | Always returns `true` — PostgreSQL supports complex filter combinations |
38
38
 
39
39
  ### Admin Methods (`driver.admin`)
@@ -71,4 +71,4 @@ function App() {
71
71
  ## Related Packages
72
72
 
73
73
  - `@rebasepro/client` — Provides `RebaseWebSocketClient` used for communication
74
- - `@rebasepro/types` — Shared types (`DataDriver`, `Entity`, `EntityCollection`, etc.)
74
+ - `@rebasepro/types` — Shared types (`DataDriver`, `Snapshot`, `CollectionConfig`, etc.)
package/dist/index.es.js CHANGED
@@ -20,33 +20,33 @@ function usePostgresClientDriver(config) {
20
20
  order
21
21
  });
22
22
  },
23
- async fetchEntity(props) {
24
- const { path, entityId, databaseId } = props;
25
- return client.fetchEntity({
23
+ async fetchOne(props) {
24
+ const { path, id, databaseId } = props;
25
+ return client.fetchOne({
26
26
  path,
27
- entityId,
27
+ id,
28
28
  databaseId
29
29
  });
30
30
  },
31
- async saveEntity(props) {
32
- return client.saveEntity({
31
+ async save(props) {
32
+ return client.save({
33
33
  path: props.path,
34
34
  values: props.values,
35
- entityId: props.entityId,
35
+ id: props.id,
36
36
  previousValues: props.previousValues,
37
37
  status: props.status
38
38
  });
39
39
  },
40
- async deleteEntity(props) {
41
- const { entity } = props;
42
- return client.deleteEntity({ entity });
40
+ async delete(props) {
41
+ const { row } = props;
42
+ return client.delete({ row });
43
43
  },
44
- async checkUniqueField(path, name, value, entityId, collection) {
45
- return client.checkUniqueField(path, name, value, entityId, collection);
44
+ async checkUniqueField(path, name, value, id, collection) {
45
+ return client.checkUniqueField(path, name, value, id, collection);
46
46
  },
47
- async countEntities(props) {
47
+ async count(props) {
48
48
  const { path, filter, limit, startAfter, orderBy, searchString, order } = props;
49
- return client.countEntities({
49
+ return client.count({
50
50
  path,
51
51
  filter,
52
52
  limit,
@@ -66,16 +66,16 @@ function usePostgresClientDriver(config) {
66
66
  orderBy,
67
67
  searchString,
68
68
  order
69
- }, (entities) => props.onUpdate(entities), props.onError);
69
+ }, (rows) => props.onUpdate(rows), props.onError);
70
70
  },
71
- listenEntity(props) {
72
- const { path, entityId, databaseId, onUpdate, onError } = props;
73
- return client.listenEntity({
71
+ listenOne(props) {
72
+ const { path, id, databaseId, onUpdate, onError } = props;
73
+ return client.listenOne({
74
74
  path,
75
- entityId,
75
+ id,
76
76
  databaseId
77
- }, (entity) => {
78
- props.onUpdate(entity);
77
+ }, (row) => {
78
+ props.onUpdate(row);
79
79
  }, props.onError);
80
80
  },
81
81
  isFilterCombinationValid() {
@@ -1 +1 @@
1
- {"version":3,"file":"index.es.js","names":[],"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: unknown, 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"],"mappings":";;AAyBA,SAAgB,wBAAwB,QAAsD;CAC1F,MAAM,SAAS,OAAO;CAEtB,OAAO,cAAc;EACjB,IAAI,CAAC,QAAQ,MAAM,IAAI,MAAM,2DAA2D;EAExF,OAAO;GAEP,KAAK;GAEL,MAAM;GAEN;GAEA,MAAM,gBAA+C,OAAsD;IAEvG,MAAM,EAAE,MAAM,QAAQ,OAAO,YAAY,SAAS,cAAc,UAAU;IAC1E,OAAO,OAAO,gBAAgB;KAAE;KAC5C;KACA;KACA;KACA;KACA;KACA;IAAM,CAAC;GACC;GAEA,MAAM,YAA2C,OAA4D;IACzG,MAAM,EAAE,MAAM,UAAU,eAAe;IACvC,OAAO,OAAO,YAAY;KAAE;KACxC;KACA;IAAW,CAAC;GACJ;GAEA,MAAM,WAA0C,OAA+C;IAC3F,OAAO,OAAO,WAAW;KACrB,MAAM,MAAM;KACZ,QAAQ,MAAM;KACd,UAAU,MAAM;KAChB,gBAAgB,MAAM;KACtB,QAAQ,MAAM;IAClB,CAAC;GACL;GAEA,MAAM,aAA4C,OAA4C;IAC1F,MAAM,EAAE,WAAW;IACnB,OAAO,OAAO,aAAa,EAAE,OAAO,CAAC;GACzC;GAEA,MAAM,iBAAiB,MAAc,MAAc,OAAgB,UAAmB,YAAiD;IACnI,OAAO,OAAO,iBAAiB,MAAM,MAAM,OAAO,UAAU,UAAU;GAC1E;GAEA,MAAM,cAA6C,OAAiD;IAChG,MAAM,EAAE,MAAM,QAAQ,OAAO,YAAY,SAAS,cAAc,UAAU;IAC1E,OAAO,OAAO,cAAc;KAAE;KAC1C;KACA;KACA;KACA;KACA;KACA;IAAM,CAAC;GACC;GAEA,iBAAgD,OAA6C;IACzF,MAAM,EAAE,MAAM,QAAQ,OAAO,YAAY,SAAS,cAAc,OAAO,UAAU,YAAY;IAC7F,OAAO,OAAO,iBACV;KAAE;KAClB;KACA;KACA;KACA;KACA;KACA;IAAM,IACW,aAAuB,MAAM,SAAS,QAAuB,GAC9D,MAAM,OACV;GACJ;GAEA,aAA4C,OAAyC;IACjF,MAAM,EAAE,MAAM,UAAU,YAAY,UAAU,YAAY;IAC1D,OAAO,OAAO,aACV;KAAE;KAClB;KACA;IAAW,IACM,WAA0B;KACvB,MAAM,SAAS,MAA0B;IAC7C,GACA,MAAM,OACV;GACJ;GAEA,2BAAoC;IAChC,OAAO;GACX;GAEA,OAAO;IACH,WAAW,KAAa,SAAoF;KACxG,OAAO,OAAO,WAAW,KAAK,OAAO;IACzC;IACA,0BAA6C;KACzC,OAAO,OAAO,wBAAwB;IAC1C;IACA,sBAAyC;KACrC,OAAO,OAAO,oBAAoB;IACtC;IACA,uBAAoD;KAChD,OAAO,OAAO,qBAAqB;IACvC;IACA,oBAAoB,aAA2C;KAC3D,OAAO,OAAO,oBAAoB,WAAW;IACjD;IACA,mBAAmB,WAAqC;KACpD,OAAO,OAAO,mBAAmB,SAAS;IAC9C;IACA,aAAa,MAAc,SAAoD;KAC3E,OAAO,OAAO,aAAa,MAAM,OAAO;IAC5C;IACA,aAAa,MAA6B;KACtC,OAAO,OAAO,aAAa,IAAI;IACnC;IACA,eAAsC;KAClC,OAAO,OAAO,aAAa;IAC/B;GACJ;EACJ;CACA,GAAG,CAAC,MAAM,CAAC;AAEf"}
1
+ {"version":3,"file":"index.es.js","names":[],"sources":["../src/usePostgresClientDriver.ts"],"sourcesContent":["import { useMemo, useEffect } from \"react\";\nimport {\n DataDriver,\n DeleteProps,\n CollectionConfig,\n FetchCollectionProps,\n FetchOneProps,\n ListenCollectionProps,\n ListenOneProps,\n SaveProps,\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<Record<string, unknown>[]> {\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 });\n },\n\n async fetchOne<M extends Record<string, any>>(props: FetchOneProps<M>): Promise<Record<string, unknown> | undefined> {\n const { path, id, databaseId } = props;\n return client.fetchOne({ path,\nid,\ndatabaseId });\n },\n\n async save<M extends Record<string, any>>(props: SaveProps<M>): Promise<Record<string, unknown>> {\n return client.save({\n path: props.path,\n values: props.values,\n id: props.id,\n previousValues: props.previousValues,\n status: props.status\n });\n },\n\n async delete<M extends Record<string, any>>(props: DeleteProps<M>): Promise<void> {\n const { row } = props;\n return client.delete({ row });\n },\n\n async checkUniqueField(path: string, name: string, value: unknown, id?: string, collection?: CollectionConfig): Promise<boolean> {\n return client.checkUniqueField(path, name, value, id, collection);\n },\n\n async count<M extends Record<string, any>>(props: FetchCollectionProps<M>): Promise<number> {\n const { path, filter, limit, startAfter, orderBy, searchString, order } = props;\n return client.count({ 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 (rows: Record<string, unknown>[]) => props.onUpdate(rows),\n props.onError\n );\n },\n\n listenOne<M extends Record<string, any>>(props: ListenOneProps<M>): () => void {\n const { path, id, databaseId, onUpdate, onError } = props;\n return client.listenOne(\n { path,\nid,\ndatabaseId },\n (row: Record<string, unknown> | null) => {\n props.onUpdate(row);\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"],"mappings":";;AAuBA,SAAgB,wBAAwB,QAAsD;CAC1F,MAAM,SAAS,OAAO;CAEtB,OAAO,cAAc;EACjB,IAAI,CAAC,QAAQ,MAAM,IAAI,MAAM,2DAA2D;EAExF,OAAO;GAEP,KAAK;GAEL,MAAM;GAEN;GAEA,MAAM,gBAA+C,OAAoE;IAErH,MAAM,EAAE,MAAM,QAAQ,OAAO,YAAY,SAAS,cAAc,UAAU;IAC1E,OAAO,OAAO,gBAAgB;KAAE;KAC5C;KACA;KACA;KACA;KACA;KACA;IAAM,CAAC;GACC;GAEA,MAAM,SAAwC,OAAuE;IACjH,MAAM,EAAE,MAAM,IAAI,eAAe;IACjC,OAAO,OAAO,SAAS;KAAE;KACrC;KACA;IAAW,CAAC;GACJ;GAEA,MAAM,KAAoC,OAAuD;IAC7F,OAAO,OAAO,KAAK;KACf,MAAM,MAAM;KACZ,QAAQ,MAAM;KACd,IAAI,MAAM;KACV,gBAAgB,MAAM;KACtB,QAAQ,MAAM;IAClB,CAAC;GACL;GAEA,MAAM,OAAsC,OAAsC;IAC9E,MAAM,EAAE,QAAQ;IAChB,OAAO,OAAO,OAAO,EAAE,IAAI,CAAC;GAChC;GAEA,MAAM,iBAAiB,MAAc,MAAc,OAAgB,IAAa,YAAiD;IAC7H,OAAO,OAAO,iBAAiB,MAAM,MAAM,OAAO,IAAI,UAAU;GACpE;GAEA,MAAM,MAAqC,OAAiD;IACxF,MAAM,EAAE,MAAM,QAAQ,OAAO,YAAY,SAAS,cAAc,UAAU;IAC1E,OAAO,OAAO,MAAM;KAAE;KAClC;KACA;KACA;KACA;KACA;KACA;IAAM,CAAC;GACC;GAEA,iBAAgD,OAA6C;IACzF,MAAM,EAAE,MAAM,QAAQ,OAAO,YAAY,SAAS,cAAc,OAAO,UAAU,YAAY;IAC7F,OAAO,OAAO,iBACV;KAAE;KAClB;KACA;KACA;KACA;KACA;KACA;IAAM,IACW,SAAoC,MAAM,SAAS,IAAI,GACxD,MAAM,OACV;GACJ;GAEA,UAAyC,OAAsC;IAC3E,MAAM,EAAE,MAAM,IAAI,YAAY,UAAU,YAAY;IACpD,OAAO,OAAO,UACV;KAAE;KAClB;KACA;IAAW,IACM,QAAwC;KACrC,MAAM,SAAS,GAAG;IACtB,GACA,MAAM,OACV;GACJ;GAEA,2BAAoC;IAChC,OAAO;GACX;GAEA,OAAO;IACH,WAAW,KAAa,SAAoF;KACxG,OAAO,OAAO,WAAW,KAAK,OAAO;IACzC;IACA,0BAA6C;KACzC,OAAO,OAAO,wBAAwB;IAC1C;IACA,sBAAyC;KACrC,OAAO,OAAO,oBAAoB;IACtC;IACA,uBAAoD;KAChD,OAAO,OAAO,qBAAqB;IACvC;IACA,oBAAoB,aAA2C;KAC3D,OAAO,OAAO,oBAAoB,WAAW;IACjD;IACA,mBAAmB,WAAqC;KACpD,OAAO,OAAO,mBAAmB,SAAS;IAC9C;IACA,aAAa,MAAc,SAAoD;KAC3E,OAAO,OAAO,aAAa,MAAM,OAAO;IAC5C;IACA,aAAa,MAA6B;KACtC,OAAO,OAAO,aAAa,IAAI;IACnC;IACA,eAAsC;KAClC,OAAO,OAAO,aAAa;IAC/B;GACJ;EACJ;CACA,GAAG,CAAC,MAAM,CAAC;AAEf"}
package/dist/index.umd.js CHANGED
@@ -23,33 +23,33 @@
23
23
  order
24
24
  });
25
25
  },
26
- async fetchEntity(props) {
27
- const { path, entityId, databaseId } = props;
28
- return client.fetchEntity({
26
+ async fetchOne(props) {
27
+ const { path, id, databaseId } = props;
28
+ return client.fetchOne({
29
29
  path,
30
- entityId,
30
+ id,
31
31
  databaseId
32
32
  });
33
33
  },
34
- async saveEntity(props) {
35
- return client.saveEntity({
34
+ async save(props) {
35
+ return client.save({
36
36
  path: props.path,
37
37
  values: props.values,
38
- entityId: props.entityId,
38
+ id: props.id,
39
39
  previousValues: props.previousValues,
40
40
  status: props.status
41
41
  });
42
42
  },
43
- async deleteEntity(props) {
44
- const { entity } = props;
45
- return client.deleteEntity({ entity });
43
+ async delete(props) {
44
+ const { row } = props;
45
+ return client.delete({ row });
46
46
  },
47
- async checkUniqueField(path, name, value, entityId, collection) {
48
- return client.checkUniqueField(path, name, value, entityId, collection);
47
+ async checkUniqueField(path, name, value, id, collection) {
48
+ return client.checkUniqueField(path, name, value, id, collection);
49
49
  },
50
- async countEntities(props) {
50
+ async count(props) {
51
51
  const { path, filter, limit, startAfter, orderBy, searchString, order } = props;
52
- return client.countEntities({
52
+ return client.count({
53
53
  path,
54
54
  filter,
55
55
  limit,
@@ -69,16 +69,16 @@
69
69
  orderBy,
70
70
  searchString,
71
71
  order
72
- }, (entities) => props.onUpdate(entities), props.onError);
72
+ }, (rows) => props.onUpdate(rows), props.onError);
73
73
  },
74
- listenEntity(props) {
75
- const { path, entityId, databaseId, onUpdate, onError } = props;
76
- return client.listenEntity({
74
+ listenOne(props) {
75
+ const { path, id, databaseId, onUpdate, onError } = props;
76
+ return client.listenOne({
77
77
  path,
78
- entityId,
78
+ id,
79
79
  databaseId
80
- }, (entity) => {
81
- props.onUpdate(entity);
80
+ }, (row) => {
81
+ props.onUpdate(row);
82
82
  }, props.onError);
83
83
  },
84
84
  isFilterCombinationValid() {
@@ -1 +1 @@
1
- {"version":3,"file":"index.umd.js","names":[],"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: unknown, 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"],"mappings":";;;;;CAyBA,SAAgB,wBAAwB,QAAsD;EAC1F,MAAM,SAAS,OAAO;EAEtB,QAAA,GAAA,MAAA,eAAqB;GACjB,IAAI,CAAC,QAAQ,MAAM,IAAI,MAAM,2DAA2D;GAExF,OAAO;IAEP,KAAK;IAEL,MAAM;IAEN;IAEA,MAAM,gBAA+C,OAAsD;KAEvG,MAAM,EAAE,MAAM,QAAQ,OAAO,YAAY,SAAS,cAAc,UAAU;KAC1E,OAAO,OAAO,gBAAgB;MAAE;MAC5C;MACA;MACA;MACA;MACA;MACA;KAAM,CAAC;IACC;IAEA,MAAM,YAA2C,OAA4D;KACzG,MAAM,EAAE,MAAM,UAAU,eAAe;KACvC,OAAO,OAAO,YAAY;MAAE;MACxC;MACA;KAAW,CAAC;IACJ;IAEA,MAAM,WAA0C,OAA+C;KAC3F,OAAO,OAAO,WAAW;MACrB,MAAM,MAAM;MACZ,QAAQ,MAAM;MACd,UAAU,MAAM;MAChB,gBAAgB,MAAM;MACtB,QAAQ,MAAM;KAClB,CAAC;IACL;IAEA,MAAM,aAA4C,OAA4C;KAC1F,MAAM,EAAE,WAAW;KACnB,OAAO,OAAO,aAAa,EAAE,OAAO,CAAC;IACzC;IAEA,MAAM,iBAAiB,MAAc,MAAc,OAAgB,UAAmB,YAAiD;KACnI,OAAO,OAAO,iBAAiB,MAAM,MAAM,OAAO,UAAU,UAAU;IAC1E;IAEA,MAAM,cAA6C,OAAiD;KAChG,MAAM,EAAE,MAAM,QAAQ,OAAO,YAAY,SAAS,cAAc,UAAU;KAC1E,OAAO,OAAO,cAAc;MAAE;MAC1C;MACA;MACA;MACA;MACA;MACA;KAAM,CAAC;IACC;IAEA,iBAAgD,OAA6C;KACzF,MAAM,EAAE,MAAM,QAAQ,OAAO,YAAY,SAAS,cAAc,OAAO,UAAU,YAAY;KAC7F,OAAO,OAAO,iBACV;MAAE;MAClB;MACA;MACA;MACA;MACA;MACA;KAAM,IACW,aAAuB,MAAM,SAAS,QAAuB,GAC9D,MAAM,OACV;IACJ;IAEA,aAA4C,OAAyC;KACjF,MAAM,EAAE,MAAM,UAAU,YAAY,UAAU,YAAY;KAC1D,OAAO,OAAO,aACV;MAAE;MAClB;MACA;KAAW,IACM,WAA0B;MACvB,MAAM,SAAS,MAA0B;KAC7C,GACA,MAAM,OACV;IACJ;IAEA,2BAAoC;KAChC,OAAO;IACX;IAEA,OAAO;KACH,WAAW,KAAa,SAAoF;MACxG,OAAO,OAAO,WAAW,KAAK,OAAO;KACzC;KACA,0BAA6C;MACzC,OAAO,OAAO,wBAAwB;KAC1C;KACA,sBAAyC;MACrC,OAAO,OAAO,oBAAoB;KACtC;KACA,uBAAoD;MAChD,OAAO,OAAO,qBAAqB;KACvC;KACA,oBAAoB,aAA2C;MAC3D,OAAO,OAAO,oBAAoB,WAAW;KACjD;KACA,mBAAmB,WAAqC;MACpD,OAAO,OAAO,mBAAmB,SAAS;KAC9C;KACA,aAAa,MAAc,SAAoD;MAC3E,OAAO,OAAO,aAAa,MAAM,OAAO;KAC5C;KACA,aAAa,MAA6B;MACtC,OAAO,OAAO,aAAa,IAAI;KACnC;KACA,eAAsC;MAClC,OAAO,OAAO,aAAa;KAC/B;IACJ;GACJ;EACA,GAAG,CAAC,MAAM,CAAC;CAEf"}
1
+ {"version":3,"file":"index.umd.js","names":[],"sources":["../src/usePostgresClientDriver.ts"],"sourcesContent":["import { useMemo, useEffect } from \"react\";\nimport {\n DataDriver,\n DeleteProps,\n CollectionConfig,\n FetchCollectionProps,\n FetchOneProps,\n ListenCollectionProps,\n ListenOneProps,\n SaveProps,\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<Record<string, unknown>[]> {\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 });\n },\n\n async fetchOne<M extends Record<string, any>>(props: FetchOneProps<M>): Promise<Record<string, unknown> | undefined> {\n const { path, id, databaseId } = props;\n return client.fetchOne({ path,\nid,\ndatabaseId });\n },\n\n async save<M extends Record<string, any>>(props: SaveProps<M>): Promise<Record<string, unknown>> {\n return client.save({\n path: props.path,\n values: props.values,\n id: props.id,\n previousValues: props.previousValues,\n status: props.status\n });\n },\n\n async delete<M extends Record<string, any>>(props: DeleteProps<M>): Promise<void> {\n const { row } = props;\n return client.delete({ row });\n },\n\n async checkUniqueField(path: string, name: string, value: unknown, id?: string, collection?: CollectionConfig): Promise<boolean> {\n return client.checkUniqueField(path, name, value, id, collection);\n },\n\n async count<M extends Record<string, any>>(props: FetchCollectionProps<M>): Promise<number> {\n const { path, filter, limit, startAfter, orderBy, searchString, order } = props;\n return client.count({ 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 (rows: Record<string, unknown>[]) => props.onUpdate(rows),\n props.onError\n );\n },\n\n listenOne<M extends Record<string, any>>(props: ListenOneProps<M>): () => void {\n const { path, id, databaseId, onUpdate, onError } = props;\n return client.listenOne(\n { path,\nid,\ndatabaseId },\n (row: Record<string, unknown> | null) => {\n props.onUpdate(row);\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"],"mappings":";;;;;CAuBA,SAAgB,wBAAwB,QAAsD;EAC1F,MAAM,SAAS,OAAO;EAEtB,QAAA,GAAA,MAAA,eAAqB;GACjB,IAAI,CAAC,QAAQ,MAAM,IAAI,MAAM,2DAA2D;GAExF,OAAO;IAEP,KAAK;IAEL,MAAM;IAEN;IAEA,MAAM,gBAA+C,OAAoE;KAErH,MAAM,EAAE,MAAM,QAAQ,OAAO,YAAY,SAAS,cAAc,UAAU;KAC1E,OAAO,OAAO,gBAAgB;MAAE;MAC5C;MACA;MACA;MACA;MACA;MACA;KAAM,CAAC;IACC;IAEA,MAAM,SAAwC,OAAuE;KACjH,MAAM,EAAE,MAAM,IAAI,eAAe;KACjC,OAAO,OAAO,SAAS;MAAE;MACrC;MACA;KAAW,CAAC;IACJ;IAEA,MAAM,KAAoC,OAAuD;KAC7F,OAAO,OAAO,KAAK;MACf,MAAM,MAAM;MACZ,QAAQ,MAAM;MACd,IAAI,MAAM;MACV,gBAAgB,MAAM;MACtB,QAAQ,MAAM;KAClB,CAAC;IACL;IAEA,MAAM,OAAsC,OAAsC;KAC9E,MAAM,EAAE,QAAQ;KAChB,OAAO,OAAO,OAAO,EAAE,IAAI,CAAC;IAChC;IAEA,MAAM,iBAAiB,MAAc,MAAc,OAAgB,IAAa,YAAiD;KAC7H,OAAO,OAAO,iBAAiB,MAAM,MAAM,OAAO,IAAI,UAAU;IACpE;IAEA,MAAM,MAAqC,OAAiD;KACxF,MAAM,EAAE,MAAM,QAAQ,OAAO,YAAY,SAAS,cAAc,UAAU;KAC1E,OAAO,OAAO,MAAM;MAAE;MAClC;MACA;MACA;MACA;MACA;MACA;KAAM,CAAC;IACC;IAEA,iBAAgD,OAA6C;KACzF,MAAM,EAAE,MAAM,QAAQ,OAAO,YAAY,SAAS,cAAc,OAAO,UAAU,YAAY;KAC7F,OAAO,OAAO,iBACV;MAAE;MAClB;MACA;MACA;MACA;MACA;MACA;KAAM,IACW,SAAoC,MAAM,SAAS,IAAI,GACxD,MAAM,OACV;IACJ;IAEA,UAAyC,OAAsC;KAC3E,MAAM,EAAE,MAAM,IAAI,YAAY,UAAU,YAAY;KACpD,OAAO,OAAO,UACV;MAAE;MAClB;MACA;KAAW,IACM,QAAwC;MACrC,MAAM,SAAS,GAAG;KACtB,GACA,MAAM,OACV;IACJ;IAEA,2BAAoC;KAChC,OAAO;IACX;IAEA,OAAO;KACH,WAAW,KAAa,SAAoF;MACxG,OAAO,OAAO,WAAW,KAAK,OAAO;KACzC;KACA,0BAA6C;MACzC,OAAO,OAAO,wBAAwB;KAC1C;KACA,sBAAyC;MACrC,OAAO,OAAO,oBAAoB;KACtC;KACA,uBAAoD;MAChD,OAAO,OAAO,qBAAqB;KACvC;KACA,oBAAoB,aAA2C;MAC3D,OAAO,OAAO,oBAAoB,WAAW;KACjD;KACA,mBAAmB,WAAqC;MACpD,OAAO,OAAO,mBAAmB,SAAS;KAC9C;KACA,aAAa,MAAc,SAAoD;MAC3E,OAAO,OAAO,aAAa,MAAM,OAAO;KAC5C;KACA,aAAa,MAA6B;MACtC,OAAO,OAAO,aAAa,IAAI;KACnC;KACA,eAAsC;MAClC,OAAO,OAAO,aAAa;KAC/B;IACJ;GACJ;EACA,GAAG,CAAC,MAAM,CAAC;CAEf"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@rebasepro/client-postgresql",
3
3
  "type": "module",
4
- "version": "0.8.0",
4
+ "version": "0.9.0",
5
5
  "description": "PostgreSQL data source client for Rebase",
6
6
  "funding": {
7
7
  "url": "https://github.com/sponsors/rebaseco"
@@ -58,8 +58,8 @@
58
58
  "./package.json": "./package.json"
59
59
  },
60
60
  "dependencies": {
61
- "@rebasepro/client": "0.8.0",
62
- "@rebasepro/types": "0.8.0"
61
+ "@rebasepro/client": "0.9.0",
62
+ "@rebasepro/types": "0.9.0"
63
63
  },
64
64
  "peerDependencies": {
65
65
  "react": ">=19.0.0",
@@ -80,6 +80,9 @@
80
80
  "publishConfig": {
81
81
  "access": "public"
82
82
  },
83
+ "files": [
84
+ "dist"
85
+ ],
83
86
  "scripts": {
84
87
  "watch": "vite build --watch",
85
88
  "build": "vite build && tsc --emitDeclarationOnly -p tsconfig.prod.json",
package/src/index.ts DELETED
@@ -1,11 +0,0 @@
1
- /**
2
- * @rebasepro/client-postgresql
3
- *
4
- * PostgreSQL data source client for Rebase
5
- * This package provides a WebSocket-based client for connecting Rebase applications
6
- * to PostgreSQL backends with real-time synchronization capabilities.
7
- */
8
-
9
- // React hooks and data source implementation
10
- export * from "./usePostgresClientDriver";
11
-
@@ -1,153 +0,0 @@
1
- import { useMemo, useEffect } from "react";
2
- import {
3
- DataDriver,
4
- DeleteEntityProps,
5
- Entity,
6
- EntityCollection,
7
- EntityReference, EntityRelation,
8
- FetchCollectionProps,
9
- FetchEntityProps,
10
- ListenCollectionProps,
11
- ListenEntityProps,
12
- SaveEntityProps,
13
- BranchInfo
14
- } from "@rebasepro/types";
15
- import { RebaseWebSocketClient } from "@rebasepro/client";
16
-
17
- export interface PostgresDataDriverConfig {
18
- wsClient?: RebaseWebSocketClient;
19
- }
20
-
21
- export interface PostgresDataDriver extends DataDriver {
22
- client?: RebaseWebSocketClient;
23
- }
24
-
25
-
26
- export function usePostgresClientDriver(config: PostgresDataDriverConfig): PostgresDataDriver {
27
- const client = config.wsClient;
28
-
29
- return useMemo(() => {
30
- if (!client) throw new Error("RebaseWebSocketClient must be provided in config.wsClient");
31
-
32
- return {
33
-
34
- key: "postgres",
35
-
36
- name: "PostgreSQL",
37
-
38
- client,
39
-
40
- async fetchCollection<M extends Record<string, any>>(props: FetchCollectionProps<M>): Promise<Entity<M>[]> {
41
- // Pick only the fields the client needs, ignoring extra fields from the CMS layer
42
- const { path, filter, limit, startAfter, orderBy, searchString, order } = props;
43
- return client.fetchCollection({ path,
44
- filter,
45
- limit,
46
- startAfter,
47
- orderBy,
48
- searchString,
49
- order }) as Promise<Entity<M>[]>;
50
- },
51
-
52
- async fetchEntity<M extends Record<string, any>>(props: FetchEntityProps<M>): Promise<Entity<M> | undefined> {
53
- const { path, entityId, databaseId } = props;
54
- return client.fetchEntity({ path,
55
- entityId,
56
- databaseId }) as Promise<Entity<M> | undefined>;
57
- },
58
-
59
- async saveEntity<M extends Record<string, any>>(props: SaveEntityProps<M>): Promise<Entity<M>> {
60
- return client.saveEntity({
61
- path: props.path,
62
- values: props.values,
63
- entityId: props.entityId,
64
- previousValues: props.previousValues,
65
- status: props.status
66
- }) as Promise<Entity<M>>;
67
- },
68
-
69
- async deleteEntity<M extends Record<string, any>>(props: DeleteEntityProps<M>): Promise<void> {
70
- const { entity } = props;
71
- return client.deleteEntity({ entity });
72
- },
73
-
74
- async checkUniqueField(path: string, name: string, value: unknown, entityId?: string, collection?: EntityCollection): Promise<boolean> {
75
- return client.checkUniqueField(path, name, value, entityId, collection);
76
- },
77
-
78
- async countEntities<M extends Record<string, any>>(props: FetchCollectionProps<M>): Promise<number> {
79
- const { path, filter, limit, startAfter, orderBy, searchString, order } = props;
80
- return client.countEntities({ path,
81
- filter,
82
- limit,
83
- startAfter,
84
- orderBy,
85
- searchString,
86
- order });
87
- },
88
-
89
- listenCollection<M extends Record<string, any>>(props: ListenCollectionProps<M>): () => void {
90
- const { path, filter, limit, startAfter, orderBy, searchString, order, onUpdate, onError } = props;
91
- return client.listenCollection(
92
- { path,
93
- filter,
94
- limit,
95
- startAfter,
96
- orderBy,
97
- searchString,
98
- order },
99
- (entities: Entity[]) => props.onUpdate(entities as Entity<M>[]),
100
- props.onError
101
- );
102
- },
103
-
104
- listenEntity<M extends Record<string, any>>(props: ListenEntityProps<M>): () => void {
105
- const { path, entityId, databaseId, onUpdate, onError } = props;
106
- return client.listenEntity(
107
- { path,
108
- entityId,
109
- databaseId },
110
- (entity: Entity | null) => {
111
- props.onUpdate(entity as Entity<M> | null);
112
- },
113
- props.onError
114
- );
115
- },
116
-
117
- isFilterCombinationValid(): boolean {
118
- return true; // PostgreSQL supports complex filter combinations
119
- },
120
-
121
- admin: {
122
- executeSql(sql: string, options?: { database?: string; role?: string }): Promise<Record<string, unknown>[]> {
123
- return client.executeSql(sql, options);
124
- },
125
- fetchAvailableDatabases(): Promise<string[]> {
126
- return client.fetchAvailableDatabases();
127
- },
128
- fetchAvailableRoles(): Promise<string[]> {
129
- return client.fetchAvailableRoles();
130
- },
131
- fetchCurrentDatabase(): Promise<string | undefined> {
132
- return client.fetchCurrentDatabase();
133
- },
134
- fetchUnmappedTables(mappedPaths?: string[]): Promise<string[]> {
135
- return client.fetchUnmappedTables(mappedPaths);
136
- },
137
- fetchTableMetadata(tableName: string): Promise<unknown> {
138
- return client.fetchTableMetadata(tableName);
139
- },
140
- createBranch(name: string, options?: { source?: string }): Promise<BranchInfo> {
141
- return client.createBranch(name, options);
142
- },
143
- deleteBranch(name: string): Promise<void> {
144
- return client.deleteBranch(name);
145
- },
146
- listBranches(): Promise<BranchInfo[]> {
147
- return client.listBranches();
148
- }
149
- }
150
- } as PostgresDataDriver;
151
- }, [client]);
152
-
153
- }
@@ -1,101 +0,0 @@
1
- import React from "react";
2
- import { renderHook } from "@testing-library/react";
3
- import { usePostgresClientDriver } from "../src/usePostgresClientDriver";
4
-
5
- describe("usePostgresClientDriver hook", () => {
6
- let mockWsClient: any;
7
-
8
- beforeEach(() => {
9
- mockWsClient = {
10
- fetchCollection: jest.fn().mockResolvedValue([{ id: "1",
11
- name: "Entity 1" }]),
12
- fetchEntity: jest.fn().mockResolvedValue({ id: "1",
13
- name: "Entity 1" }),
14
- saveEntity: jest.fn().mockResolvedValue({ id: "1",
15
- name: "Saved Entity" }),
16
- deleteEntity: jest.fn().mockResolvedValue(undefined),
17
- checkUniqueField: jest.fn().mockResolvedValue(true),
18
- countEntities: jest.fn().mockResolvedValue(42),
19
- listenCollection: jest.fn(() => jest.fn()),
20
- listenEntity: jest.fn(() => jest.fn()),
21
- executeSql: jest.fn().mockResolvedValue([]),
22
- fetchAvailableDatabases: jest.fn().mockResolvedValue(["db1"]),
23
- fetchAvailableRoles: jest.fn().mockResolvedValue(["role1"]),
24
- fetchCurrentDatabase: jest.fn().mockResolvedValue("db1"),
25
- fetchUnmappedTables: jest.fn().mockResolvedValue([]),
26
- fetchTableMetadata: jest.fn().mockResolvedValue({}),
27
- createBranch: jest.fn().mockResolvedValue({ name: "branch1" }),
28
- deleteBranch: jest.fn().mockResolvedValue(undefined),
29
- listBranches: jest.fn().mockResolvedValue([])
30
- };
31
- });
32
-
33
- it("throws error if wsClient is not provided", () => {
34
- expect(() => {
35
- renderHook(() => usePostgresClientDriver({} as any));
36
- }).toThrow("RebaseWebSocketClient must be provided in config.wsClient");
37
- });
38
-
39
- it("returns active database driver object", () => {
40
- const { result } = renderHook(() => usePostgresClientDriver({ wsClient: mockWsClient }));
41
-
42
- expect(result.current.key).toBe("postgres");
43
- expect(result.current.name).toBe("PostgreSQL");
44
- expect(result.current.client).toBe(mockWsClient);
45
- });
46
-
47
- it("correctly routes fetchCollection, fetchEntity, saveEntity, deleteEntity", async () => {
48
- const { result } = renderHook(() => usePostgresClientDriver({ wsClient: mockWsClient }));
49
- const driver = result.current;
50
-
51
- // fetchCollection
52
- const list = await driver.fetchCollection({ path: "posts" });
53
- expect(mockWsClient.fetchCollection).toHaveBeenCalledWith({ path: "posts" });
54
- expect(list).toEqual([{ id: "1",
55
- name: "Entity 1" }]);
56
-
57
- // fetchEntity
58
- const item = await driver.fetchEntity({ path: "posts",
59
- entityId: "1" });
60
- expect(mockWsClient.fetchEntity).toHaveBeenCalledWith({ path: "posts",
61
- entityId: "1" });
62
- expect(item).toEqual({ id: "1",
63
- name: "Entity 1" });
64
-
65
- // saveEntity
66
- const saved = await driver.saveEntity({ path: "posts",
67
- values: { name: "Test" } });
68
- expect(mockWsClient.saveEntity).toHaveBeenCalledWith({
69
- path: "posts",
70
- values: { name: "Test" },
71
- entityId: undefined,
72
- previousValues: undefined,
73
- status: undefined
74
- });
75
- expect(saved).toEqual({ id: "1",
76
- name: "Saved Entity" });
77
-
78
- // deleteEntity
79
- await driver.deleteEntity({ entity: { id: "1",
80
- name: "Test" } });
81
- expect(mockWsClient.deleteEntity).toHaveBeenCalledWith({ entity: { id: "1",
82
- name: "Test" } });
83
- });
84
-
85
- it("correctly routes admin database branching operations", async () => {
86
- const { result } = renderHook(() => usePostgresClientDriver({ wsClient: mockWsClient }));
87
- const driver = result.current;
88
-
89
- // createBranch
90
- await driver.admin.createBranch("branch_test");
91
- expect(mockWsClient.createBranch).toHaveBeenCalledWith("branch_test", undefined);
92
-
93
- // deleteBranch
94
- await driver.admin.deleteBranch("branch_test");
95
- expect(mockWsClient.deleteBranch).toHaveBeenCalledWith("branch_test");
96
-
97
- // listBranches
98
- await driver.admin.listBranches();
99
- expect(mockWsClient.listBranches).toHaveBeenCalled();
100
- });
101
- });
package/tsconfig.json DELETED
@@ -1,46 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "rootDir": ".",
4
- "ignoreDeprecations": "6.0",
5
- "outDir": "dist",
6
- "module": "ESNEXT",
7
- "target": "ESNEXT",
8
- "lib": [
9
- "dom",
10
- "dom.iterable",
11
- "esnext"
12
- ],
13
- "moduleResolution": "bundler",
14
- "jsx": "react-jsx",
15
- "noFallthroughCasesInSwitch": true,
16
- "declaration": true,
17
- "esModuleInterop": true,
18
- "noImplicitReturns": true,
19
- "noImplicitThis": true,
20
- "noImplicitAny": true,
21
- "strictNullChecks": true,
22
- "allowSyntheticDefaultImports": true,
23
- "skipLibCheck": true,
24
- "strict": true,
25
- "forceConsistentCasingInFileNames": true,
26
- "resolveJsonModule": true,
27
- "isolatedModules": true,
28
- "noEmit": true,
29
- "baseUrl": ".",
30
- "paths": {
31
- "@rebasepro/core": ["../core/src"],
32
- "@rebasepro/client": ["../client/src"],
33
- "@rebasepro/types": [
34
- "../types/src"
35
- ]
36
- }
37
- },
38
- "include": [
39
- "src/**/*"
40
- ],
41
- "exclude": [
42
- "node_modules",
43
- "dist",
44
- "test"
45
- ]
46
- }
@@ -1,23 +0,0 @@
1
- {
2
- "extends": "./tsconfig.json",
3
- "compilerOptions": {
4
- "ignoreDeprecations": "6.0",
5
- "rootDir": "./src",
6
- "noEmit": false,
7
- "declaration": true,
8
- "emitDeclarationOnly": true,
9
- "declarationDir": "dist",
10
- "paths": {}
11
- },
12
- "include": [
13
- "src/**/*"
14
- ],
15
- "exclude": [
16
- "node_modules",
17
- "dist",
18
- "test",
19
- "src/**/*.test.ts",
20
- "src/**/*.spec.ts"
21
- ]
22
- }
23
-
package/vite.config.ts DELETED
@@ -1,61 +0,0 @@
1
- import path from "path";
2
-
3
- import { defineConfig } from "vite";
4
- import react from "@vitejs/plugin-react"
5
-
6
- const ReactCompilerConfig = {
7
- target: "18"
8
- };
9
-
10
- const isExternal = (id: string) => {
11
- if (id.startsWith(".") || path.isAbsolute(id)) return false;
12
-
13
- return true;
14
- };
15
-
16
- export default defineConfig(() => ({
17
- esbuild: {
18
- logOverride: { "this-is-undefined-in-esm": "silent" }
19
- },
20
- build: {
21
- lib: {
22
- entry: path.resolve(__dirname, "src/index.ts"),
23
- name: "Rebase PostgreSQL",
24
- fileName: (format) => `index.${format}.js`
25
- },
26
- target: "ESNEXT",
27
- minify: false,
28
- sourcemap: true,
29
- rollupOptions: {
30
- external: isExternal,
31
- onwarn(warning, warn) {
32
- if (warning.code === "MISSING_GLOBAL_NAME") return;
33
- if (warning.code === "INEFFECTIVE_DYNAMIC_IMPORT") return;
34
- warn(warning);
35
- },
36
- output: {
37
- globals: {
38
- "json-logic-js": "jsonLogic",
39
- "fast-equals": "fastEquals",
40
- "lodash/cloneDeep.js": "cloneDeep"
41
- }
42
- }
43
- }
44
- },
45
- resolve: {
46
- alias: {
47
- "@rebasepro/client": path.resolve(__dirname, "../client/src"),
48
- "@rebasepro/core": path.resolve(__dirname, "../core/src"),
49
- "@rebasepro/types": path.resolve(__dirname, "../types/src")
50
- }
51
- },
52
- plugins: [
53
- react({
54
- babel: {
55
- plugins: [
56
- ["babel-plugin-react-compiler", ReactCompilerConfig]
57
- ]
58
- }
59
- })
60
- ]
61
- }));