@protobase/schema 0.13.4 → 0.14.1
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/access/capability.d.ts +3 -0
- package/dist/access/index.d.ts +3 -3
- package/dist/access/resolve.d.ts +13 -0
- package/dist/access/role-entry.d.ts +5 -0
- package/dist/access/roles.d.ts +14 -0
- package/dist/access/roles.js +11 -0
- package/dist/access/rule.d.ts +10 -0
- package/dist/access/rule.js +10 -0
- package/dist/access/types.d.ts +11 -0
- package/dist/assistant/protocol.d.ts +67 -2
- package/dist/bottom-bar-errors.d.ts +3 -0
- package/dist/bottom-bar.d.ts +3 -1
- package/dist/bottom-bar.js +2 -1
- package/dist/events/event-helpers.d.ts +41 -8
- package/dist/events/event-helpers.js +1 -3
- package/dist/field-ref.d.ts +1 -0
- package/dist/field.d.ts +54 -1
- package/dist/field.js +16 -0
- package/dist/fields.d.ts +31 -0
- package/dist/fields.js +31 -0
- package/dist/file-field.d.ts +6 -1
- package/dist/file-field.js +6 -1
- package/dist/files/file-options.d.ts +17 -0
- package/dist/filter/check.d.ts +5 -0
- package/dist/filter/evaluate.d.ts +1 -0
- package/dist/filter/order-by.d.ts +14 -0
- package/dist/filter/order-by.js +2 -0
- package/dist/filter/parse.d.ts +16 -2
- package/dist/filter/parse.js +8 -2
- package/dist/filter/where.d.ts +61 -0
- package/dist/filter/where.js +34 -0
- package/dist/index.d.ts +16 -24
- package/dist/index.js +6 -18
- package/dist/internal.d.ts +17 -0
- package/dist/internal.js +17 -0
- package/dist/keys.d.ts +1 -0
- package/dist/layout.d.ts +15 -0
- package/dist/layout.js +15 -0
- package/dist/model.d.ts +344 -6
- package/dist/refs.d.ts +6 -0
- package/dist/relation-field.d.ts +5 -0
- package/dist/relation-field.js +5 -0
- package/dist/resource-types.d.ts +18 -0
- package/dist/resource.d.ts +94 -6
- package/dist/resource.js +75 -2
- package/dist/user-menu.d.ts +5 -1
- package/dist/user-menu.js +4 -1
- package/dist/view-actions.d.ts +1 -0
- package/dist/view-displays.d.ts +3 -0
- package/dist/view-field.d.ts +14 -1
- package/dist/view-field.js +7 -0
- package/dist/view-widgets.d.ts +7 -0
- package/dist/view-widgets.js +7 -0
- package/dist/view.d.ts +52 -4
- package/dist/view.js +39 -2
- package/dist/webhooks/webhook-resources.js +1 -1
- package/package.json +3 -2
package/dist/model.d.ts
CHANGED
|
@@ -1,34 +1,57 @@
|
|
|
1
1
|
import { ImageVariant } from "./files/file-options.js";
|
|
2
2
|
//#region src/model.d.ts
|
|
3
|
+
/** A field's storage type, as `f.*` declares it; see [Field types](website/src/content/docs/reference/data-config.mdx#field-types). */
|
|
3
4
|
export type FieldType = 'text' | 'integer' | 'bigint' | 'decimal' | 'boolean' | 'date' | 'timestamp' | 'uuid' | 'enum' | 'json' | 'relation' | 'file' | 'currency' | 'country';
|
|
5
|
+
/**
|
|
6
|
+
* A field of a resource as the server and the app see it, built from its `f.*` builder and options; see
|
|
7
|
+
* [Field options](website/src/content/docs/reference/data-config.mdx#field-options).
|
|
8
|
+
*/
|
|
4
9
|
export type FieldModel = {
|
|
10
|
+
/** The field's name: in URLs, the API, filters and sorts. */
|
|
5
11
|
name: string;
|
|
12
|
+
/** The table column it reads and writes: the snake_case of the name unless `.column()` says otherwise. */
|
|
6
13
|
column: string;
|
|
14
|
+
/** Its storage type. */
|
|
7
15
|
type: FieldType;
|
|
16
|
+
/** Whether the value may be `null` (`.optional()`). */
|
|
8
17
|
nullable: boolean;
|
|
18
|
+
/** Never written through the API (`.readOnly()`). */
|
|
9
19
|
readOnly: boolean;
|
|
20
|
+
/** May appear in filters and filter widgets (`.filterable()`). */
|
|
10
21
|
filterable: boolean;
|
|
22
|
+
/** May appear in `order_by` and sorts (`.sortable()`). */
|
|
11
23
|
sortable: boolean;
|
|
24
|
+
/** Other names filters may use for the field (`.alias()`). */
|
|
12
25
|
aliases: string[];
|
|
26
|
+
/** An enum's values, in order. */
|
|
13
27
|
enumValues?: string[];
|
|
28
|
+
/** A relation's target. */
|
|
14
29
|
relation?: {
|
|
30
|
+
/** The resource it points at. */
|
|
15
31
|
resource: string;
|
|
32
|
+
/** The columns of this table holding the other record's key, in the order of that key. */
|
|
16
33
|
columns: string[];
|
|
17
34
|
};
|
|
18
35
|
/** Never sent with the record; revealed one value at a time (`.sensitive()`). */
|
|
19
36
|
sensitive?: true;
|
|
20
37
|
/** A value the form prefills, or `db` when the database supplies it (identity, now(), ...). */
|
|
21
38
|
default?: {
|
|
39
|
+
/** The value a create uses when none is given (`.default()`). */
|
|
22
40
|
value: unknown;
|
|
23
41
|
} | {
|
|
42
|
+
/** The database supplies the value (`.dbDefault()`). */
|
|
24
43
|
db: true;
|
|
25
44
|
};
|
|
26
45
|
/** A file field's allowed types (empty: any), largest upload in bytes, provider, and what each upload writes. */
|
|
27
46
|
file?: FileFieldModel;
|
|
28
47
|
};
|
|
48
|
+
/** A file field's settings, as `/meta` gives them; see [Files](website/src/content/docs/reference/files.mdx). */
|
|
29
49
|
export type FileFieldModel = {
|
|
50
|
+
/** The content types an upload may have, exact or `type/*`; any when empty. */
|
|
30
51
|
accept: string[];
|
|
52
|
+
/** The largest upload, in bytes. */
|
|
31
53
|
maxSize: number;
|
|
54
|
+
/** The name of the storage provider the files go to. */
|
|
32
55
|
provider: string;
|
|
33
56
|
/** The fields each upload writes: those of `.derive()` and the placeholder's. */
|
|
34
57
|
derive?: string[];
|
|
@@ -41,15 +64,27 @@ export type FileFieldModel = {
|
|
|
41
64
|
};
|
|
42
65
|
/** `digitsEnd`: only the end of the value's digits, spaces, `+` and dashes ignored (phone numbers). */
|
|
43
66
|
export type SearchMatch = 'digitsEnd';
|
|
67
|
+
/**
|
|
68
|
+
* A resource as the server and the app see it: a table, its fields and what the API does with them, built by
|
|
69
|
+
* `resource(...).toModel()`; see [resource()](website/src/content/docs/reference/data-config.mdx#resource).
|
|
70
|
+
*/
|
|
44
71
|
export type ResourceModel = {
|
|
72
|
+
/** The resource's name: its address (`/api/v1/<name>`, `/<name>` in the admin) and how other config refers to it. */
|
|
45
73
|
name: string;
|
|
74
|
+
/** The table it reads and writes. */
|
|
46
75
|
table: {
|
|
76
|
+
/** The table's schema; the search path decides when omitted. */
|
|
47
77
|
schema?: string;
|
|
78
|
+
/** The table's name. */
|
|
48
79
|
name: string;
|
|
49
80
|
};
|
|
81
|
+
/** Its fields, by field name. */
|
|
50
82
|
fields: Record<string, FieldModel>;
|
|
83
|
+
/** The fields of its key, in order; records are addressed by it. */
|
|
51
84
|
primaryKey: string[];
|
|
85
|
+
/** The field a delete sets instead of removing the row, and lists leave such rows out (`.softDelete()`). */
|
|
52
86
|
softDelete?: string;
|
|
87
|
+
/** The field that separates tenants: every query is limited to the caller's tenant (`.tenant()`). */
|
|
53
88
|
tenant?: string;
|
|
54
89
|
/** Field names that the bare-text `search` filter matches against. */
|
|
55
90
|
search?: string[];
|
|
@@ -65,74 +100,118 @@ export type EventOperation = 'create' | 'update' | 'delete' | 'undelete';
|
|
|
65
100
|
/**
|
|
66
101
|
* An event a resource declares. It fires for a change whose operation is listed and that passes every condition:
|
|
67
102
|
* `when` on the record after the change, `from` on the record before it, `becomes` turning true (false or no record
|
|
68
|
-
* before, true after), one of the `changed` fields changing, and a code predicate when `match` is set.
|
|
103
|
+
* before, true after), one of the `changed` fields changing, and a code predicate when `match` is set. See
|
|
104
|
+
* [Declaring events](website/src/content/docs/reference/events.mdx#declaring-events).
|
|
69
105
|
*/
|
|
70
106
|
export type EventModel = {
|
|
71
107
|
/** `<resource>.<name>`, such as `orders.created`. */
|
|
72
108
|
name: string;
|
|
109
|
+
/** The operations it fires for. */
|
|
73
110
|
operations: EventOperation[];
|
|
111
|
+
/** A filter the record after the change must pass. */
|
|
74
112
|
when?: string;
|
|
113
|
+
/** A filter the record before the change must pass. */
|
|
75
114
|
from?: string;
|
|
115
|
+
/** A filter that must turn true with the change: false or no record before, true after. */
|
|
76
116
|
becomes?: string;
|
|
117
|
+
/** Fields of which at least one must change. */
|
|
77
118
|
changed?: string[];
|
|
78
119
|
/** A code predicate decides too; it stays in the config. */
|
|
79
120
|
match?: true;
|
|
80
121
|
};
|
|
122
|
+
/** A sort: fields with their direction, the first deciding most. */
|
|
81
123
|
export type SortSpec = Array<[field: string, direction: 'asc' | 'desc']>;
|
|
82
124
|
/** A value that survives `JSON.stringify` unchanged, as a custom component's props in a view must be. */
|
|
83
125
|
export type JsonValue = string | number | boolean | null | JsonValue[] | {
|
|
84
126
|
[key: string]: JsonValue;
|
|
85
127
|
};
|
|
128
|
+
/** One part of a record's key: a number for integer keys, text for the others (`bigint` included). */
|
|
86
129
|
export type KeyValue = string | number;
|
|
130
|
+
/** One page of a list, as the query package reads it from the database. */
|
|
87
131
|
export type ListQuery = {
|
|
132
|
+
/** The rows it keeps, already checked against the resource. */
|
|
88
133
|
filter?: CheckedFilter;
|
|
134
|
+
/** The order; the primary key decides ties. */
|
|
89
135
|
sort?: SortSpec;
|
|
136
|
+
/** The fields it reads, by name; every field when omitted. */
|
|
90
137
|
columns?: string[];
|
|
138
|
+
/** Where the page starts: a cursor from a previous page. */
|
|
91
139
|
cursor?: string;
|
|
140
|
+
/** Whether the page comes after the cursor (the default) or before it. */
|
|
92
141
|
direction?: 'after' | 'before';
|
|
142
|
+
/** The most rows the page holds. */
|
|
93
143
|
limit: number;
|
|
94
144
|
};
|
|
145
|
+
/** Where a list page's filters sit on a wide screen: in a `bar` over the list, or a `panel` beside it. */
|
|
95
146
|
export type FilterLayout = 'bar' | 'panel';
|
|
96
147
|
/** Where a list's map display looks: the centre in decimal degrees, and MapLibre's zoom, from 0 to 22. */
|
|
97
148
|
export type MapView = {
|
|
149
|
+
/** The centre's latitude, in decimal degrees. */
|
|
98
150
|
latitude: number;
|
|
151
|
+
/** The centre's longitude, in decimal degrees. */
|
|
99
152
|
longitude: number;
|
|
153
|
+
/** MapLibre's zoom, from 0 to 22. */
|
|
100
154
|
zoom: number;
|
|
101
155
|
};
|
|
102
156
|
/**
|
|
103
157
|
* A place in the app: a resource's list, one of its records, its create form, or a composed page. A record's `key` is
|
|
104
158
|
* its one value or its parts, as the record API takes them; `readAppPath` gives it back as the API's text form. A create
|
|
105
159
|
* form's `values` fill in fields of the new record by name, as text (`{ listing_id: '42' }`). A list's `map` is where its
|
|
106
|
-
* map display looks.
|
|
160
|
+
* map display looks. See [Addresses](website/src/content/docs/reference/layouts.md#addresses).
|
|
107
161
|
*/
|
|
108
162
|
export type AppAddress = {
|
|
163
|
+
/** A resource's list. */
|
|
109
164
|
kind: 'list';
|
|
165
|
+
/** The resource listed. */
|
|
110
166
|
resource: string;
|
|
167
|
+
/** An AIP-160 filter on the list. */
|
|
111
168
|
filter?: string;
|
|
169
|
+
/** An AIP-132 order of the list. */
|
|
112
170
|
orderBy?: string;
|
|
171
|
+
/** The display the list shows in, by name; its default when omitted. */
|
|
113
172
|
display?: string;
|
|
173
|
+
/** Where its filters sit. */
|
|
114
174
|
filterLayout?: FilterLayout;
|
|
175
|
+
/** Where its map display looks. */
|
|
115
176
|
map?: MapView;
|
|
116
177
|
} | {
|
|
178
|
+
/** One record. */
|
|
117
179
|
kind: 'record';
|
|
180
|
+
/** The record's resource. */
|
|
118
181
|
resource: string;
|
|
182
|
+
/** The record's key: its value, or its parts for a composite key. */
|
|
119
183
|
key: KeyValue | readonly KeyValue[];
|
|
120
184
|
} | {
|
|
185
|
+
/** The form for a new record. */
|
|
121
186
|
kind: 'create';
|
|
187
|
+
/** The resource the record is created in. */
|
|
122
188
|
resource: string;
|
|
189
|
+
/** Fields of the new record filled in by name, as text; a start the person can change. */
|
|
123
190
|
values?: Readonly<Record<string, string>>;
|
|
124
191
|
} | {
|
|
192
|
+
/** A composed page. */
|
|
125
193
|
kind: 'page';
|
|
194
|
+
/** The page's name. */
|
|
126
195
|
page: string;
|
|
127
196
|
};
|
|
197
|
+
/**
|
|
198
|
+
* How a value is shown: `badge` as a coloured badge, `code` in monospace, `percent` with a % sign. `relative`,
|
|
199
|
+
* `absolute` and `compact` are carried in `/meta` for apps that render their own lists.
|
|
200
|
+
*/
|
|
128
201
|
export type FieldFormat = 'relative' | 'absolute' | 'compact' | 'percent' | 'badge' | 'code';
|
|
202
|
+
/** A view's hints for one field (`.fields((r) => ...)`); see [Names and columns](website/src/content/docs/reference/ui-config.mdx#names-and-columns). */
|
|
129
203
|
export type FieldViewModel = {
|
|
204
|
+
/** What the field is called, instead of its name in words. */
|
|
130
205
|
label?: string;
|
|
206
|
+
/** A line under the field on the record page and in forms. */
|
|
131
207
|
help?: string;
|
|
208
|
+
/** How the value is shown. */
|
|
132
209
|
format?: FieldFormat;
|
|
210
|
+
/** Text before a number wherever it is shown, such as `€`. */
|
|
133
211
|
prefix?: string;
|
|
134
212
|
/** Text after a number wherever it is shown, such as a unit: `m²` shows `120 m²`. */
|
|
135
213
|
suffix?: string;
|
|
214
|
+
/** How many decimals a number shows. */
|
|
136
215
|
decimals?: number;
|
|
137
216
|
/** An icon before the value on a card's meta row, by the names actions take (`ruler`); an unknown name shows none. */
|
|
138
217
|
icon?: string;
|
|
@@ -148,10 +227,13 @@ export type FieldViewModel = {
|
|
|
148
227
|
*/
|
|
149
228
|
widget?: FieldWidgetModel;
|
|
150
229
|
};
|
|
230
|
+
/** How a field's badges are drawn: `arrow` points them right, as on a rating scale. */
|
|
151
231
|
export type BadgeShape = 'arrow';
|
|
152
232
|
/** A field type by the name a plugin registers it under, and the plain data it is given. */
|
|
153
233
|
export type FieldWidgetModel = {
|
|
234
|
+
/** The name the field type is registered under. */
|
|
154
235
|
name: string;
|
|
236
|
+
/** The plain data it is given. */
|
|
155
237
|
props?: Record<string, JsonValue>;
|
|
156
238
|
};
|
|
157
239
|
/**
|
|
@@ -159,52 +241,89 @@ export type FieldWidgetModel = {
|
|
|
159
241
|
* a map of the records at their `latitude` and `longitude`, each opening the card of the cards display named `cards`
|
|
160
242
|
* (`map`), or a project component (`custom`) drawing the rows the list page loads. A card's `amount` is the first of its fields with
|
|
161
243
|
* a value, `footer` its fields with a value joined by bullets, and `flags` boolean fields shown as small badges of their
|
|
162
|
-
* labels when true. `name` is what the address names (`?display=cards`); `label` and `icon` are its switch's.
|
|
244
|
+
* labels when true. `name` is what the address names (`?display=cards`); `label` and `icon` are its switch's. See
|
|
245
|
+
* [List displays](website/src/content/docs/reference/ui-config.mdx#list-displays).
|
|
163
246
|
*/
|
|
164
247
|
export type ListDisplayModel = {
|
|
248
|
+
/** A card per record. */
|
|
165
249
|
kind: 'cards';
|
|
250
|
+
/** What the address names (`?display=cards`). */
|
|
166
251
|
name: string;
|
|
252
|
+
/** The display's name in the switch. */
|
|
167
253
|
label?: string;
|
|
254
|
+
/** The display's icon in the switch. */
|
|
168
255
|
icon?: string;
|
|
256
|
+
/** A file field shown as a picture across the card's top. */
|
|
169
257
|
image?: string;
|
|
258
|
+
/** The card's title; the view's title when omitted. */
|
|
170
259
|
title?: string;
|
|
260
|
+
/** The line under the title. */
|
|
171
261
|
subtitle?: string;
|
|
262
|
+
/** Fields of which the first with a value shows in bold, such as a price or a rent. */
|
|
172
263
|
amount?: string[];
|
|
264
|
+
/** A field drawn as a badge with its value labels. */
|
|
173
265
|
badge?: string;
|
|
266
|
+
/** A few small fields, such as dates, each shown when it has a value. */
|
|
174
267
|
meta?: string[];
|
|
268
|
+
/** Fields joined by bullets on a line at the card's bottom. */
|
|
175
269
|
footer?: string[];
|
|
270
|
+
/** Boolean fields shown as small badges of their labels when true. */
|
|
176
271
|
flags?: string[];
|
|
272
|
+
/** The component that draws each card's content instead of the built-in card. */
|
|
177
273
|
card?: string;
|
|
274
|
+
/** Where the card's further photos come from. */
|
|
178
275
|
photos?: CardPhotosModel;
|
|
179
276
|
} | {
|
|
277
|
+
/** A map of the records at their position. */
|
|
180
278
|
kind: 'map';
|
|
279
|
+
/** What the address names (`?display=map`). */
|
|
181
280
|
name: string;
|
|
281
|
+
/** The display's name in the switch. */
|
|
182
282
|
label?: string;
|
|
283
|
+
/** The display's icon in the switch. */
|
|
183
284
|
icon?: string;
|
|
285
|
+
/** The filterable number field holding each record's latitude, in decimal degrees. */
|
|
184
286
|
latitude: string;
|
|
287
|
+
/** The filterable number field holding each record's longitude, in decimal degrees. */
|
|
185
288
|
longitude: string;
|
|
289
|
+
/** The cards display whose card a chosen marker shows; the list's first cards display when omitted. */
|
|
186
290
|
cards?: string;
|
|
187
291
|
} | {
|
|
292
|
+
/** The rows drawn by a project component. */
|
|
188
293
|
kind: 'custom';
|
|
294
|
+
/** What the address names (`?display=board`). */
|
|
189
295
|
name: string;
|
|
296
|
+
/** The display's name in the switch. */
|
|
190
297
|
label: string;
|
|
298
|
+
/** The display's icon in the switch. */
|
|
191
299
|
icon?: string;
|
|
300
|
+
/** The component's name, as `protobase.ui.tsx` registers it. */
|
|
192
301
|
component: string;
|
|
302
|
+
/** The fields it shows, loaded with the names of the records relations point at. */
|
|
193
303
|
fields: string[];
|
|
304
|
+
/** The plain data the component gets, with field references where it takes a field. */
|
|
194
305
|
props?: Record<string, JsonValue>;
|
|
195
306
|
};
|
|
196
307
|
/**
|
|
197
308
|
* Where a card's further photos come from: the records of `resource` whose relation `field` points at the card's record,
|
|
198
|
-
* in `sort` order, each shown by its file field `image`. The card loads them when its arrows are first used.
|
|
309
|
+
* in `sort` order, each shown by its file field `image`. The card loads them when its arrows are first used. See
|
|
310
|
+
* [Card photos](website/src/content/docs/reference/ui-config.mdx#card-photos).
|
|
199
311
|
*/
|
|
200
312
|
export type CardPhotosModel = {
|
|
313
|
+
/** The resource holding the photos. */
|
|
201
314
|
resource: string;
|
|
315
|
+
/** Its filterable relation that points at the card's record. */
|
|
202
316
|
field: string;
|
|
317
|
+
/** Its file field holding each photo. */
|
|
203
318
|
image: string;
|
|
319
|
+
/** An AIP-132 order of the photos. */
|
|
204
320
|
sort?: string;
|
|
205
321
|
};
|
|
322
|
+
/** A view's list page (`.list(...)`). */
|
|
206
323
|
export type ListModel = {
|
|
324
|
+
/** The table's columns, in order. */
|
|
207
325
|
columns: string[];
|
|
326
|
+
/** The order the list starts in. */
|
|
208
327
|
sort?: SortSpec;
|
|
209
328
|
/** Defaults for the UI's search box. `ResourceModel.search` is authoritative for what `search(...)` matches on the server. */
|
|
210
329
|
search?: string[];
|
|
@@ -213,44 +332,76 @@ export type ListModel = {
|
|
|
213
332
|
/** The display the list opens in when the address names none; the table when omitted. */
|
|
214
333
|
default?: string;
|
|
215
334
|
};
|
|
335
|
+
/** A button of a date range filter: today, yesterday, the last 7, 30 or 90 days, or this month, quarter or year. */
|
|
216
336
|
export type DatePreset = 'today' | 'yesterday' | '7d' | '30d' | '90d' | 'month' | 'quarter' | 'year';
|
|
337
|
+
/**
|
|
338
|
+
* A filter widget above a list (`.filters((r, w) => ...)`), on a filterable field; see
|
|
339
|
+
* [Filters and the chart](website/src/content/docs/reference/ui-config.mdx#filters-and-the-chart).
|
|
340
|
+
*/
|
|
217
341
|
export type FilterWidgetModel = {
|
|
342
|
+
/** A slider between the lowest and highest value. */
|
|
218
343
|
kind: 'range';
|
|
344
|
+
/** The field it filters. */
|
|
219
345
|
field: string;
|
|
346
|
+
/** Whether the values' histogram is drawn behind the slider. */
|
|
220
347
|
histogram: boolean;
|
|
221
348
|
} | {
|
|
349
|
+
/** A menu of the field's values with counts. */
|
|
222
350
|
kind: 'facets';
|
|
351
|
+
/** The field it filters. */
|
|
223
352
|
field: string;
|
|
353
|
+
/** Whether the menu has a search box, for long lists. */
|
|
224
354
|
search: boolean;
|
|
225
355
|
} | {
|
|
356
|
+
/** Buttons for date ranges. */
|
|
226
357
|
kind: 'dateRange';
|
|
358
|
+
/** The date or timestamp field it filters. */
|
|
227
359
|
field: string;
|
|
360
|
+
/** The buttons it shows. */
|
|
228
361
|
presets: DatePreset[];
|
|
229
362
|
} | {
|
|
363
|
+
/** A switch for a boolean field. */
|
|
230
364
|
kind: 'toggle';
|
|
365
|
+
/** The boolean field it filters. */
|
|
231
366
|
field: string;
|
|
232
367
|
} | {
|
|
368
|
+
/** A menu of boolean fields under one label; a record shows when any chosen field is true. */
|
|
233
369
|
kind: 'flags';
|
|
370
|
+
/** The boolean fields it offers. */
|
|
234
371
|
fields: string[];
|
|
372
|
+
/** The menu's label. */
|
|
235
373
|
label: string;
|
|
236
374
|
};
|
|
237
375
|
/**
|
|
238
376
|
* Records of another resource on the record page: those whose `field` holds this record's key or, with `through`,
|
|
239
377
|
* those whose `field` holds one of the `key` values of the `through` records that point at this record (a join table).
|
|
378
|
+
* See [Related records](website/src/content/docs/reference/ui-config.mdx#related-records).
|
|
240
379
|
*/
|
|
241
380
|
export type RelatedModel = {
|
|
381
|
+
/** A related records section. */
|
|
242
382
|
kind: 'related';
|
|
383
|
+
/** The section's title. */
|
|
243
384
|
title: string;
|
|
385
|
+
/** A line under the title. */
|
|
244
386
|
help?: string;
|
|
387
|
+
/** The resource whose records it lists. */
|
|
245
388
|
resource: string;
|
|
389
|
+
/** The filterable field of `resource` matched against this record's key, or with `through` against the join records' keys. */
|
|
246
390
|
field: string;
|
|
391
|
+
/** The join records between this record and the listed ones. */
|
|
247
392
|
through?: {
|
|
393
|
+
/** The join resource. */
|
|
248
394
|
resource: string;
|
|
395
|
+
/** Its filterable relation that holds this record's key. */
|
|
249
396
|
field: string;
|
|
397
|
+
/** Its field whose values pick the listed records; its primary key when omitted. */
|
|
250
398
|
key?: string;
|
|
399
|
+
/** An AIP-160 filter on the join records. */
|
|
251
400
|
filter?: string;
|
|
252
401
|
};
|
|
402
|
+
/** An AIP-160 filter on the listed records. */
|
|
253
403
|
filter?: string;
|
|
404
|
+
/** An AIP-132 order of the listed records. */
|
|
254
405
|
sort?: string;
|
|
255
406
|
/** Fields of `resource`, through relations too (`unitId.propertyId`). */
|
|
256
407
|
columns?: string[];
|
|
@@ -258,6 +409,7 @@ export type RelatedModel = {
|
|
|
258
409
|
limit?: number;
|
|
259
410
|
/** The display of `resource`'s list it opens in, such as `cards`; the list's default when omitted. */
|
|
260
411
|
display?: string;
|
|
412
|
+
/** The text when nothing matches. */
|
|
261
413
|
empty?: string;
|
|
262
414
|
};
|
|
263
415
|
/**
|
|
@@ -265,41 +417,66 @@ export type RelatedModel = {
|
|
|
265
417
|
* sidebar, under `title` when it has one. It gets `props` and reads the record with `useLayoutRecord()`.
|
|
266
418
|
*/
|
|
267
419
|
export type CustomSectionModel = {
|
|
420
|
+
/** A custom section. */
|
|
268
421
|
kind: 'custom';
|
|
422
|
+
/** The component's name, as `protobase.ui.tsx` registers it. */
|
|
269
423
|
component: string;
|
|
424
|
+
/** The title over it. */
|
|
270
425
|
title?: string;
|
|
426
|
+
/** The plain data the component gets, with field references where it takes a field. */
|
|
271
427
|
props?: Record<string, JsonValue>;
|
|
428
|
+
/** Drawn as a sidebar card instead of in the main column. */
|
|
272
429
|
sidebar?: true;
|
|
273
430
|
};
|
|
274
431
|
/**
|
|
275
432
|
* A map of the record's position, its `latitude` and `longitude` fields in decimal degrees (WGS84), centred on a marker
|
|
276
433
|
* at `zoom`: in the main column under `title`, or with `sidebar` as a sidebar card. The app draws it with the map style
|
|
277
|
-
* its server names, and leaves it out without one.
|
|
434
|
+
* its server names, and leaves it out without one. See [Maps](website/src/content/docs/reference/ui-config.mdx#maps).
|
|
278
435
|
*/
|
|
279
436
|
export type MapSectionModel = {
|
|
437
|
+
/** A map section. */
|
|
280
438
|
kind: 'map';
|
|
439
|
+
/** The section's title. */
|
|
281
440
|
title: string;
|
|
441
|
+
/** The number field holding the record's latitude. */
|
|
282
442
|
latitude: string;
|
|
443
|
+
/** The number field holding the record's longitude. */
|
|
283
444
|
longitude: string;
|
|
445
|
+
/** MapLibre's zoom, from 0 to 22; 15 when omitted. */
|
|
284
446
|
zoom?: number;
|
|
447
|
+
/** Drawn as a sidebar card instead of in the main column. */
|
|
285
448
|
sidebar?: true;
|
|
286
449
|
};
|
|
450
|
+
/** An item of the record page (`.layout((r) => ...)` with `l`); see [The record page](website/src/content/docs/reference/ui-config.mdx#the-record-page). */
|
|
287
451
|
export type LayoutItemModel = {
|
|
452
|
+
/** A titled group of fields in the main column, editable where the user may write. */
|
|
288
453
|
kind: 'section';
|
|
454
|
+
/** The section's title. */
|
|
289
455
|
title: string;
|
|
456
|
+
/** The fields it shows, in order. */
|
|
290
457
|
fields: string[];
|
|
458
|
+
/** A line under the title. */
|
|
291
459
|
help?: string;
|
|
292
460
|
} | {
|
|
461
|
+
/** A read-only summary card beside the main column. */
|
|
293
462
|
kind: 'sidebar';
|
|
463
|
+
/** The fields it shows, in order. */
|
|
294
464
|
fields: string[];
|
|
295
465
|
} | RelatedModel | CustomSectionModel | MapSectionModel;
|
|
466
|
+
/** How far back a list's chart reaches. */
|
|
296
467
|
export type ChartRange = '7d' | '30d' | '90d' | '1y' | 'all';
|
|
468
|
+
/** How long each bar of a list's chart is. */
|
|
297
469
|
export type ChartGranularity = 'hour' | 'day' | 'week' | 'month';
|
|
470
|
+
/** A chart of records over time above a list, following its filters (`.chart(...)`). */
|
|
298
471
|
export type ChartModel = {
|
|
472
|
+
/** The date or timestamp field the records are counted by. */
|
|
299
473
|
field: string;
|
|
474
|
+
/** How far back it reaches. */
|
|
300
475
|
range: ChartRange;
|
|
476
|
+
/** How long each bar is. */
|
|
301
477
|
granularity: ChartGranularity;
|
|
302
478
|
};
|
|
479
|
+
/** How the record page shows that a save went through: a `toast` (the default) or on the Save `button`. */
|
|
303
480
|
export type SaveFeedback = 'toast' | 'button';
|
|
304
481
|
/**
|
|
305
482
|
* What a named action does in the app: set fields of the record (`update`), delete it (`delete`), go to an address in
|
|
@@ -307,23 +484,37 @@ export type SaveFeedback = 'toast' | 'button';
|
|
|
307
484
|
* values. Without it the app runs a handler it registered by name.
|
|
308
485
|
*/
|
|
309
486
|
export type ActionRun = {
|
|
487
|
+
/** Updates the record. */
|
|
310
488
|
kind: 'update';
|
|
489
|
+
/** The fields it sets, by name. */
|
|
311
490
|
values: Record<string, unknown>;
|
|
312
491
|
} | {
|
|
492
|
+
/** Deletes the record, soft deleting when the resource does. */
|
|
313
493
|
kind: 'delete';
|
|
314
494
|
} | {
|
|
495
|
+
/** Goes to an address in the app. */
|
|
315
496
|
kind: 'link';
|
|
497
|
+
/** The address, with `{field}` replaced by the record's values. */
|
|
316
498
|
to: AppAddress;
|
|
317
499
|
} | {
|
|
500
|
+
/** Opens a link that leaves the app. */
|
|
318
501
|
kind: 'link';
|
|
502
|
+
/** The link (`https:`, `mailto:`), with `{field}` replaced by the record's values, percent-encoded. */
|
|
319
503
|
href: string;
|
|
320
504
|
};
|
|
505
|
+
/** A named action of a view (`.actions((a) => ...)`); see [Named actions](website/src/content/docs/reference/layouts.md#named-actions). */
|
|
321
506
|
export type ActionModel = {
|
|
507
|
+
/** The action's name, which `<Action name="..." />` and handlers use. */
|
|
322
508
|
name: string;
|
|
509
|
+
/** The button's label. */
|
|
323
510
|
label: string;
|
|
511
|
+
/** The button's icon: `bed`, `file-text`, `ruler`, `send` or `wallet`; another name shows a lightning bolt. */
|
|
324
512
|
icon?: string;
|
|
513
|
+
/** The question the button asks before it runs the action. */
|
|
325
514
|
confirm?: string;
|
|
515
|
+
/** Whether the action is meant for several records at once (`a.action`'s `bulk`). */
|
|
326
516
|
bulk: boolean;
|
|
517
|
+
/** What it does; without it the app runs the handler registered under `name`. */
|
|
327
518
|
run?: ActionRun;
|
|
328
519
|
};
|
|
329
520
|
/** The colour of a status dot in the sidebar. */
|
|
@@ -343,54 +534,90 @@ export type NavRecentModel = {
|
|
|
343
534
|
/** How many records to show, 1 to 20; 3 when omitted. */
|
|
344
535
|
limit?: number;
|
|
345
536
|
};
|
|
537
|
+
/** Where a resource sits in the sidebar (`.nav(...)`); see [Sidebar](website/src/content/docs/reference/sidebar.md). */
|
|
346
538
|
export type NavModel = {
|
|
347
539
|
/** Hide the resource from the sidebar, for line or link tables. */
|
|
348
540
|
hidden?: boolean;
|
|
541
|
+
/** The sidebar group it sits in; its database schema when omitted. */
|
|
349
542
|
group?: string;
|
|
543
|
+
/** Where it sorts within its group. */
|
|
350
544
|
order?: number;
|
|
545
|
+
/** A few of its records listed under its entry. */
|
|
351
546
|
recent?: NavRecentModel;
|
|
352
547
|
};
|
|
353
548
|
/** An entry in the menu under the signed-in user, at the bottom of the sidebar. */
|
|
354
549
|
export type UserMenuItemModel = {
|
|
550
|
+
/** Opens a resource's list. */
|
|
355
551
|
kind: 'resource';
|
|
552
|
+
/** The resource, which leaves the sidebar. */
|
|
356
553
|
resource: string;
|
|
554
|
+
/** The entry's label; the view's plural name when omitted. */
|
|
357
555
|
label?: string;
|
|
556
|
+
/** The entry's icon; the resource's sidebar icon when omitted. */
|
|
358
557
|
icon?: string;
|
|
359
558
|
} | {
|
|
559
|
+
/** Opens a composed page. */
|
|
360
560
|
kind: 'page';
|
|
561
|
+
/** The page, which leaves the sidebar. */
|
|
361
562
|
page: string;
|
|
563
|
+
/** The entry's label; the page's title when omitted. */
|
|
362
564
|
label?: string;
|
|
565
|
+
/** The entry's icon. */
|
|
363
566
|
icon?: string;
|
|
364
567
|
} | {
|
|
568
|
+
/** Opens an address outside the admin in a new tab. */
|
|
365
569
|
kind: 'link';
|
|
570
|
+
/** The entry's label. */
|
|
366
571
|
label: string;
|
|
572
|
+
/** The address: `https:`, `http:` or `mailto:`. */
|
|
367
573
|
href: string;
|
|
574
|
+
/** The entry's icon; `external-link` when omitted. */
|
|
368
575
|
icon?: string;
|
|
369
576
|
};
|
|
577
|
+
/** The menu under the signed-in user (`userMenu(...)`); see [User menu](website/src/content/docs/reference/user-menu.md). */
|
|
370
578
|
export type UserMenuModel = {
|
|
579
|
+
/** Its entries, in order, before the built-in account pages and "Sign out". */
|
|
371
580
|
items: UserMenuItemModel[];
|
|
372
581
|
};
|
|
373
582
|
/** A tab of a bottom bar on phones: icon above an explicit label. */
|
|
374
583
|
export type BottomBarItemModel = {
|
|
584
|
+
/** Opens a resource's list. */
|
|
375
585
|
kind: 'resource';
|
|
586
|
+
/** The resource. */
|
|
376
587
|
resource: string;
|
|
588
|
+
/** The tab's label. */
|
|
377
589
|
label: string;
|
|
590
|
+
/** The tab's icon; the resource's sidebar icon when omitted. */
|
|
378
591
|
icon?: string;
|
|
379
592
|
} | {
|
|
593
|
+
/** Opens a composed page. */
|
|
380
594
|
kind: 'page';
|
|
595
|
+
/** The page. */
|
|
381
596
|
page: string;
|
|
597
|
+
/** The tab's label. */
|
|
382
598
|
label: string;
|
|
599
|
+
/** The tab's icon; the page's own when omitted. */
|
|
383
600
|
icon?: string;
|
|
384
601
|
} | {
|
|
602
|
+
/** Opens an address outside the admin in a new tab. */
|
|
385
603
|
kind: 'link';
|
|
604
|
+
/** The tab's label. */
|
|
386
605
|
label: string;
|
|
606
|
+
/** The address: `https:`, `http:` or `mailto:`. */
|
|
387
607
|
href: string;
|
|
608
|
+
/** The tab's icon. */
|
|
388
609
|
icon?: string;
|
|
389
610
|
};
|
|
390
|
-
/**
|
|
611
|
+
/**
|
|
612
|
+
* A bottom bar for the users holding one of `roles`; `label` names it in the role view switcher. See
|
|
613
|
+
* [Bottom bar](website/src/content/docs/reference/bottom-bar.md).
|
|
614
|
+
*/
|
|
391
615
|
export type BottomBarModel = {
|
|
616
|
+
/** The bar's name, where someone with several switches between them. */
|
|
392
617
|
label: string;
|
|
618
|
+
/** The roles that get the bar; a role belongs to one bar. */
|
|
393
619
|
roles: string[];
|
|
620
|
+
/** Its tabs, in order, at most four before "More". */
|
|
394
621
|
items: BottomBarItemModel[];
|
|
395
622
|
};
|
|
396
623
|
/**
|
|
@@ -398,10 +625,17 @@ export type BottomBarModel = {
|
|
|
398
625
|
* field, which then shows instead. Without a subtitle, the first search field not in the title is the default.
|
|
399
626
|
*/
|
|
400
627
|
export type SearchResultModel = {
|
|
628
|
+
/** Fields joined by spaces into the result's bold line; the view's `title` when omitted. */
|
|
401
629
|
title?: string[];
|
|
630
|
+
/** The field on the line under it. */
|
|
402
631
|
subtitle?: string;
|
|
403
632
|
};
|
|
633
|
+
/**
|
|
634
|
+
* How the admin shows a resource: its names, list, filters, record page and actions, built by `view(...)` and sent to
|
|
635
|
+
* each user in `/meta` without what they cannot see. See [Views](website/src/content/docs/reference/ui-config.mdx).
|
|
636
|
+
*/
|
|
404
637
|
export type ViewModel = {
|
|
638
|
+
/** The resource it shows. */
|
|
405
639
|
resource: string;
|
|
406
640
|
/** Shown only to users with one of these roles; a view without roles is the default. */
|
|
407
641
|
roles?: string[];
|
|
@@ -409,128 +643,232 @@ export type ViewModel = {
|
|
|
409
643
|
title?: string;
|
|
410
644
|
/** A record in the global search: a title of one or more fields joined by spaces, over a subtitle field by default. */
|
|
411
645
|
searchResult?: SearchResultModel;
|
|
646
|
+
/** Where the resource sits in the sidebar. */
|
|
412
647
|
nav?: NavModel;
|
|
648
|
+
/** What one record and several are called, such as "Repair" and "Repairs"; the resource's name in words when omitted. */
|
|
413
649
|
names?: {
|
|
650
|
+
/** One record's name, as in "New repair". */
|
|
414
651
|
singular: string;
|
|
652
|
+
/** The records' name, as in the sidebar. */
|
|
415
653
|
plural: string;
|
|
416
654
|
};
|
|
655
|
+
/** An icon name, carried in `/meta` for apps that render their own shell. */
|
|
417
656
|
icon?: string;
|
|
657
|
+
/** A line under the list's title. */
|
|
418
658
|
help?: string;
|
|
659
|
+
/** Hints per field, by field name. */
|
|
419
660
|
fields: Record<string, FieldViewModel>;
|
|
661
|
+
/** The list page; the resource's first six fields as columns when omitted. */
|
|
420
662
|
list?: ListModel;
|
|
663
|
+
/** The filter widgets above the list, in order. */
|
|
421
664
|
filters: FilterWidgetModel[];
|
|
665
|
+
/** The record page's items, in order; one section of every field when empty. */
|
|
422
666
|
layout: LayoutItemModel[];
|
|
667
|
+
/** A chart of records over time above the list. */
|
|
423
668
|
chart?: ChartModel;
|
|
669
|
+
/** How the record page shows that a save went through. */
|
|
424
670
|
saveFeedback?: SaveFeedback;
|
|
671
|
+
/** The named actions of its records. */
|
|
425
672
|
actions: ActionModel[];
|
|
426
673
|
};
|
|
674
|
+
/** Where a part of a filter or order stands in its text, as character offsets. */
|
|
427
675
|
export type Span = {
|
|
676
|
+
/** The offset of its first character. */
|
|
428
677
|
start: number;
|
|
678
|
+
/** The offset after its last character. */
|
|
429
679
|
end: number;
|
|
430
680
|
};
|
|
681
|
+
/** A field named in a filter or order, as written: its name, or a path through relations (`customer.name`). */
|
|
431
682
|
export type FieldPath = {
|
|
683
|
+
/** A field path. */
|
|
432
684
|
kind: 'field';
|
|
685
|
+
/** The names along the path, the field's own last. */
|
|
433
686
|
path: string[];
|
|
687
|
+
/** Where it stands in the text. */
|
|
434
688
|
span: Span;
|
|
435
689
|
};
|
|
690
|
+
/** The unit of a duration: seconds, minutes, hours, days or weeks. */
|
|
436
691
|
export type DurationUnit = 's' | 'm' | 'h' | 'd' | 'w';
|
|
692
|
+
/** A length of time in a filter, such as `7d`. */
|
|
437
693
|
export type DurationLiteral = {
|
|
694
|
+
/** A duration. */
|
|
438
695
|
kind: 'duration';
|
|
696
|
+
/** How many units. */
|
|
439
697
|
amount: number;
|
|
698
|
+
/** The unit. */
|
|
440
699
|
unit: DurationUnit;
|
|
700
|
+
/** Where it stands in the filter text. */
|
|
441
701
|
span: Span;
|
|
442
702
|
};
|
|
703
|
+
/** A value written in a filter: text, a number, `true` or `false`, a duration or a timestamp. */
|
|
443
704
|
export type Literal = {
|
|
705
|
+
/** Quoted text. */
|
|
444
706
|
kind: 'string';
|
|
707
|
+
/** The text, unescaped. */
|
|
445
708
|
value: string;
|
|
709
|
+
/** Where it stands in the filter text. */
|
|
446
710
|
span: Span;
|
|
447
711
|
} | {
|
|
712
|
+
/** A number. */
|
|
448
713
|
kind: 'number';
|
|
714
|
+
/** The number. */
|
|
449
715
|
value: number;
|
|
716
|
+
/** The number as written, which keeps digits a `number` cannot hold, as for `bigint` and `decimal` fields. */
|
|
450
717
|
raw: string;
|
|
718
|
+
/** Where it stands in the filter text. */
|
|
451
719
|
span: Span;
|
|
452
720
|
} | {
|
|
721
|
+
/** `true` or `false`. */
|
|
453
722
|
kind: 'boolean';
|
|
723
|
+
/** The value. */
|
|
454
724
|
value: boolean;
|
|
725
|
+
/** Where it stands in the filter text. */
|
|
455
726
|
span: Span;
|
|
456
727
|
} | DurationLiteral | {
|
|
728
|
+
/** An RFC 3339 timestamp. */
|
|
457
729
|
kind: 'timestamp';
|
|
730
|
+
/** The timestamp as written. */
|
|
458
731
|
value: string;
|
|
732
|
+
/** Where it stands in the filter text. */
|
|
459
733
|
span: Span;
|
|
460
734
|
};
|
|
735
|
+
/** `now()` in a filter, the moment the filter runs, with an optional offset such as `now() - 7d`. */
|
|
461
736
|
export type NowValue = {
|
|
737
|
+
/** The current time. */
|
|
462
738
|
kind: 'now';
|
|
739
|
+
/** A duration added or taken off. */
|
|
463
740
|
offset?: {
|
|
741
|
+
/** Whether the duration is added or taken off. */
|
|
464
742
|
sign: '+' | '-';
|
|
743
|
+
/** The duration. */
|
|
465
744
|
duration: DurationLiteral;
|
|
466
745
|
};
|
|
746
|
+
/** Where it stands in the filter text. */
|
|
467
747
|
span: Span;
|
|
468
748
|
};
|
|
749
|
+
/** What a field is compared with in a filter: a written value or `now()`. */
|
|
469
750
|
export type FilterValue = Literal | NowValue;
|
|
751
|
+
/** A comparison in a filter. */
|
|
470
752
|
export type CompareOp = '=' | '!=' | '<' | '<=' | '>' | '>=';
|
|
753
|
+
/**
|
|
754
|
+
* A filter's syntax tree: AIP-160 with the functions the API adds (`search`, `similar`, `regex`, `isNull`, `in`); see
|
|
755
|
+
* [Filters](website/src/content/docs/reference/api.md#filters). `F` is how a field is represented: a `FieldPath` when
|
|
756
|
+
* parsed (`FilterExpr`), a `FieldModel` once checked (`CheckedFilter`).
|
|
757
|
+
*/
|
|
471
758
|
export type FilterOf<F> = {
|
|
759
|
+
/** Every one of `args` holds (`AND`). */
|
|
472
760
|
kind: 'and';
|
|
761
|
+
/** The filters joined. */
|
|
473
762
|
args: FilterOf<F>[];
|
|
763
|
+
/** Where it stands in the filter text. */
|
|
474
764
|
span: Span;
|
|
475
765
|
} | {
|
|
766
|
+
/** One of `args` holds (`OR`). */
|
|
476
767
|
kind: 'or';
|
|
768
|
+
/** The filters joined. */
|
|
477
769
|
args: FilterOf<F>[];
|
|
770
|
+
/** Where it stands in the filter text. */
|
|
478
771
|
span: Span;
|
|
479
772
|
} | {
|
|
773
|
+
/** `arg` does not hold (`NOT`, `-`). */
|
|
480
774
|
kind: 'not';
|
|
775
|
+
/** The filter negated. */
|
|
481
776
|
arg: FilterOf<F>;
|
|
777
|
+
/** Where it stands in the filter text. */
|
|
482
778
|
span: Span;
|
|
483
779
|
} | {
|
|
780
|
+
/** A comparison of a field with a value. */
|
|
484
781
|
kind: 'compare';
|
|
782
|
+
/** The comparison. */
|
|
485
783
|
op: CompareOp;
|
|
784
|
+
/** The field compared. */
|
|
486
785
|
field: F;
|
|
786
|
+
/** What it is compared with. */
|
|
487
787
|
value: FilterValue;
|
|
788
|
+
/** Where it stands in the filter text. */
|
|
488
789
|
span: Span;
|
|
489
790
|
} | {
|
|
791
|
+
/** `field:value`: a JSON field holds the value as a key or element. */
|
|
490
792
|
kind: 'has';
|
|
793
|
+
/** The field. */
|
|
491
794
|
field: F;
|
|
795
|
+
/** The value it holds. */
|
|
492
796
|
value: Literal;
|
|
797
|
+
/** Where it stands in the filter text. */
|
|
493
798
|
span: Span;
|
|
494
799
|
} | {
|
|
800
|
+
/** `field:*`: the field has a value. */
|
|
495
801
|
kind: 'present';
|
|
802
|
+
/** The field. */
|
|
496
803
|
field: F;
|
|
804
|
+
/** Where it stands in the filter text. */
|
|
497
805
|
span: Span;
|
|
498
806
|
} | {
|
|
807
|
+
/** `in(field, v, ...)`: the field equals one of the values. */
|
|
499
808
|
kind: 'in';
|
|
809
|
+
/** The field. */
|
|
500
810
|
field: F;
|
|
811
|
+
/** The values. */
|
|
501
812
|
values: Literal[];
|
|
813
|
+
/** Where it stands in the filter text. */
|
|
502
814
|
span: Span;
|
|
503
815
|
} | {
|
|
816
|
+
/** `search("text")` or bare words: every word appears in one of the resource's search fields. */
|
|
504
817
|
kind: 'search';
|
|
818
|
+
/** The text searched for. */
|
|
505
819
|
text: string;
|
|
820
|
+
/** Where it stands in the filter text. */
|
|
506
821
|
span: Span;
|
|
507
822
|
} | {
|
|
823
|
+
/** `similar(field, "text")`: the field is like the text, by pg_trgm similarity. */
|
|
508
824
|
kind: 'similar';
|
|
825
|
+
/** The field. */
|
|
509
826
|
field: F;
|
|
827
|
+
/** The text it is compared with. */
|
|
510
828
|
text: string;
|
|
829
|
+
/** Where it stands in the filter text. */
|
|
511
830
|
span: Span;
|
|
512
831
|
} | {
|
|
832
|
+
/** `regex(field, "pattern")`: the field matches the regular expression. */
|
|
513
833
|
kind: 'regex';
|
|
834
|
+
/** The field. */
|
|
514
835
|
field: F;
|
|
836
|
+
/** The regular expression. */
|
|
515
837
|
pattern: string;
|
|
838
|
+
/** Where it stands in the filter text. */
|
|
516
839
|
span: Span;
|
|
517
840
|
} | {
|
|
841
|
+
/** `isNull(field)`: the field has no value. */
|
|
518
842
|
kind: 'isNull';
|
|
843
|
+
/** The field. */
|
|
519
844
|
field: F;
|
|
845
|
+
/** Where it stands in the filter text. */
|
|
520
846
|
span: Span;
|
|
521
847
|
};
|
|
848
|
+
/** A filter as parsed, its fields as written (`parseFilter`). */
|
|
522
849
|
export type FilterExpr = FilterOf<FieldPath>;
|
|
850
|
+
/** A filter checked against a resource, its fields resolved to the resource's (`checkFilter`). */
|
|
523
851
|
export type CheckedFilter = FilterOf<FieldModel>;
|
|
852
|
+
/** Why a filter or order could not be parsed or checked, as `FilterError.code` names it. */
|
|
524
853
|
export type FilterErrorCode = 'unexpected-character' | 'unterminated-string' | 'invalid-escape' | 'invalid-number' | 'invalid-timestamp' | 'unexpected-token' | 'expected-token' | 'unknown-function' | 'invalid-arguments' | 'unsupported' | 'too-deep' | 'unknown-field' | 'not-filterable' | 'not-sortable' | 'unsupported-traversal' | 'invalid-value' | 'operator-not-allowed' | 'wildcard-not-allowed' | 'invalid-unicode' | 'too-long' | 'invalid-traversal' | 'wrong-arity' | 'wrong-argument' | 'not-boolean' | 'expected-field' | 'no-search-fields';
|
|
854
|
+
/** A problem with a filter or order, where it is and how to fix it. */
|
|
525
855
|
export type FilterError = {
|
|
856
|
+
/** What kind of problem it is. */
|
|
526
857
|
code: FilterErrorCode;
|
|
858
|
+
/** What is wrong. */
|
|
527
859
|
message: string;
|
|
860
|
+
/** How to fix it. */
|
|
528
861
|
hint: string;
|
|
862
|
+
/** Where it stands in the text. */
|
|
529
863
|
span: Span;
|
|
530
864
|
};
|
|
865
|
+
/** One field of an AIP-132 order, as parsed (`parseOrderBy`). */
|
|
531
866
|
export type OrderByItem = {
|
|
867
|
+
/** The field, as written. */
|
|
532
868
|
path: FieldPath;
|
|
869
|
+
/** Its direction. */
|
|
533
870
|
direction: 'asc' | 'desc';
|
|
871
|
+
/** Where it stands in the order text. */
|
|
534
872
|
span: Span;
|
|
535
873
|
};
|
|
536
874
|
//#endregion
|