@linabase/js 0.3.1 → 0.4.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/dist/index.cjs +81 -9
- package/dist/index.d.cts +44 -4
- package/dist/index.d.ts +44 -4
- package/dist/index.js +81 -9
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -57,10 +57,11 @@ var DatabaseClient = class {
|
|
|
57
57
|
if (options?.count) this.preferHeaders.push(`count=${options.count}`);
|
|
58
58
|
return this;
|
|
59
59
|
}
|
|
60
|
-
insert(data) {
|
|
60
|
+
insert(data, options) {
|
|
61
61
|
this.method = "POST";
|
|
62
62
|
this.body = data;
|
|
63
63
|
this.preferHeaders.push("return=representation");
|
|
64
|
+
if (options?.defaultToNull === false) this.preferHeaders.push("missing=default");
|
|
64
65
|
return this;
|
|
65
66
|
}
|
|
66
67
|
/** Upsert: insert or update on conflict. Uses merge-duplicates by default. */
|
|
@@ -74,6 +75,7 @@ var DatabaseClient = class {
|
|
|
74
75
|
if (options?.onConflict) {
|
|
75
76
|
this.params.set("on_conflict", options.onConflict);
|
|
76
77
|
}
|
|
78
|
+
if (options?.defaultToNull === false) this.preferHeaders.push("missing=default");
|
|
77
79
|
return this;
|
|
78
80
|
}
|
|
79
81
|
update(data) {
|
|
@@ -82,8 +84,28 @@ var DatabaseClient = class {
|
|
|
82
84
|
this.preferHeaders.push("return=representation");
|
|
83
85
|
return this;
|
|
84
86
|
}
|
|
85
|
-
delete() {
|
|
87
|
+
delete(options) {
|
|
86
88
|
this.method = "DELETE";
|
|
89
|
+
if (options?.count) this.preferHeaders.push(`count=${options.count}`);
|
|
90
|
+
return this;
|
|
91
|
+
}
|
|
92
|
+
/** Specify return=minimal to skip returning data on mutations (better performance). */
|
|
93
|
+
returning(mode = "representation") {
|
|
94
|
+
this.preferHeaders = this.preferHeaders.filter((h) => !h.startsWith("return="));
|
|
95
|
+
this.preferHeaders.push(`return=${mode}`);
|
|
96
|
+
return this;
|
|
97
|
+
}
|
|
98
|
+
/** Get the query execution plan (EXPLAIN). */
|
|
99
|
+
explain(options) {
|
|
100
|
+
const parts = ["plan"];
|
|
101
|
+
if (options?.analyze) parts.push("analyze");
|
|
102
|
+
if (options?.verbose) parts.push("verbose");
|
|
103
|
+
if (options?.settings) parts.push("settings");
|
|
104
|
+
if (options?.buffers) parts.push("buffers");
|
|
105
|
+
if (options?.wal) parts.push("wal");
|
|
106
|
+
if (options?.format) parts.push(`format:${options.format}`);
|
|
107
|
+
this.preferHeaders = this.preferHeaders.filter((h) => !h.startsWith("plan"));
|
|
108
|
+
this.preferHeaders.push(parts.join("|"));
|
|
87
109
|
return this;
|
|
88
110
|
}
|
|
89
111
|
// ─── Comparison Filters ─────────────────────────────────
|
|
@@ -167,6 +189,32 @@ var DatabaseClient = class {
|
|
|
167
189
|
this.params.set(column, `isdistinct.${value}`);
|
|
168
190
|
return this;
|
|
169
191
|
}
|
|
192
|
+
// ─── Range Type Filters ──────────────────────────────────
|
|
193
|
+
/** Strictly left of: [a,b] << [c,d] */
|
|
194
|
+
rangeLt(column, range) {
|
|
195
|
+
this.params.set(column, `sl.${range}`);
|
|
196
|
+
return this;
|
|
197
|
+
}
|
|
198
|
+
/** Strictly right of: [a,b] >> [c,d] */
|
|
199
|
+
rangeGt(column, range) {
|
|
200
|
+
this.params.set(column, `sr.${range}`);
|
|
201
|
+
return this;
|
|
202
|
+
}
|
|
203
|
+
/** Does not extend to the left of */
|
|
204
|
+
rangeGte(column, range) {
|
|
205
|
+
this.params.set(column, `nxl.${range}`);
|
|
206
|
+
return this;
|
|
207
|
+
}
|
|
208
|
+
/** Does not extend to the right of */
|
|
209
|
+
rangeLte(column, range) {
|
|
210
|
+
this.params.set(column, `nxr.${range}`);
|
|
211
|
+
return this;
|
|
212
|
+
}
|
|
213
|
+
/** Range is adjacent to */
|
|
214
|
+
rangeAdjacent(column, range) {
|
|
215
|
+
this.params.set(column, `adj.${range}`);
|
|
216
|
+
return this;
|
|
217
|
+
}
|
|
170
218
|
// ─── Negation ───────────────────────────────────────────
|
|
171
219
|
/** Negate a filter: not.eq, not.in, not.is, etc. */
|
|
172
220
|
not(column, operator, value) {
|
|
@@ -175,29 +223,53 @@ var DatabaseClient = class {
|
|
|
175
223
|
}
|
|
176
224
|
// ─── Logical ────────────────────────────────────────────
|
|
177
225
|
/** OR filter: or("age.gt.20,name.eq.John") */
|
|
178
|
-
or(filters) {
|
|
179
|
-
|
|
226
|
+
or(filters, options) {
|
|
227
|
+
const key = options?.foreignTable ? `${options.foreignTable}.or` : "or";
|
|
228
|
+
this.params.set(key, `(${filters})`);
|
|
229
|
+
return this;
|
|
230
|
+
}
|
|
231
|
+
/** AND filter: and("age.gt.20,name.eq.John") */
|
|
232
|
+
and(filters, options) {
|
|
233
|
+
const key = options?.foreignTable ? `${options.foreignTable}.and` : "and";
|
|
234
|
+
this.params.set(key, `(${filters})`);
|
|
235
|
+
return this;
|
|
236
|
+
}
|
|
237
|
+
/** Generic filter: filter("column", "operator", "value") */
|
|
238
|
+
filter(column, operator, value) {
|
|
239
|
+
this.params.set(column, `${operator}.${value}`);
|
|
180
240
|
return this;
|
|
181
241
|
}
|
|
182
242
|
// ─── Full-Text Search ───────────────────────────────────
|
|
183
|
-
/** to_tsquery */
|
|
243
|
+
/** Full-text search (to_tsquery, plainto_tsquery, phraseto_tsquery, or websearch_to_tsquery) */
|
|
184
244
|
textSearch(column, query, options) {
|
|
185
245
|
const op = options?.type === "plain" ? "plfts" : options?.type === "phrase" ? "phfts" : options?.type === "websearch" ? "wfts" : "fts";
|
|
186
|
-
|
|
246
|
+
const config = options?.config ? `(${options.config})` : "";
|
|
247
|
+
this.params.set(column, `${op}${config}.${query}`);
|
|
187
248
|
return this;
|
|
188
249
|
}
|
|
189
250
|
// ─── Ordering & Pagination ──────────────────────────────
|
|
190
251
|
order(column, options) {
|
|
191
252
|
const dir = options?.ascending === false ? "desc" : "asc";
|
|
192
253
|
const nulls = options?.nullsFirst === true ? ".nullsfirst" : options?.nullsFirst === false ? ".nullslast" : "";
|
|
193
|
-
const
|
|
254
|
+
const key = options?.foreignTable ? `${options.foreignTable}.order` : "order";
|
|
255
|
+
const existing = this.params.get(key);
|
|
194
256
|
if (existing) {
|
|
195
|
-
this.params.set(
|
|
257
|
+
this.params.set(key, `${existing},${column}.${dir}${nulls}`);
|
|
196
258
|
} else {
|
|
197
|
-
this.params.set(
|
|
259
|
+
this.params.set(key, `${column}.${dir}${nulls}`);
|
|
198
260
|
}
|
|
199
261
|
return this;
|
|
200
262
|
}
|
|
263
|
+
/** Limit results on a foreign table */
|
|
264
|
+
limitForeignTable(count, foreignTable) {
|
|
265
|
+
this.params.set(`${foreignTable}.limit`, String(count));
|
|
266
|
+
return this;
|
|
267
|
+
}
|
|
268
|
+
/** Offset results on a foreign table */
|
|
269
|
+
offsetForeignTable(count, foreignTable) {
|
|
270
|
+
this.params.set(`${foreignTable}.offset`, String(count));
|
|
271
|
+
return this;
|
|
272
|
+
}
|
|
201
273
|
limit(count) {
|
|
202
274
|
this.params.set("limit", String(count));
|
|
203
275
|
return this;
|
package/dist/index.d.cts
CHANGED
|
@@ -39,14 +39,30 @@ declare class DatabaseClient {
|
|
|
39
39
|
count?: "exact" | "estimated" | "planned";
|
|
40
40
|
head?: boolean;
|
|
41
41
|
}): this;
|
|
42
|
-
insert(data: Record<string, any> | Record<string, any>[]
|
|
42
|
+
insert(data: Record<string, any> | Record<string, any>[], options?: {
|
|
43
|
+
defaultToNull?: boolean;
|
|
44
|
+
}): this;
|
|
43
45
|
/** Upsert: insert or update on conflict. Uses merge-duplicates by default. */
|
|
44
46
|
upsert(data: Record<string, any> | Record<string, any>[], options?: {
|
|
45
47
|
ignoreDuplicates?: boolean;
|
|
46
48
|
onConflict?: string;
|
|
49
|
+
defaultToNull?: boolean;
|
|
47
50
|
}): this;
|
|
48
51
|
update(data: Record<string, any>): this;
|
|
49
|
-
delete(
|
|
52
|
+
delete(options?: {
|
|
53
|
+
count?: "exact" | "estimated" | "planned";
|
|
54
|
+
}): this;
|
|
55
|
+
/** Specify return=minimal to skip returning data on mutations (better performance). */
|
|
56
|
+
returning(mode?: "minimal" | "representation"): this;
|
|
57
|
+
/** Get the query execution plan (EXPLAIN). */
|
|
58
|
+
explain(options?: {
|
|
59
|
+
analyze?: boolean;
|
|
60
|
+
verbose?: boolean;
|
|
61
|
+
settings?: boolean;
|
|
62
|
+
buffers?: boolean;
|
|
63
|
+
wal?: boolean;
|
|
64
|
+
format?: "json" | "text";
|
|
65
|
+
}): this;
|
|
50
66
|
eq(column: string, value: any): this;
|
|
51
67
|
neq(column: string, value: any): this;
|
|
52
68
|
gt(column: string, value: any): this;
|
|
@@ -69,18 +85,42 @@ declare class DatabaseClient {
|
|
|
69
85
|
is(column: string, value: "null" | "true" | "false" | null | boolean): this;
|
|
70
86
|
/** IS DISTINCT FROM */
|
|
71
87
|
isDistinct(column: string, value: any): this;
|
|
88
|
+
/** Strictly left of: [a,b] << [c,d] */
|
|
89
|
+
rangeLt(column: string, range: string): this;
|
|
90
|
+
/** Strictly right of: [a,b] >> [c,d] */
|
|
91
|
+
rangeGt(column: string, range: string): this;
|
|
92
|
+
/** Does not extend to the left of */
|
|
93
|
+
rangeGte(column: string, range: string): this;
|
|
94
|
+
/** Does not extend to the right of */
|
|
95
|
+
rangeLte(column: string, range: string): this;
|
|
96
|
+
/** Range is adjacent to */
|
|
97
|
+
rangeAdjacent(column: string, range: string): this;
|
|
72
98
|
/** Negate a filter: not.eq, not.in, not.is, etc. */
|
|
73
99
|
not(column: string, operator: string, value: any): this;
|
|
74
100
|
/** OR filter: or("age.gt.20,name.eq.John") */
|
|
75
|
-
or(filters: string
|
|
76
|
-
|
|
101
|
+
or(filters: string, options?: {
|
|
102
|
+
foreignTable?: string;
|
|
103
|
+
}): this;
|
|
104
|
+
/** AND filter: and("age.gt.20,name.eq.John") */
|
|
105
|
+
and(filters: string, options?: {
|
|
106
|
+
foreignTable?: string;
|
|
107
|
+
}): this;
|
|
108
|
+
/** Generic filter: filter("column", "operator", "value") */
|
|
109
|
+
filter(column: string, operator: string, value: any): this;
|
|
110
|
+
/** Full-text search (to_tsquery, plainto_tsquery, phraseto_tsquery, or websearch_to_tsquery) */
|
|
77
111
|
textSearch(column: string, query: string, options?: {
|
|
78
112
|
type?: "plain" | "phrase" | "websearch";
|
|
113
|
+
config?: string;
|
|
79
114
|
}): this;
|
|
80
115
|
order(column: string, options?: {
|
|
81
116
|
ascending?: boolean;
|
|
82
117
|
nullsFirst?: boolean;
|
|
118
|
+
foreignTable?: string;
|
|
83
119
|
}): this;
|
|
120
|
+
/** Limit results on a foreign table */
|
|
121
|
+
limitForeignTable(count: number, foreignTable: string): this;
|
|
122
|
+
/** Offset results on a foreign table */
|
|
123
|
+
offsetForeignTable(count: number, foreignTable: string): this;
|
|
84
124
|
limit(count: number): this;
|
|
85
125
|
offset(count: number): this;
|
|
86
126
|
/** Request exact, estimated, or planned count via Prefer header */
|
package/dist/index.d.ts
CHANGED
|
@@ -39,14 +39,30 @@ declare class DatabaseClient {
|
|
|
39
39
|
count?: "exact" | "estimated" | "planned";
|
|
40
40
|
head?: boolean;
|
|
41
41
|
}): this;
|
|
42
|
-
insert(data: Record<string, any> | Record<string, any>[]
|
|
42
|
+
insert(data: Record<string, any> | Record<string, any>[], options?: {
|
|
43
|
+
defaultToNull?: boolean;
|
|
44
|
+
}): this;
|
|
43
45
|
/** Upsert: insert or update on conflict. Uses merge-duplicates by default. */
|
|
44
46
|
upsert(data: Record<string, any> | Record<string, any>[], options?: {
|
|
45
47
|
ignoreDuplicates?: boolean;
|
|
46
48
|
onConflict?: string;
|
|
49
|
+
defaultToNull?: boolean;
|
|
47
50
|
}): this;
|
|
48
51
|
update(data: Record<string, any>): this;
|
|
49
|
-
delete(
|
|
52
|
+
delete(options?: {
|
|
53
|
+
count?: "exact" | "estimated" | "planned";
|
|
54
|
+
}): this;
|
|
55
|
+
/** Specify return=minimal to skip returning data on mutations (better performance). */
|
|
56
|
+
returning(mode?: "minimal" | "representation"): this;
|
|
57
|
+
/** Get the query execution plan (EXPLAIN). */
|
|
58
|
+
explain(options?: {
|
|
59
|
+
analyze?: boolean;
|
|
60
|
+
verbose?: boolean;
|
|
61
|
+
settings?: boolean;
|
|
62
|
+
buffers?: boolean;
|
|
63
|
+
wal?: boolean;
|
|
64
|
+
format?: "json" | "text";
|
|
65
|
+
}): this;
|
|
50
66
|
eq(column: string, value: any): this;
|
|
51
67
|
neq(column: string, value: any): this;
|
|
52
68
|
gt(column: string, value: any): this;
|
|
@@ -69,18 +85,42 @@ declare class DatabaseClient {
|
|
|
69
85
|
is(column: string, value: "null" | "true" | "false" | null | boolean): this;
|
|
70
86
|
/** IS DISTINCT FROM */
|
|
71
87
|
isDistinct(column: string, value: any): this;
|
|
88
|
+
/** Strictly left of: [a,b] << [c,d] */
|
|
89
|
+
rangeLt(column: string, range: string): this;
|
|
90
|
+
/** Strictly right of: [a,b] >> [c,d] */
|
|
91
|
+
rangeGt(column: string, range: string): this;
|
|
92
|
+
/** Does not extend to the left of */
|
|
93
|
+
rangeGte(column: string, range: string): this;
|
|
94
|
+
/** Does not extend to the right of */
|
|
95
|
+
rangeLte(column: string, range: string): this;
|
|
96
|
+
/** Range is adjacent to */
|
|
97
|
+
rangeAdjacent(column: string, range: string): this;
|
|
72
98
|
/** Negate a filter: not.eq, not.in, not.is, etc. */
|
|
73
99
|
not(column: string, operator: string, value: any): this;
|
|
74
100
|
/** OR filter: or("age.gt.20,name.eq.John") */
|
|
75
|
-
or(filters: string
|
|
76
|
-
|
|
101
|
+
or(filters: string, options?: {
|
|
102
|
+
foreignTable?: string;
|
|
103
|
+
}): this;
|
|
104
|
+
/** AND filter: and("age.gt.20,name.eq.John") */
|
|
105
|
+
and(filters: string, options?: {
|
|
106
|
+
foreignTable?: string;
|
|
107
|
+
}): this;
|
|
108
|
+
/** Generic filter: filter("column", "operator", "value") */
|
|
109
|
+
filter(column: string, operator: string, value: any): this;
|
|
110
|
+
/** Full-text search (to_tsquery, plainto_tsquery, phraseto_tsquery, or websearch_to_tsquery) */
|
|
77
111
|
textSearch(column: string, query: string, options?: {
|
|
78
112
|
type?: "plain" | "phrase" | "websearch";
|
|
113
|
+
config?: string;
|
|
79
114
|
}): this;
|
|
80
115
|
order(column: string, options?: {
|
|
81
116
|
ascending?: boolean;
|
|
82
117
|
nullsFirst?: boolean;
|
|
118
|
+
foreignTable?: string;
|
|
83
119
|
}): this;
|
|
120
|
+
/** Limit results on a foreign table */
|
|
121
|
+
limitForeignTable(count: number, foreignTable: string): this;
|
|
122
|
+
/** Offset results on a foreign table */
|
|
123
|
+
offsetForeignTable(count: number, foreignTable: string): this;
|
|
84
124
|
limit(count: number): this;
|
|
85
125
|
offset(count: number): this;
|
|
86
126
|
/** Request exact, estimated, or planned count via Prefer header */
|
package/dist/index.js
CHANGED
|
@@ -25,10 +25,11 @@ var DatabaseClient = class {
|
|
|
25
25
|
if (options?.count) this.preferHeaders.push(`count=${options.count}`);
|
|
26
26
|
return this;
|
|
27
27
|
}
|
|
28
|
-
insert(data) {
|
|
28
|
+
insert(data, options) {
|
|
29
29
|
this.method = "POST";
|
|
30
30
|
this.body = data;
|
|
31
31
|
this.preferHeaders.push("return=representation");
|
|
32
|
+
if (options?.defaultToNull === false) this.preferHeaders.push("missing=default");
|
|
32
33
|
return this;
|
|
33
34
|
}
|
|
34
35
|
/** Upsert: insert or update on conflict. Uses merge-duplicates by default. */
|
|
@@ -42,6 +43,7 @@ var DatabaseClient = class {
|
|
|
42
43
|
if (options?.onConflict) {
|
|
43
44
|
this.params.set("on_conflict", options.onConflict);
|
|
44
45
|
}
|
|
46
|
+
if (options?.defaultToNull === false) this.preferHeaders.push("missing=default");
|
|
45
47
|
return this;
|
|
46
48
|
}
|
|
47
49
|
update(data) {
|
|
@@ -50,8 +52,28 @@ var DatabaseClient = class {
|
|
|
50
52
|
this.preferHeaders.push("return=representation");
|
|
51
53
|
return this;
|
|
52
54
|
}
|
|
53
|
-
delete() {
|
|
55
|
+
delete(options) {
|
|
54
56
|
this.method = "DELETE";
|
|
57
|
+
if (options?.count) this.preferHeaders.push(`count=${options.count}`);
|
|
58
|
+
return this;
|
|
59
|
+
}
|
|
60
|
+
/** Specify return=minimal to skip returning data on mutations (better performance). */
|
|
61
|
+
returning(mode = "representation") {
|
|
62
|
+
this.preferHeaders = this.preferHeaders.filter((h) => !h.startsWith("return="));
|
|
63
|
+
this.preferHeaders.push(`return=${mode}`);
|
|
64
|
+
return this;
|
|
65
|
+
}
|
|
66
|
+
/** Get the query execution plan (EXPLAIN). */
|
|
67
|
+
explain(options) {
|
|
68
|
+
const parts = ["plan"];
|
|
69
|
+
if (options?.analyze) parts.push("analyze");
|
|
70
|
+
if (options?.verbose) parts.push("verbose");
|
|
71
|
+
if (options?.settings) parts.push("settings");
|
|
72
|
+
if (options?.buffers) parts.push("buffers");
|
|
73
|
+
if (options?.wal) parts.push("wal");
|
|
74
|
+
if (options?.format) parts.push(`format:${options.format}`);
|
|
75
|
+
this.preferHeaders = this.preferHeaders.filter((h) => !h.startsWith("plan"));
|
|
76
|
+
this.preferHeaders.push(parts.join("|"));
|
|
55
77
|
return this;
|
|
56
78
|
}
|
|
57
79
|
// ─── Comparison Filters ─────────────────────────────────
|
|
@@ -135,6 +157,32 @@ var DatabaseClient = class {
|
|
|
135
157
|
this.params.set(column, `isdistinct.${value}`);
|
|
136
158
|
return this;
|
|
137
159
|
}
|
|
160
|
+
// ─── Range Type Filters ──────────────────────────────────
|
|
161
|
+
/** Strictly left of: [a,b] << [c,d] */
|
|
162
|
+
rangeLt(column, range) {
|
|
163
|
+
this.params.set(column, `sl.${range}`);
|
|
164
|
+
return this;
|
|
165
|
+
}
|
|
166
|
+
/** Strictly right of: [a,b] >> [c,d] */
|
|
167
|
+
rangeGt(column, range) {
|
|
168
|
+
this.params.set(column, `sr.${range}`);
|
|
169
|
+
return this;
|
|
170
|
+
}
|
|
171
|
+
/** Does not extend to the left of */
|
|
172
|
+
rangeGte(column, range) {
|
|
173
|
+
this.params.set(column, `nxl.${range}`);
|
|
174
|
+
return this;
|
|
175
|
+
}
|
|
176
|
+
/** Does not extend to the right of */
|
|
177
|
+
rangeLte(column, range) {
|
|
178
|
+
this.params.set(column, `nxr.${range}`);
|
|
179
|
+
return this;
|
|
180
|
+
}
|
|
181
|
+
/** Range is adjacent to */
|
|
182
|
+
rangeAdjacent(column, range) {
|
|
183
|
+
this.params.set(column, `adj.${range}`);
|
|
184
|
+
return this;
|
|
185
|
+
}
|
|
138
186
|
// ─── Negation ───────────────────────────────────────────
|
|
139
187
|
/** Negate a filter: not.eq, not.in, not.is, etc. */
|
|
140
188
|
not(column, operator, value) {
|
|
@@ -143,29 +191,53 @@ var DatabaseClient = class {
|
|
|
143
191
|
}
|
|
144
192
|
// ─── Logical ────────────────────────────────────────────
|
|
145
193
|
/** OR filter: or("age.gt.20,name.eq.John") */
|
|
146
|
-
or(filters) {
|
|
147
|
-
|
|
194
|
+
or(filters, options) {
|
|
195
|
+
const key = options?.foreignTable ? `${options.foreignTable}.or` : "or";
|
|
196
|
+
this.params.set(key, `(${filters})`);
|
|
197
|
+
return this;
|
|
198
|
+
}
|
|
199
|
+
/** AND filter: and("age.gt.20,name.eq.John") */
|
|
200
|
+
and(filters, options) {
|
|
201
|
+
const key = options?.foreignTable ? `${options.foreignTable}.and` : "and";
|
|
202
|
+
this.params.set(key, `(${filters})`);
|
|
203
|
+
return this;
|
|
204
|
+
}
|
|
205
|
+
/** Generic filter: filter("column", "operator", "value") */
|
|
206
|
+
filter(column, operator, value) {
|
|
207
|
+
this.params.set(column, `${operator}.${value}`);
|
|
148
208
|
return this;
|
|
149
209
|
}
|
|
150
210
|
// ─── Full-Text Search ───────────────────────────────────
|
|
151
|
-
/** to_tsquery */
|
|
211
|
+
/** Full-text search (to_tsquery, plainto_tsquery, phraseto_tsquery, or websearch_to_tsquery) */
|
|
152
212
|
textSearch(column, query, options) {
|
|
153
213
|
const op = options?.type === "plain" ? "plfts" : options?.type === "phrase" ? "phfts" : options?.type === "websearch" ? "wfts" : "fts";
|
|
154
|
-
|
|
214
|
+
const config = options?.config ? `(${options.config})` : "";
|
|
215
|
+
this.params.set(column, `${op}${config}.${query}`);
|
|
155
216
|
return this;
|
|
156
217
|
}
|
|
157
218
|
// ─── Ordering & Pagination ──────────────────────────────
|
|
158
219
|
order(column, options) {
|
|
159
220
|
const dir = options?.ascending === false ? "desc" : "asc";
|
|
160
221
|
const nulls = options?.nullsFirst === true ? ".nullsfirst" : options?.nullsFirst === false ? ".nullslast" : "";
|
|
161
|
-
const
|
|
222
|
+
const key = options?.foreignTable ? `${options.foreignTable}.order` : "order";
|
|
223
|
+
const existing = this.params.get(key);
|
|
162
224
|
if (existing) {
|
|
163
|
-
this.params.set(
|
|
225
|
+
this.params.set(key, `${existing},${column}.${dir}${nulls}`);
|
|
164
226
|
} else {
|
|
165
|
-
this.params.set(
|
|
227
|
+
this.params.set(key, `${column}.${dir}${nulls}`);
|
|
166
228
|
}
|
|
167
229
|
return this;
|
|
168
230
|
}
|
|
231
|
+
/** Limit results on a foreign table */
|
|
232
|
+
limitForeignTable(count, foreignTable) {
|
|
233
|
+
this.params.set(`${foreignTable}.limit`, String(count));
|
|
234
|
+
return this;
|
|
235
|
+
}
|
|
236
|
+
/** Offset results on a foreign table */
|
|
237
|
+
offsetForeignTable(count, foreignTable) {
|
|
238
|
+
this.params.set(`${foreignTable}.offset`, String(count));
|
|
239
|
+
return this;
|
|
240
|
+
}
|
|
169
241
|
limit(count) {
|
|
170
242
|
this.params.set("limit", String(count));
|
|
171
243
|
return this;
|