@rebasepro/server-postgres 0.9.1-canary.1d2d8b5 → 0.9.1-canary.58368ce

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.
@@ -3,7 +3,7 @@ import { BranchService } from "./services/BranchService";
3
3
  import { RealtimeService } from "./services/realtimeService";
4
4
  import { DatabasePoolManager } from "./databasePoolManager";
5
5
  import { DrizzleClient } from "./interfaces";
6
- import { DatabaseAdmin, DataDriver, DeleteProps, CollectionConfig, FetchCollectionProps, FetchOneProps, ListenCollectionProps, ListenOneProps, RebaseClient, RebaseSdkData, RestFetchService, SaveProps, TableMetadata, User } from "@rebasepro/types";
6
+ import { DatabaseAdmin, DataDriver, DeleteProps, CollectionConfig, FetchCollectionProps, FetchOneProps, ListenCollectionProps, ListenOneProps, RebaseClient, RebaseSdkData, RestFetchService, SaveManyProps, SaveProps, TableMetadata, User } from "@rebasepro/types";
7
7
  import { PostgresCollectionRegistry } from "./collections/PostgresCollectionRegistry";
8
8
  import { HistoryService } from "./history/HistoryService";
9
9
  export declare class PostgresBackendDriver implements DataDriver {
@@ -88,7 +88,20 @@ export declare class PostgresBackendDriver implements DataDriver {
88
88
  listenCollection<M extends Record<string, unknown>>({ path, collection, filter, limit, offset, startAfter, orderBy, searchString, order, onUpdate, onError }: ListenCollectionProps<M>): () => void;
89
89
  fetchOne<M extends Record<string, unknown>>({ path, id, databaseId, collection }: FetchOneProps<M>): Promise<Record<string, unknown> | undefined>;
90
90
  listenOne<M extends Record<string, unknown>>({ path, id, collection, onUpdate, onError }: ListenOneProps<M>): () => void;
91
- save<M extends Record<string, unknown>>({ path, id, values, collection, status }: SaveProps<M>): Promise<Record<string, unknown>>;
91
+ save<M extends Record<string, unknown>>({ path, id, values, collection, status, upsert }: SaveProps<M>): Promise<Record<string, unknown>>;
92
+ /**
93
+ * Write many rows through the same pipeline as {@link save}.
94
+ *
95
+ * The batch runs in one transaction of its own, so a failure part-way leaves
96
+ * nothing behind — the point of a batch is that a re-run starts from a known
97
+ * state. When this driver is already inside a transaction (the authenticated
98
+ * path, via `withTransaction`) the nested call becomes a savepoint, which is
99
+ * still atomic and still commits once.
100
+ *
101
+ * Rows are applied in order, so a batch that touches the same key twice ends
102
+ * with the last write winning, exactly as separate calls would.
103
+ */
104
+ saveMany<M extends Record<string, unknown>>({ path, rows, collection, upsert }: SaveManyProps<M>): Promise<Record<string, unknown>[]>;
92
105
  delete<M extends Record<string, unknown>>({ row, collection }: DeleteProps<M>): Promise<void>;
93
106
  deleteAll(path: string): Promise<void>;
94
107
  checkUniqueField(path: string, name: string, value: unknown, id?: string, collection?: CollectionConfig): Promise<boolean>;
@@ -143,6 +156,16 @@ export declare class AuthenticatedPostgresBackendDriver implements DataDriver {
143
156
  fetchOne<M extends Record<string, unknown>>(props: FetchOneProps<M>): Promise<Record<string, unknown> | undefined>;
144
157
  listenOne<M extends Record<string, unknown>>(props: ListenOneProps<M>): () => void;
145
158
  save<M extends Record<string, unknown>>(props: SaveProps<M>): Promise<Record<string, unknown>>;
159
+ /**
160
+ * One transaction for the whole batch, rather than one per row.
161
+ *
162
+ * This is the point of the method: `save` opens a transaction per call, so
163
+ * importing 10k rows through it means 10k transactions (and, over HTTP, 10k
164
+ * round trips). Here the RLS context is established once and every row lands
165
+ * or none does. Realtime notifications are already deferred to commit by
166
+ * `withTransaction`, so a batch does not flood subscribers mid-flight.
167
+ */
168
+ saveMany<M extends Record<string, unknown>>(props: SaveManyProps<M>): Promise<Record<string, unknown>[]>;
146
169
  delete<M extends Record<string, unknown>>(props: DeleteProps<M>): Promise<void>;
147
170
  deleteAll(path: string): Promise<void>;
148
171
  checkUniqueField(path: string, name: string, value: unknown, id?: string, collection?: CollectionConfig): Promise<boolean>;
@@ -0,0 +1,27 @@
1
+ import { Relations } from "drizzle-orm";
2
+ import { PgEnum } from "drizzle-orm/pg-core";
3
+ import { CollectionConfig } from "@rebasepro/types";
4
+ import { PostgresCollectionRegistry } from "./PostgresCollectionRegistry";
5
+ /**
6
+ * Everything a registry is built from: the collections, and the drizzle schema
7
+ * they are backed by. In BaaS mode all of it is introspected from the live
8
+ * database; in CMS mode it comes from the config and the generated schema.
9
+ */
10
+ export interface RegistrySchema {
11
+ collections?: CollectionConfig[];
12
+ tables?: Record<string, unknown>;
13
+ enums?: Record<string, PgEnum<[string, ...string[]]>>;
14
+ relations?: Record<string, Relations>;
15
+ }
16
+ /**
17
+ * Build the collection registry for a driver.
18
+ *
19
+ * The order matters and is the reason this is one function rather than a run of
20
+ * statements in the bootstrapper. Keys are resolved from the drizzle schema, so
21
+ * anything that inspects them has to run *after* the tables are registered —
22
+ * and `warnOnKeysTheAdminCannotResolve` fails open if it does not, because a
23
+ * collection whose table it cannot look up is one it has nothing to say about.
24
+ * Warned too early, it would skip every collection and report nothing, which
25
+ * reads exactly like having nothing to report.
26
+ */
27
+ export declare function buildCollectionRegistry(schema: RegistrySchema): PostgresCollectionRegistry;
@@ -12,12 +12,19 @@ import { PostgresCollectionRegistry } from "./collections/PostgresCollectionRegi
12
12
  export interface SerializedEntityData {
13
13
  /** Scalar column values ready for INSERT/UPDATE. */
14
14
  scalarData: Record<string, unknown>;
15
- /** Inverse relation updates that must be applied to target tables. */
15
+ /**
16
+ * Inverse relation updates that must be applied to target tables.
17
+ *
18
+ * No address here: the row being written does not know its own. These are
19
+ * applied by `PersistService`, which addresses them with the id it holds —
20
+ * the one it was given for an update, or the one the INSERT returned — and
21
+ * that is the authority. This item used to carry a `currentId` derived from
22
+ * the *input* values, which nothing ever read.
23
+ */
16
24
  inverseRelationUpdates: Array<{
17
25
  relationKey: string;
18
26
  relation: Relation;
19
27
  newValue: unknown;
20
- currentId?: string | number;
21
28
  }>;
22
29
  /** JoinPath relation updates that require multi-hop writes. */
23
30
  joinPathRelationUpdates: Array<{