@rebasepro/client 0.19.1 → 0.19.2-canary.g09316f6
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/dist/collection.d.ts +16 -0
- package/dist/index.d.ts +37 -2
- package/dist/index.es.js +378 -49
- package/dist/index.es.js.map +1 -1
- package/dist/offline-query.d.ts +0 -30
- package/dist/sdk_query_builder.d.ts +81 -8
- package/dist/transport.d.ts +37 -2
- package/dist/websocket.d.ts +2 -2
- package/package.json +4 -4
package/dist/offline-query.d.ts
CHANGED
|
@@ -60,36 +60,6 @@ export declare function resolvePagination(params?: FindParams): {
|
|
|
60
60
|
limit: number;
|
|
61
61
|
offset: number;
|
|
62
62
|
};
|
|
63
|
-
/**
|
|
64
|
-
* Can a locally evaluated answer to `params` be trusted to match the server's,
|
|
65
|
-
* assuming the cache holds every row of the collection?
|
|
66
|
-
*
|
|
67
|
-
* `include` pulls in rows from other collections that this evaluator never
|
|
68
|
-
* sees, and `searchString` is only approximated — both make the local answer a
|
|
69
|
-
* best effort rather than an equivalent one.
|
|
70
|
-
*
|
|
71
|
-
* **Ordering comparisons are refused, and that is the interesting one.**
|
|
72
|
-
* `compareValues` falls back to an `Intl.Collator` for operands it cannot read
|
|
73
|
-
* as numbers or instants. PostgreSQL orders text by the *database's* collation,
|
|
74
|
-
* which is a property of the server this process has never been told: under the
|
|
75
|
-
* C collation `'apple' < 'Banana'` is false, under `en_US.UTF-8` it is true,
|
|
76
|
-
* and the collator says true. So `["<", "Banana"]` selects a different set here
|
|
77
|
-
* than it does there — silently, and in whichever direction the deployment
|
|
78
|
-
* happens to have been created.
|
|
79
|
-
*
|
|
80
|
-
* The refusal covers *every* ordering comparison rather than only the ones with
|
|
81
|
-
* a string operand, because the operand type does not settle it: a numeric
|
|
82
|
-
* bound against a text column (`["<", 10]` on a `varchar`) also reaches the
|
|
83
|
-
* collator, and nothing in `params` says what the column holds. Conservative on
|
|
84
|
-
* purpose — the cost is that a query combining an ordering filter with
|
|
85
|
-
* *unsynced local writes* stops placing those writes optimistically, which is a
|
|
86
|
-
* degraded answer rather than a wrong one. Claiming exactness we do not have is
|
|
87
|
-
* the other way round.
|
|
88
|
-
*
|
|
89
|
-
* This says nothing about ordering *results*; that is a separate claim with a
|
|
90
|
-
* separate answer, because a sort changes which rows come first and not which
|
|
91
|
-
* rows match. See {@link isLocallySortable}.
|
|
92
|
-
*/
|
|
93
63
|
export declare function isExactlyEvaluable(params?: FindParams): boolean;
|
|
94
64
|
/**
|
|
95
65
|
* Would sorting `rows` locally reproduce the order the server would have sent?
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { FindResult, LogicalCondition, PageWalkOptions, RelationAggregateSort, SDKCollectionClient, SDKQueryBuilderInterface, WhereFilterOp, WhereValueFor, type ComputedSortField, type FieldPath, type NonColumnFieldPath } from "@rebasepro/types";
|
|
1
|
+
import { FindResult, LogicalCondition, PageWalkOptions, RelationAggregateSort, SDKCollectionClient, SDKQueryBuilderInterface, WhereFilterOp, WhereValueFor, type AggregateParams, type AggregateRow, type ComputedSortField, type FieldPath, type IncludeSpec, type NonColumnFieldPath, type NullsPlacement } from "@rebasepro/types";
|
|
2
2
|
/**
|
|
3
3
|
* SDK Query Builder — returns flat rows (`FindResult<M>`) instead of
|
|
4
4
|
* Entity-wrapped results (`FindResponse<M>`).
|
|
@@ -33,7 +33,14 @@ export declare class SDKQueryBuilder<M extends Record<string, unknown> = Record<
|
|
|
33
33
|
* `.orderBy("roles").orderBy("created_at", "desc")` sorts by role and
|
|
34
34
|
* shows the newest first within each one.
|
|
35
35
|
*/
|
|
36
|
-
orderBy(column: FieldPath<M> | ComputedSortField | RelationAggregateSort, direction?: "asc" | "desc"
|
|
36
|
+
orderBy(column: FieldPath<M> | ComputedSortField | RelationAggregateSort, direction?: "asc" | "desc",
|
|
37
|
+
/**
|
|
38
|
+
* Where this key's NULLs go. Omitted means the direction's own
|
|
39
|
+
* convention — last ascending, first descending — which is what put
|
|
40
|
+
* every undated row at the top of a `.orderBy("published_at", "desc")`
|
|
41
|
+
* list, ahead of everything real.
|
|
42
|
+
*/
|
|
43
|
+
nulls?: NullsPlacement): this;
|
|
37
44
|
/**
|
|
38
45
|
* Limit the number of results returned.
|
|
39
46
|
*/
|
|
@@ -89,18 +96,84 @@ export declare class SDKQueryBuilder<M extends Record<string, unknown> = Record<
|
|
|
89
96
|
threshold?: number;
|
|
90
97
|
}): this;
|
|
91
98
|
/**
|
|
92
|
-
*
|
|
93
|
-
* Relations will be populated with full data instead of just IDs.
|
|
99
|
+
* Load related rows into the response, in place of their foreign keys.
|
|
94
100
|
*
|
|
95
|
-
*
|
|
96
|
-
*
|
|
97
|
-
*
|
|
101
|
+
* Three spellings, all the same request:
|
|
102
|
+
*
|
|
103
|
+
* ```ts
|
|
104
|
+
* client.data.posts.include("tags", "author") // names
|
|
105
|
+
* client.data.posts.include("comments.author") // a dotted path
|
|
106
|
+
* client.data.posts.include({ // parametrised
|
|
107
|
+
* comments: {
|
|
108
|
+
* limit: 5,
|
|
109
|
+
* where: { published: ["==", true] },
|
|
110
|
+
* orderBy: ["created_at", "desc"],
|
|
111
|
+
* include: { author: true }
|
|
112
|
+
* }
|
|
113
|
+
* })
|
|
114
|
+
* ```
|
|
115
|
+
*
|
|
116
|
+
* Up to three hops deep, and `"*"` still loads every relation one hop
|
|
117
|
+
* deep. A name that is not a relation of the collection is a 400
|
|
118
|
+
* `UNKNOWN_RELATION` — it used to be ignored, which answers 200 with the
|
|
119
|
+
* field missing and reads exactly like a row that has no related row.
|
|
120
|
+
*
|
|
121
|
+
* Repeated calls **merge**: `.include("author").include("tags")` asks for
|
|
122
|
+
* both. Assigning here — which is what it used to do — meant the second
|
|
123
|
+
* call silently discarded the first.
|
|
124
|
+
*/
|
|
125
|
+
include(...relations: (string | IncludeSpec)[]): this;
|
|
126
|
+
/**
|
|
127
|
+
* Return only these columns.
|
|
128
|
+
*
|
|
129
|
+
* A projection at the database, not a trim of the response: a query that
|
|
130
|
+
* needs two fields of a wide row reads two columns. The primary key always
|
|
131
|
+
* comes back regardless — a row that cannot be addressed cannot be
|
|
132
|
+
* updated, deleted or paged past — and `excludeFromApi` columns stay
|
|
133
|
+
* hidden whether or not they are named.
|
|
134
|
+
*/
|
|
135
|
+
fields(...columns: (FieldPath<M> | string)[]): this;
|
|
136
|
+
/**
|
|
137
|
+
* Collapse rows that are identical over the columns being returned.
|
|
138
|
+
*
|
|
139
|
+
* Only meaningful alongside {@link fields}: the primary key is always in
|
|
140
|
+
* the projection, so without narrowing it every row is already distinct.
|
|
141
|
+
*
|
|
142
|
+
* ```ts
|
|
143
|
+
* client.data.posts.fields("status").distinct().find() // the statuses in use
|
|
144
|
+
* ```
|
|
145
|
+
*/
|
|
146
|
+
distinct(enabled?: boolean): this;
|
|
147
|
+
/**
|
|
148
|
+
* Continue after a previous page's `meta.nextCursor` — keyset paging.
|
|
149
|
+
*
|
|
150
|
+
* Unlike `offset`, a row inserted or deleted before the cursor cannot
|
|
151
|
+
* shift the window, so a walk neither repeats nor skips rows. Keep
|
|
152
|
+
* `orderBy` identical across pages: a cursor only continues the listing it
|
|
153
|
+
* came from, and one used against a different sort is refused rather than
|
|
154
|
+
* seeked in an order nobody asked for.
|
|
98
155
|
*/
|
|
99
|
-
|
|
156
|
+
after(cursor: string): this;
|
|
100
157
|
/**
|
|
101
158
|
* Execute the find query and return the results as flat rows.
|
|
102
159
|
*/
|
|
103
160
|
find(): Promise<FindResult<M>>;
|
|
161
|
+
/**
|
|
162
|
+
* Aggregate the rows this query matches instead of returning them.
|
|
163
|
+
*
|
|
164
|
+
* The builder's `where`/`logical`/`search` narrow which rows are
|
|
165
|
+
* aggregated; its `orderBy`, `include` and window do not apply — an
|
|
166
|
+
* aggregate has no rows to sort, no relations to load and no page to
|
|
167
|
+
* continue.
|
|
168
|
+
*
|
|
169
|
+
* ```ts
|
|
170
|
+
* await client.data.orders
|
|
171
|
+
* .where("created_at", ">=", startOfMonth)
|
|
172
|
+
* .aggregate({ select: [{ fn: "sum", field: "total" }], groupBy: ["status"] });
|
|
173
|
+
* // [{ status: "paid", sum_total: 41822.5 }, …]
|
|
174
|
+
* ```
|
|
175
|
+
*/
|
|
176
|
+
aggregate(params: Omit<AggregateParams<M>, "where" | "logical" | "searchString">): Promise<AggregateRow[]>;
|
|
104
177
|
/**
|
|
105
178
|
* Page through everything this query matches, one row at a time.
|
|
106
179
|
*
|
package/dist/transport.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { FindParams as TypesFindParams, FindResponse as TypesFindResponse } from "@rebasepro/types";
|
|
1
|
+
import { AggregateParams, FindParams as TypesFindParams, FindResponse as TypesFindResponse } from "@rebasepro/types";
|
|
2
2
|
export { RebaseApiError } from "@rebasepro/types";
|
|
3
3
|
export type { RebaseErrorInit } from "@rebasepro/types";
|
|
4
4
|
export interface RebaseClientConfig {
|
|
@@ -127,8 +127,43 @@ export declare const ANONYMOUS_SERVER_CLIENT_WARNING: string;
|
|
|
127
127
|
export type FindParams<M extends Record<string, unknown> = Record<string, unknown>> = TypesFindParams<M>;
|
|
128
128
|
export type FindResponse<T> = TypesFindResponse<T extends Record<string, unknown> ? T : Record<string, unknown>>;
|
|
129
129
|
export declare function buildQueryString(params?: FindParams): string;
|
|
130
|
+
/**
|
|
131
|
+
* The query string for `GET /<collection>/aggregate`.
|
|
132
|
+
*
|
|
133
|
+
* `?select=sum(total),count()` is SQL's spelling, because whoever writes an
|
|
134
|
+
* aggregate is thinking in SQL and any other spelling has to be learned first —
|
|
135
|
+
* and because it is what the route already parses. The filters are serialised
|
|
136
|
+
* by exactly the same code a `find()` uses, so "revenue by status, this month"
|
|
137
|
+
* narrows the same rows whichever call is asking.
|
|
138
|
+
*
|
|
139
|
+
* `orderBy`, `include` and the page are deliberately not here: an aggregate has
|
|
140
|
+
* no rows to sort, no relations to load and no page to continue. `limit` is,
|
|
141
|
+
* and bounds the number of *groups*.
|
|
142
|
+
*/
|
|
143
|
+
export declare function buildAggregateQueryString(params: AggregateParams): string;
|
|
144
|
+
/**
|
|
145
|
+
* Response metadata a caller can ask for, filled in by `request`.
|
|
146
|
+
*
|
|
147
|
+
* An out-parameter rather than a second return value, because every one of the
|
|
148
|
+
* fifty-odd call sites wants the body and nothing else, and changing the return
|
|
149
|
+
* shape would mean rewriting all of them to reach past a wrapper. It is also
|
|
150
|
+
* why this is a third *optional* parameter: a `Transport` stub in a test that
|
|
151
|
+
* ignores it is still a valid `Transport`.
|
|
152
|
+
*
|
|
153
|
+
* Only `ETag` for now, and only because a row's version is not part of the row.
|
|
154
|
+
* It cannot be: adding it as a column would put it in the generated `Row` type,
|
|
155
|
+
* in every `find()` result, in the offline cache and in what a caller sends
|
|
156
|
+
* back on the next write — a field the server would then have to strip. The
|
|
157
|
+
* header is where HTTP puts it, so the header is where this reads it.
|
|
158
|
+
*/
|
|
159
|
+
export interface ResponseMeta {
|
|
160
|
+
/** The `ETag` header, when the response carried one. */
|
|
161
|
+
etag?: string;
|
|
162
|
+
/** The HTTP status, for a caller that has to tell 200 from 204. */
|
|
163
|
+
status?: number;
|
|
164
|
+
}
|
|
130
165
|
export interface Transport {
|
|
131
|
-
request: <T = unknown>(path: string, init?: RequestInit) => Promise<T>;
|
|
166
|
+
request: <T = unknown>(path: string, init?: RequestInit, meta?: ResponseMeta) => Promise<T>;
|
|
132
167
|
setToken: (newToken: string | null) => void;
|
|
133
168
|
setAuthTokenGetter: (getter: () => Promise<string | null>) => void;
|
|
134
169
|
setOnUnauthorized: (handler: () => Promise<boolean>) => void;
|
package/dist/websocket.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DeleteProps, CollectionConfig, FetchCollectionProps, FetchOneProps, SaveProps, TableMetadata, BranchInfo } from "@rebasepro/types";
|
|
1
|
+
import { DeleteProps, CollectionConfig, FetchCollectionProps, ListenCollectionProps, FetchOneProps, SaveProps, CollectionUpdateMeta, TableMetadata, BranchInfo } from "@rebasepro/types";
|
|
2
2
|
export interface RebaseWebSocketConfig {
|
|
3
3
|
websocketUrl: string;
|
|
4
4
|
/** Optional auth token getter for WebSocket authentication */
|
|
@@ -171,7 +171,7 @@ export declare class RebaseWebSocketClient {
|
|
|
171
171
|
* haven't actually changed.
|
|
172
172
|
*/
|
|
173
173
|
private mergeRows;
|
|
174
|
-
listenCollection<M extends Record<string, unknown>>(props:
|
|
174
|
+
listenCollection<M extends Record<string, unknown>>(props: Omit<ListenCollectionProps<M>, "onUpdate" | "onError">, onUpdate: (rows: Record<string, unknown>[], meta?: CollectionUpdateMeta) => void, onError?: (error: Error) => void): () => void;
|
|
175
175
|
listenOne<M extends Record<string, unknown>>(props: FetchOneProps<M>, onUpdate: (row: Record<string, unknown> | null) => void, onError?: (error: Error) => void): () => void;
|
|
176
176
|
/**
|
|
177
177
|
* Send a `subscribe_collection` for an already-registered subscription and
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rebasepro/client",
|
|
3
|
-
"version": "0.19.
|
|
3
|
+
"version": "0.19.2-canary.g09316f6",
|
|
4
4
|
"description": "HTTP SDK client for the Rebase custom backend",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"rebase",
|
|
@@ -41,9 +41,9 @@
|
|
|
41
41
|
"./package.json": "./package.json"
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@rebasepro/common": "0.19.
|
|
45
|
-
"@rebasepro/
|
|
46
|
-
"@rebasepro/
|
|
44
|
+
"@rebasepro/common": "0.19.2-canary.g09316f6",
|
|
45
|
+
"@rebasepro/types": "0.19.2-canary.g09316f6",
|
|
46
|
+
"@rebasepro/utils": "0.19.2-canary.g09316f6"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
49
|
"@jest/globals": "^30.4.1",
|