@rebasepro/common 0.13.0 → 0.13.1-canary.g18cfeb7

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.
@@ -34,7 +34,16 @@ export declare function buildRebaseData(driver: DataDriver, options?: EntityData
34
34
  * admin `RebaseDataContext` — without it the admin renders rows with only their
35
35
  * `id`.
36
36
  */
37
- export declare function wrapAsEntityData(sdkData: RebaseSdkData, options?: EntityDataOptions): RebaseData;
37
+ /**
38
+ * Only the by-slug accessor is asked for, so only that is required.
39
+ *
40
+ * Taking a whole `RebaseSdkData` meant taking `RebaseSdkData<unknown>`, whose
41
+ * dynamic branch is an index signature — and no `RebaseSdkData<DB>` satisfies
42
+ * it, because its own `collection` method is not a `SDKCollectionClient`. So a
43
+ * caller holding a *typed* client could not pass it to a function that reads
44
+ * one method off it, and that method is identical on every instantiation.
45
+ */
46
+ export declare function wrapAsEntityData(sdkData: Pick<RebaseSdkData, "collection">, options?: EntityDataOptions): RebaseData;
38
47
  /**
39
48
  * Wrap a Entity-shaped {@link RebaseData} into a flat {@link RebaseSdkData}.
40
49
  *
@@ -72,4 +72,18 @@ export declare function serializeLogicalCondition(cond: LogicalCondition | Filte
72
72
  * deserializeLogicalCondition("or(status.eq.active,age.gte.18)")
73
73
  * // → { type: "or", conditions: [...] }
74
74
  */
75
- export declare function deserializeLogicalCondition(str: string): LogicalCondition | FilterCondition;
75
+ /**
76
+ * How deeply `or(...)`/`and(...)` groups may nest.
77
+ *
78
+ * This parser recurses once per level, on a value that arrives in a query
79
+ * string. Unbounded, twenty thousand levels reached `RangeError: Maximum call
80
+ * stack size exceeded`, which a caller sees as a 500 about the call stack
81
+ * rather than a 400 about their filter. Node's 16 KB header cap keeps a GET
82
+ * below that in practice, but "the HTTP layer happens to stop it" is not a
83
+ * bound this parser should rely on.
84
+ *
85
+ * Thirty-two is far past anything a real filter expresses; the deepest in this
86
+ * repository's own tests is three.
87
+ */
88
+ export declare const MAX_LOGICAL_NESTING_DEPTH = 32;
89
+ export declare function deserializeLogicalCondition(str: string, nesting?: number): LogicalCondition | FilterCondition;
@@ -45,6 +45,26 @@ export declare class RebasePaginationError extends Error {
45
45
  }
46
46
  /** The one thing a transport has to provide to be paginated. */
47
47
  export type PageFinder<M extends Record<string, unknown> = Record<string, unknown>> = (params: FindParams<M>) => Promise<FindResult<M>>;
48
+ /**
49
+ * Resolve `limit`/`offset`/`page` into the window a read will actually use.
50
+ *
51
+ * Lives here, next to the walk, for the reason at the top of this file: every
52
+ * transport has to mean the same thing by "page two". Four of them did not —
53
+ * the REST layer strode by {@link DEFAULT_LIST_LIMIT}, the local-first
54
+ * evaluator by {@link DEFAULT_PAGE_SIZE}, the in-process accessor by 20, and
55
+ * the published type documented a fourth number. Pages that overlap or skip
56
+ * rows are the mildest of those outcomes.
57
+ *
58
+ * `page` wins over `offset`, as {@link FindParams} documents. `driverOffset`
59
+ * is the value to hand a driver: it stays `undefined` when the caller named no
60
+ * offset, because keyset pagination seeks with a `where` clause and must not
61
+ * look like it is paging by offset.
62
+ */
63
+ export declare function resolveFindWindow(params?: Pick<FindParams, "limit" | "offset" | "page">): {
64
+ limit: number;
65
+ offset: number;
66
+ driverOffset: number | undefined;
67
+ };
48
68
  /**
49
69
  * Walk every row a query matches, yielding one row at a time and fetching the
50
70
  * next page only when the consumer asks for it.
@@ -41,3 +41,39 @@ export declare function createDataSourceRegistry(definitions?: DataSourceDefinit
41
41
  * @param registry optional registry of declared data sources
42
42
  */
43
43
  export declare function resolveDataSource(collection: DataSourceResolvable | undefined, registry?: DataSourceRegistry): ResolvedDataSource;
44
+ /**
45
+ * Does a SQL toolchain own this collection's storage?
46
+ *
47
+ * "Owns the storage" means: something generates a table for it, pushes that
48
+ * table to a database, plans its RLS policies, and reports it as drifted when
49
+ * the two disagree. That is true of a Postgres collection and false of a
50
+ * Firestore or MongoDB one, whose documents live in a store Rebase never
51
+ * migrates — and the two were never told apart. Every stage of the SQL
52
+ * toolchain took "the collections" to mean *all* of them, so a Firestore
53
+ * collection declared next to the Postgres ones got a `pgTable` in the
54
+ * generated schema, a `CREATE TABLE` at boot, RLS policies, and a place in the
55
+ * `db push` include list — where its name shielding a same-named real table
56
+ * from Atlas's exclude list is the one that can lose data.
57
+ *
58
+ * The answer is the resolved engine's {@link DataSourceCapabilities}, not a
59
+ * name check: an engine registered through `registerDataSourceCapabilities`
60
+ * gets the same treatment as the built-in ones.
61
+ *
62
+ * Deliberately answers **true** for an engine nobody has heard of. Build-time
63
+ * tooling (the CLI, the schema generator) has no data-source registry to
64
+ * resolve a `dataSource` key against, so an unknown key resolves to an unknown
65
+ * engine — and the cost of the two mistakes is not symmetric. Wrongly
66
+ * including a collection generates a table nothing writes to; wrongly excluding
67
+ * one silently stops generating a table the app is serving from. Declare
68
+ * `engine` on a collection that is not SQL-backed and this is exact.
69
+ */
70
+ export declare function isRelationalCollection(collection: DataSourceResolvable | undefined, registry?: DataSourceRegistry): boolean;
71
+ /**
72
+ * The subset of `collections` a SQL toolchain owns — see
73
+ * {@link isRelationalCollection}.
74
+ *
75
+ * Every stage that generates SQL from collections starts by calling this, so
76
+ * the rule lives in one place rather than being re-decided per generator. It
77
+ * keeps the input order.
78
+ */
79
+ export declare function relationalCollections<C extends DataSourceResolvable>(collections: readonly C[], registry?: DataSourceRegistry): C[];