@pipeline-builder/pipeline-data 4.1.3 → 4.1.5

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
@@ -22,7 +22,6 @@ Database layer for [Pipeline Builder](https://mwashburn160.github.io/pipeline-bu
22
22
  | `db` | Shared Drizzle database instance |
23
23
  | `getConnection`, `closeConnection` | PostgreSQL connection lifecycle (with retry strategy) |
24
24
  | `schema` | All Drizzle table definitions and their `*Insert` / `*Update` types |
25
- | `runMigrations` (`MigrateOptions`) | Drizzle migration runner |
26
25
  | `tenantContext`, `runWithTenantContext`, `getTenantContext`, `withTenantTx` | Tenant-context primitives for scoped/RLS transactions |
27
26
 
28
27
  ### Services
@@ -40,7 +40,10 @@ export interface QueryOptions {
40
40
  sortOrder?: 'asc' | 'desc';
41
41
  /** When true, runs a separate COUNT(*) query to include exact total. Default: false. */
42
42
  includeTotal?: boolean;
43
- /** Cursor-based pagination: fetch rows after this cursor value (uses sortBy column). */
43
+ /**
44
+ * Keyset pagination: the opaque `nextCursor` of the previous page. Continues
45
+ * strictly after that row in (sortBy, id) order; takes precedence over `offset`.
46
+ */
44
47
  cursor?: string;
45
48
  /** Sparse fieldset: column names to select. Returns all columns when omitted. */
46
49
  fields?: string[];
@@ -55,7 +58,7 @@ export interface PaginatedResult<T> {
55
58
  limit: number;
56
59
  offset: number;
57
60
  hasMore: boolean;
58
- /** Cursor pointing to the last item, for cursor-based pagination. */
61
+ /** Opaque cursor for the next page. Present only when `hasMore`. */
59
62
  nextCursor?: string;
60
63
  }
61
64
  /** The shared soft-delete retention window in ms (`SOFT_DELETE_RETENTION_DAYS`,
@@ -90,7 +93,7 @@ export declare abstract class CrudService<TEntity extends BaseEntity, TFilter, T
90
93
  * be the tenant `orgId` column, not a display/name column.
91
94
  */
92
95
  protected abstract getOrgColumn(): AnyColumn;
93
- /** Get the unique constraint columns for onConflictDoUpdate */
96
+ /** The unique-constraint columns a create must not conflict on (see {@link create}). */
94
97
  protected abstract get conflictTarget(): AnyColumn[];
95
98
  private readonly _logger;
96
99
  constructor();
@@ -184,12 +187,11 @@ export declare abstract class CrudService<TEntity extends BaseEntity, TFilter, T
184
187
  findPaginated(filter: Partial<TFilter>, orgId?: string, options?: QueryOptions, parentOrgId?: string): Promise<PaginatedResult<TEntity>>;
185
188
  /**
186
189
  * Build a column selection map for sparse fieldsets.
187
- * Falls back to full select if no matching columns found.
190
+ * Falls back to full select if no fields are requested.
188
191
  *
189
- * `sortBy` (when set) is always folded into the projection even if the caller's
190
- * `fields` omits it — cursor pagination reads the next cursor from the sort
191
- * column's value on the last row, so dropping it from the SELECT would yield an
192
- * undefined cursor and stall paging. Included the same way `id` always is.
192
+ * `id` is always included — it is the entity identity AND the keyset cursor's
193
+ * tie-breaker. The sort value for the cursor is projected separately (as text)
194
+ * by `findPaginated`, so the fieldset need not carry the sort column.
193
195
  */
194
196
  private buildFieldSelect;
195
197
  /**
@@ -254,21 +256,6 @@ export declare abstract class CrudService<TEntity extends BaseEntity, TFilter, T
254
256
  * Update multiple entities matching filter
255
257
  */
256
258
  updateMany(filter: Partial<TFilter>, data: Partial<TUpdate>, orgId: string, userId: string): Promise<TEntity[]>;
257
- /**
258
- * Create multiple entities in a single batch insert.
259
- * Uses upsert (onConflictDoUpdate) — all rows are inserted in one query per chunk.
260
- * Chunks of 100 to stay within PostgreSQL parameter limits.
261
- */
262
- /**
263
- * Build the `onConflictDoUpdate` SET for a bulk upsert. Unlike a single-row
264
- * create (which can spread the one row's data), a batched insert has many rows,
265
- * so each updatable column is written from `excluded.*` (the would-be-inserted
266
- * value) — otherwise an existing row's fields are silently discarded and only
267
- * timestamps bump. Skips identity/immutable (`id`, `createdAt`, `createdBy`)
268
- * and the conflict-target columns; `updatedAt`/`updatedBy` get the fresh values.
269
- */
270
- private buildBulkUpsertSet;
271
- bulkCreate(items: TInsert[], userId: string): Promise<TEntity[]>;
272
259
  /**
273
260
  * The `visibility` predicate for a bulk soft-delete, mirroring
274
261
  * `requireVisibilityWriteAccess` rung for rung so bulk and single-row delete