@stoker-platform/types 0.5.68 → 0.5.70
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/package.json +5 -5
- package/src/types/app.ts +195 -5
- package/src/types/schema.ts +688 -4
package/src/types/schema.ts
CHANGED
|
@@ -5,7 +5,9 @@ import { CalendarOptions } from "@fullcalendar/core"
|
|
|
5
5
|
import { SearchOptions } from "minisearch"
|
|
6
6
|
import { UserRecord } from "firebase-admin/auth"
|
|
7
7
|
|
|
8
|
+
/** An access role in the app, i.e. "Manager". Each role has its own permissions */
|
|
8
9
|
export type StokerRole = string
|
|
10
|
+
/** The name of a collection in the app, i.e. "Clients" */
|
|
9
11
|
export type StokerCollection = string
|
|
10
12
|
|
|
11
13
|
export type FirestoreTimestamp = Timestamp | AdminTimestamp
|
|
@@ -13,64 +15,96 @@ export type InputTimestamp = Timestamp | FieldValue
|
|
|
13
15
|
|
|
14
16
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
15
17
|
|
|
18
|
+
/** A relation value stored on a record, containing the related record's collection path and any denormalized include fields */
|
|
16
19
|
export interface StokerRelation {
|
|
17
20
|
Collection_Path: string[]
|
|
18
21
|
[key: string]: any
|
|
19
22
|
}
|
|
20
23
|
|
|
24
|
+
/** A map of related record IDs to relation values, as stored on relation fields */
|
|
21
25
|
export interface StokerRelationObject {
|
|
22
26
|
[id: string]: StokerRelation
|
|
23
27
|
}
|
|
28
|
+
/** An array of related record IDs, as stored on relation fields */
|
|
24
29
|
export type StokerRelationArray = string[]
|
|
25
30
|
|
|
31
|
+
/** System fields automatically maintained on every record */
|
|
26
32
|
export interface SystemFields {
|
|
33
|
+
/** The Firestore path segments for the record's collection */
|
|
27
34
|
Collection_Path: string[]
|
|
35
|
+
/** When the record was last written. Set on the client, so it may not be reliable. Useful for logging when offline writes occurred */
|
|
28
36
|
Last_Write_At: Timestamp | FieldValue
|
|
37
|
+
/** When the record was last saved. Safely generated on the server */
|
|
29
38
|
Last_Save_At: Timestamp | FieldValue
|
|
39
|
+
/** The ID of the user who last wrote the record */
|
|
30
40
|
Last_Write_By: string
|
|
41
|
+
/** The app that made the last write */
|
|
31
42
|
Last_Write_App: string
|
|
43
|
+
/** Whether the last write was made while online or offline */
|
|
32
44
|
Last_Write_Connection_Status: "Online" | "Offline"
|
|
45
|
+
/** The schema version at the time of the last write */
|
|
33
46
|
Last_Write_Version: number
|
|
47
|
+
/** When the record was created. Set on the client, so it may not be reliable. Useful for logging when offline writes occurred */
|
|
34
48
|
Created_At: Timestamp | FieldValue
|
|
49
|
+
/** When the record was first saved. Safely generated on the server */
|
|
35
50
|
Saved_At: Timestamp | FieldValue
|
|
51
|
+
/** The ID of the user who created the record */
|
|
36
52
|
Created_By: string
|
|
37
53
|
}
|
|
38
54
|
|
|
55
|
+
/** A record in a Stoker collection, including system fields */
|
|
39
56
|
export interface StokerRecord extends SystemFields {
|
|
40
57
|
[key: string]: any
|
|
41
58
|
}
|
|
42
59
|
/* eslint-enable @typescript-eslint/no-explicit-any */
|
|
43
60
|
|
|
61
|
+
/** A user's permissions for a single collection, as stored in their permissions record */
|
|
44
62
|
export interface CollectionPermissions {
|
|
63
|
+
/** Whether the user has been granted auth (credential assignment) access for this collection */
|
|
45
64
|
auth?: boolean
|
|
65
|
+
/** The CRUD operations the user can perform on the collection */
|
|
46
66
|
operations: ("Read" | "Create" | "Update" | "Delete")[]
|
|
67
|
+
/** Whether the Record Owner restriction is active for this user */
|
|
47
68
|
recordOwner?: {
|
|
48
69
|
active: boolean
|
|
49
70
|
}
|
|
71
|
+
/** Whether the Record User restriction is active for this user */
|
|
50
72
|
recordUser?: {
|
|
51
73
|
active: boolean
|
|
52
74
|
}
|
|
75
|
+
/** Whether the Record Property restriction is active for this user */
|
|
53
76
|
recordProperty?: {
|
|
54
77
|
active: boolean
|
|
55
78
|
}
|
|
79
|
+
/** Whether entity restrictions are active for this user */
|
|
56
80
|
restrictEntities?: boolean
|
|
81
|
+
/** IDs of individual records assigned to the user */
|
|
57
82
|
individualEntities?: string[]
|
|
83
|
+
/** IDs of parent records whose child records are assigned to the user */
|
|
58
84
|
parentEntities?: string[]
|
|
85
|
+
/** IDs of parent records mapped to the property values assigned to the user */
|
|
59
86
|
parentPropertyEntities?: Record<string, string[]>
|
|
60
87
|
}
|
|
61
88
|
|
|
89
|
+
/** A user's permissions record, defining their role and per-collection access */
|
|
62
90
|
export interface StokerPermissions {
|
|
63
|
-
|
|
91
|
+
/** The ID of the auth user these permissions apply to */
|
|
64
92
|
User_ID?: string
|
|
93
|
+
/** The ID of the record in the auth collection that the user is linked to */
|
|
65
94
|
Doc_ID?: string
|
|
95
|
+
/** The auth collection the user belongs to */
|
|
66
96
|
Collection?: StokerCollection
|
|
97
|
+
/** The user's access role */
|
|
67
98
|
Role?: StokerRole
|
|
99
|
+
/** Whether the user's access is enabled */
|
|
68
100
|
Enabled?: boolean
|
|
101
|
+
/** Per-collection permissions for the user */
|
|
69
102
|
collections?: {
|
|
70
103
|
[collection: string]: CollectionPermissions
|
|
71
104
|
}
|
|
72
105
|
}
|
|
73
106
|
|
|
107
|
+
/** The names of the system fields automatically maintained on every record */
|
|
74
108
|
export type SystemField =
|
|
75
109
|
| "id"
|
|
76
110
|
| "Collection_Path"
|
|
@@ -84,149 +118,246 @@ export type SystemField =
|
|
|
84
118
|
| "Saved_At"
|
|
85
119
|
| "Created_By"
|
|
86
120
|
|
|
121
|
+
/** The names for a collection. Names must start with a capital letter and contain only letters, digits, and underscores. Provide user-friendly labels in admin.titles */
|
|
87
122
|
export interface CollectionLabels {
|
|
123
|
+
/** The name for the collection, i.e. "Clients" */
|
|
88
124
|
collection: string
|
|
125
|
+
/** The name for a record in the collection, i.e. "Client" */
|
|
89
126
|
record: string
|
|
90
127
|
}
|
|
91
128
|
|
|
92
129
|
export type OperationType = "Read" | "Create" | "Update" | "Delete"
|
|
93
130
|
export type OperationTypeLower = "read" | "create" | "update" | "delete"
|
|
94
131
|
|
|
132
|
+
/** Defines which operations and restrictions can be assigned for a collection when writing permissions */
|
|
95
133
|
export interface PermissionWriteCollection {
|
|
134
|
+
/** The collection these permission write restrictions apply to */
|
|
96
135
|
collection: StokerCollection
|
|
136
|
+
/** The operations that can be granted for the collection */
|
|
97
137
|
operations: OperationType[]
|
|
138
|
+
/** Attribute restrictions that must be applied when granting access to the collection */
|
|
98
139
|
attributeRestrictions?: AttributeRestriction["type"][]
|
|
140
|
+
/** Whether entity restrictions must be applied when granting access to the collection */
|
|
99
141
|
restrictEntities?: boolean
|
|
142
|
+
/** Whether auth access can be granted for the collection */
|
|
100
143
|
auth?: boolean
|
|
101
144
|
}
|
|
102
145
|
|
|
146
|
+
/** Restricts which permissions a user role can assign to other user roles, allowing a flexible yet secure hierarchy of access assignment */
|
|
103
147
|
export interface PermissionWriteRestriction {
|
|
148
|
+
/** The user role you are applying restrictions to */
|
|
104
149
|
userRole: StokerRole
|
|
150
|
+
/** A role that the user above can assign access to */
|
|
105
151
|
recordRole: StokerRole
|
|
152
|
+
/** Define which operations and restrictions are applied for each collection */
|
|
106
153
|
collections: PermissionWriteCollection[]
|
|
107
154
|
}
|
|
108
155
|
|
|
156
|
+
/** A role that an attribute restriction applies to */
|
|
109
157
|
export interface AttributeRestrictionRole {
|
|
158
|
+
/** The role that this restriction applies to */
|
|
110
159
|
role: StokerRole
|
|
160
|
+
/** If `true`, this restriction can be removed for individual users */
|
|
111
161
|
assignable?: boolean
|
|
162
|
+
/** For Record Property restrictions, the property values this role can access */
|
|
112
163
|
values?: string[]
|
|
113
164
|
}
|
|
165
|
+
/** A role that an entity restriction applies to */
|
|
114
166
|
export interface EntityRestrictionRole {
|
|
167
|
+
/** The role that this restriction applies to */
|
|
115
168
|
role: StokerRole
|
|
116
169
|
}
|
|
117
170
|
|
|
118
171
|
export type AccessRole = AttributeRestrictionRole | EntityRestrictionRole
|
|
119
172
|
|
|
173
|
+
/** Assign individual records to a user in their profile */
|
|
120
174
|
export interface IndividualEntityRestriction {
|
|
121
175
|
type: "Individual"
|
|
176
|
+
/** The roles that this restriction applies to */
|
|
122
177
|
roles: EntityRestrictionRole[]
|
|
178
|
+
/** Advanced. Force read operations to get all records in a single API call */
|
|
123
179
|
singleQuery?: number
|
|
124
180
|
}
|
|
181
|
+
/** Assign all records for a parent record to a user in their profile, i.e. "All Sites for Company X" */
|
|
125
182
|
export interface ParentEntityRestriction {
|
|
126
183
|
type: "Parent"
|
|
184
|
+
/** The roles that this restriction applies to */
|
|
127
185
|
roles: EntityRestrictionRole[]
|
|
186
|
+
/** The field that parent records can be selected from. Must be a relational field */
|
|
128
187
|
collectionField: string
|
|
188
|
+
/** Advanced. Force read operations to get all records in a single API call */
|
|
129
189
|
singleQuery?: number
|
|
130
190
|
}
|
|
191
|
+
/** Assign all records for a parent record to a user in their profile, by attribute, i.e. "All Sites for Company X in State NY" */
|
|
131
192
|
export interface ParentPropertyEntityRestriction {
|
|
132
193
|
type: "Parent_Property"
|
|
194
|
+
/** The roles that this restriction applies to */
|
|
133
195
|
roles: EntityRestrictionRole[]
|
|
196
|
+
/** The field that parent records can be selected from. Must be a relational field */
|
|
134
197
|
collectionField: string
|
|
198
|
+
/** The field that defines the attribute */
|
|
135
199
|
propertyField: string
|
|
136
200
|
}
|
|
137
201
|
export type AttributeRestriction = RecordUserRestriction | RecordOwnerRestriction | RecordPropertyRestriction
|
|
138
202
|
|
|
203
|
+
/** Users will only be able to access records that they have been assigned to, i.e. via an "Assigned To" field */
|
|
139
204
|
export interface RecordUserRestriction {
|
|
140
205
|
type: "Record_User"
|
|
206
|
+
/** The roles that this restriction applies to. If `assignable` is `true`, this restriction can be removed for individual users */
|
|
141
207
|
roles: AttributeRestrictionRole[]
|
|
208
|
+
/** The field used to assign access. Must be a relational field linked to an auth collection */
|
|
142
209
|
collectionField: string
|
|
210
|
+
/** If provided, the restriction only applies to the listed operations */
|
|
143
211
|
operations?: ("Read" | "Create" | "Update" | "Delete")[]
|
|
144
212
|
}
|
|
213
|
+
/** Users will only be able to access records that they created themselves */
|
|
145
214
|
export interface RecordOwnerRestriction {
|
|
146
215
|
type: "Record_Owner"
|
|
216
|
+
/** The roles that this restriction applies to. If `assignable` is `true`, this restriction can be removed for individual users */
|
|
147
217
|
roles: AttributeRestrictionRole[]
|
|
218
|
+
/** If provided, the restriction only applies to the listed operations */
|
|
148
219
|
operations?: ("Read" | "Create" | "Update" | "Delete")[]
|
|
149
220
|
}
|
|
221
|
+
/** Users will only be able to access records that have specified values for a selected field, i.e. only "Not Started" and "In Progress" records */
|
|
150
222
|
export interface RecordPropertyRestriction {
|
|
151
223
|
type: "Record_Property"
|
|
224
|
+
/** The roles this restriction applies to, and which property values they can access. If `assignable` is `true`, this restriction can be removed for individual users */
|
|
152
225
|
roles: AttributeRestrictionRole[]
|
|
226
|
+
/** The field that defines the property. Must be a String field with `values` set */
|
|
153
227
|
propertyField: string
|
|
228
|
+
/** If provided, the restriction only applies to the listed operations */
|
|
154
229
|
operations?: ("Read" | "Create" | "Update" | "Delete")[]
|
|
155
230
|
}
|
|
156
231
|
|
|
157
232
|
export type EntityRestriction = IndividualEntityRestriction | ParentEntityRestriction | ParentPropertyEntityRestriction
|
|
158
233
|
export type AccessRestriction = AttributeRestriction | EntityRestriction
|
|
159
234
|
|
|
235
|
+
/** Apply an individual entity restriction from a parent collection onto this collection */
|
|
160
236
|
export interface IndividualEntityParentFilter {
|
|
161
237
|
type: "Individual"
|
|
238
|
+
/** The relational field that links to the collection that the individual entity restriction is on */
|
|
162
239
|
collectionField: string
|
|
240
|
+
/** The roles that this parent filter applies to */
|
|
163
241
|
roles: EntityRestrictionRole[]
|
|
164
242
|
}
|
|
243
|
+
/** Apply a parent entity restriction from a parent collection onto this collection */
|
|
165
244
|
export interface ParentEntityParentFilter {
|
|
166
245
|
type: "Parent"
|
|
246
|
+
/** The relational field that links to the collection that the parent entity restriction is on */
|
|
167
247
|
collectionField: string
|
|
248
|
+
/** The relational field that matches the parent entity restriction's collection field */
|
|
168
249
|
parentCollectionField: string
|
|
250
|
+
/** The roles that this parent filter applies to */
|
|
169
251
|
roles: EntityRestrictionRole[]
|
|
170
252
|
}
|
|
253
|
+
/** Apply a parent property entity restriction from a parent collection onto this collection */
|
|
171
254
|
export interface ParentPropertyEntityParentFilter {
|
|
172
255
|
type: "Parent_Property"
|
|
256
|
+
/** The relational field that links to the collection that the parent property entity restriction is on */
|
|
173
257
|
collectionField: string
|
|
258
|
+
/** The relational field that matches the parent entity restriction's collection field */
|
|
174
259
|
parentCollectionField: string
|
|
260
|
+
/** The field that matches the parent entity restriction's property field */
|
|
175
261
|
parentPropertyField: string
|
|
262
|
+
/** The roles that this parent filter applies to */
|
|
176
263
|
roles: EntityRestrictionRole[]
|
|
177
264
|
}
|
|
178
265
|
export type EntityParentFilter =
|
|
179
|
-
|
|
|
180
|
-
| ParentEntityParentFilter
|
|
181
|
-
| ParentPropertyEntityParentFilter
|
|
266
|
+
IndividualEntityParentFilter | ParentEntityParentFilter | ParentPropertyEntityParentFilter
|
|
182
267
|
|
|
268
|
+
/** Define which roles can perform which CRUD operations for the collection */
|
|
183
269
|
export interface AccessOperations {
|
|
270
|
+
/** Set to `true` or an array of user roles to allow disabling of access in the user's profile */
|
|
184
271
|
assignable?: boolean | StokerRole[]
|
|
272
|
+
/** Roles that can read records in the collection */
|
|
185
273
|
read?: StokerRole[]
|
|
274
|
+
/** Roles that can create records in the collection */
|
|
186
275
|
create?: StokerRole[]
|
|
276
|
+
/** Roles that can update records in the collection */
|
|
187
277
|
update?: StokerRole[]
|
|
278
|
+
/** Roles that can delete records in the collection */
|
|
188
279
|
delete?: StokerRole[]
|
|
189
280
|
}
|
|
190
281
|
|
|
282
|
+
/** The roles that must be granted each file operation */
|
|
191
283
|
export interface AccessFilesAssignmentRoles {
|
|
284
|
+
/** Roles for read access to the file */
|
|
192
285
|
read?: StokerRole[]
|
|
286
|
+
/** Roles for update access to the file */
|
|
193
287
|
update?: StokerRole[]
|
|
288
|
+
/** Roles for delete access to the file */
|
|
194
289
|
delete?: StokerRole[]
|
|
195
290
|
}
|
|
291
|
+
/** File access assignment rules for a user role */
|
|
196
292
|
export interface AccessFilesAssignment {
|
|
293
|
+
/** Access assignments the user may optionally grant */
|
|
197
294
|
optional?: AccessFilesAssignmentRoles
|
|
295
|
+
/** Access assignments the user must grant */
|
|
198
296
|
required?: AccessFilesAssignmentRoles
|
|
199
297
|
}
|
|
298
|
+
/** Access rules for file uploads */
|
|
200
299
|
export interface AccessFiles {
|
|
300
|
+
/** Define the user roles that the user must assign access to for each file */
|
|
201
301
|
assignment?: {
|
|
202
302
|
[role: StokerRole]: AccessFilesAssignment
|
|
203
303
|
}
|
|
304
|
+
/** Enforce Firebase Storage metadata constraints, i.e. `{ size: " <= (5 * 1024 * 1024)" }` */
|
|
204
305
|
metadata?: {
|
|
205
306
|
[key: string]: string
|
|
206
307
|
}
|
|
308
|
+
/** Enforce custom metadata constraints */
|
|
207
309
|
customMetadata?: {
|
|
208
310
|
[key: string]: string
|
|
209
311
|
}
|
|
210
312
|
}
|
|
211
313
|
|
|
314
|
+
/** Explicitly define which specific records or groups of records can be accessed by a user. Assignment is done in the user's profile (by an Admin) */
|
|
212
315
|
export interface EntityRestrictions {
|
|
316
|
+
/** User roles for which entity restrictions can be disabled for individual users */
|
|
213
317
|
assignable?: StokerRole[]
|
|
318
|
+
/** The entity restrictions to apply */
|
|
214
319
|
restrictions?: EntityRestriction[]
|
|
320
|
+
/** Apply entity restrictions from a parent collection onto this collection, i.e. "All Jobs on Sites for Company X" */
|
|
215
321
|
parentFilters?: EntityParentFilter[]
|
|
216
322
|
}
|
|
323
|
+
/** Access control config for the collection */
|
|
217
324
|
export interface CollectionAccess {
|
|
325
|
+
/**
|
|
326
|
+
* Roles that must read data via the server. This allows more granular access control (specified in
|
|
327
|
+
* `custom.serverAccess` at the collection or field level). Warning: slows performance and removes
|
|
328
|
+
* offline and realtime capabilities
|
|
329
|
+
*/
|
|
218
330
|
serverReadOnly?: StokerRole[]
|
|
331
|
+
/**
|
|
332
|
+
* Set to `true` to force writes through the server. Required for two-way relation writes,
|
|
333
|
+
* and automatically enabled for collections with `auth` set to `true`. Removes offline write
|
|
334
|
+
* capabilities, but can greatly reduce the amount of Firestore Security Rules used by the collection
|
|
335
|
+
*/
|
|
219
336
|
serverWriteOnly?: boolean
|
|
337
|
+
/** Set to `true` to write custom Firestore Security Rules for the collection, at `firebase-rules/firestore.custom.rules` */
|
|
220
338
|
customSecurityRules?: boolean
|
|
339
|
+
/** Set to `true` to write custom Firebase Storage Rules for the collection */
|
|
221
340
|
customStorageRules?: boolean
|
|
341
|
+
/** Restrict a user's access to records with certain attributes */
|
|
222
342
|
attributeRestrictions?: AttributeRestriction[]
|
|
343
|
+
/** Explicitly define which specific records or groups of records can be accessed by a user */
|
|
223
344
|
entityRestrictions?: EntityRestrictions
|
|
345
|
+
/** Restrict which permissions a user role can assign to other user roles */
|
|
224
346
|
permissionWriteRestrictions?: PermissionWriteRestriction[]
|
|
347
|
+
/** Define which roles can perform which CRUD operations for the collection */
|
|
225
348
|
operations: AccessOperations
|
|
349
|
+
/**
|
|
350
|
+
* Only relevant when `auth` is set to `true` in the root collection config.
|
|
351
|
+
* `roles`: Roles that can be granted the ability to assign access credentials for this collection.
|
|
352
|
+
* `assignable`: Optional subset of `roles` for which auth can be enabled or disabled per user.
|
|
353
|
+
* Roles listed in `roles` but not in `assignable` are granted auth access automatically
|
|
354
|
+
*/
|
|
226
355
|
auth?: { roles: StokerRole[]; assignable?: StokerRole[] }
|
|
356
|
+
/** Define access rules for file uploads */
|
|
227
357
|
files?: AccessFiles
|
|
228
358
|
}
|
|
229
359
|
|
|
360
|
+
/** Arguments for the preOperation hook, which fires before a read or write operation */
|
|
230
361
|
export type PreOperationHookArgs = {
|
|
231
362
|
operation: "read" | "create" | "update" | "delete"
|
|
232
363
|
data?: StokerRecord
|
|
@@ -236,6 +367,7 @@ export type PreOperationHookArgs = {
|
|
|
236
367
|
batch?: WriteBatch
|
|
237
368
|
originalRecord?: StokerRecord
|
|
238
369
|
}
|
|
370
|
+
/** Arguments for the preRead hook, which fires before a read operation */
|
|
239
371
|
export type PreReadHookArgs = {
|
|
240
372
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
241
373
|
context: any
|
|
@@ -243,6 +375,7 @@ export type PreReadHookArgs = {
|
|
|
243
375
|
multiple?: boolean
|
|
244
376
|
listener?: boolean
|
|
245
377
|
}
|
|
378
|
+
/** Arguments for the postRead hook, which fires after a read operation */
|
|
246
379
|
export type PostReadHookArgs = {
|
|
247
380
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
248
381
|
context: any
|
|
@@ -250,7 +383,9 @@ export type PostReadHookArgs = {
|
|
|
250
383
|
record?: StokerRecord
|
|
251
384
|
listener?: boolean
|
|
252
385
|
}
|
|
386
|
+
/** Arguments for the preDuplicate hook, which fires before a duplicate operation in the Admin UI */
|
|
253
387
|
export type PreDuplicateHookArgs = { data: Partial<StokerRecord> }
|
|
388
|
+
/** Arguments for the preValidate hook, which fires at write validation time */
|
|
254
389
|
export type PreValidateHookArgs = {
|
|
255
390
|
operation: "create" | "update"
|
|
256
391
|
data: StokerRecord
|
|
@@ -259,6 +394,7 @@ export type PreValidateHookArgs = {
|
|
|
259
394
|
batch?: WriteBatch
|
|
260
395
|
originalRecord?: StokerRecord
|
|
261
396
|
}
|
|
397
|
+
/** Arguments for the preWrite hook, which fires before a write operation */
|
|
262
398
|
export type PreWriteHookArgs = {
|
|
263
399
|
operation: "create" | "update" | "delete"
|
|
264
400
|
data: StokerRecord
|
|
@@ -268,6 +404,7 @@ export type PreWriteHookArgs = {
|
|
|
268
404
|
batch?: WriteBatch
|
|
269
405
|
originalRecord?: StokerRecord
|
|
270
406
|
}
|
|
407
|
+
/** Arguments for the postWrite hook, which fires after a write operation */
|
|
271
408
|
export type PostWriteHookArgs = {
|
|
272
409
|
operation: "create" | "update" | "delete"
|
|
273
410
|
data: StokerRecord
|
|
@@ -277,6 +414,7 @@ export type PostWriteHookArgs = {
|
|
|
277
414
|
retry?: boolean
|
|
278
415
|
originalRecord?: StokerRecord
|
|
279
416
|
}
|
|
417
|
+
/** Arguments for the postWriteError hook, which fires when a write operation encounters an error */
|
|
280
418
|
export type PostWriteErrorHookArgs = {
|
|
281
419
|
operation: "create" | "update" | "delete"
|
|
282
420
|
data: StokerRecord
|
|
@@ -289,6 +427,7 @@ export type PostWriteErrorHookArgs = {
|
|
|
289
427
|
retries?: number
|
|
290
428
|
originalRecord?: StokerRecord
|
|
291
429
|
}
|
|
430
|
+
/** Arguments for the postOperation hook, which fires after a read or write operation */
|
|
292
431
|
export type PostOperationHookArgs = {
|
|
293
432
|
operation: "read" | "create" | "update" | "delete"
|
|
294
433
|
data?: StokerRecord
|
|
@@ -299,12 +438,14 @@ export type PostOperationHookArgs = {
|
|
|
299
438
|
originalRecord?: StokerRecord
|
|
300
439
|
}
|
|
301
440
|
|
|
441
|
+
/** The access permissions assigned to an uploaded file */
|
|
302
442
|
export type FilePermissions = {
|
|
303
443
|
read?: string
|
|
304
444
|
update?: string
|
|
305
445
|
delete?: string
|
|
306
446
|
}
|
|
307
447
|
|
|
448
|
+
/** Arguments for the preFileAdd hook, which fires before a file is uploaded */
|
|
308
449
|
export type PreFileAddHookArgs = {
|
|
309
450
|
record: StokerRecord
|
|
310
451
|
fullPath: string
|
|
@@ -312,6 +453,7 @@ export type PreFileAddHookArgs = {
|
|
|
312
453
|
permissions: FilePermissions
|
|
313
454
|
}
|
|
314
455
|
|
|
456
|
+
/** Arguments for the preFileUpdate hook, which fires before a file is updated */
|
|
315
457
|
export type PreFileUpdateHookArgs = {
|
|
316
458
|
record: StokerRecord
|
|
317
459
|
update:
|
|
@@ -324,6 +466,7 @@ export type PreFileUpdateHookArgs = {
|
|
|
324
466
|
}
|
|
325
467
|
}
|
|
326
468
|
|
|
469
|
+
/** Arguments for the postFileAdd hook, which fires after a file is uploaded */
|
|
327
470
|
export type PostFileAddHookArgs = {
|
|
328
471
|
record: StokerRecord
|
|
329
472
|
fullPath: string
|
|
@@ -331,6 +474,7 @@ export type PostFileAddHookArgs = {
|
|
|
331
474
|
permissions: FilePermissions
|
|
332
475
|
}
|
|
333
476
|
|
|
477
|
+
/** Arguments for the postFileUpdate hook, which fires after a file is updated */
|
|
334
478
|
export type PostFileUpdateHookArgs = {
|
|
335
479
|
record: StokerRecord
|
|
336
480
|
update:
|
|
@@ -343,10 +487,12 @@ export type PostFileUpdateHookArgs = {
|
|
|
343
487
|
}
|
|
344
488
|
}
|
|
345
489
|
|
|
490
|
+
/** Arguments for the postFileAddError hook, which fires when a file upload fails */
|
|
346
491
|
export type PostFileAddErrorHookArgs = PostFileAddHookArgs & {
|
|
347
492
|
error: unknown
|
|
348
493
|
}
|
|
349
494
|
|
|
495
|
+
/** Arguments for the setEmbedding hook, which calculates an embedding value for the record */
|
|
350
496
|
export type SetEmbeddingHookArgs = { record: StokerRecord }
|
|
351
497
|
|
|
352
498
|
export type HookArgs =
|
|
@@ -366,24 +512,43 @@ export type HookArgs =
|
|
|
366
512
|
| PostFileUpdateHookArgs
|
|
367
513
|
| SetEmbeddingHookArgs
|
|
368
514
|
|
|
515
|
+
/** Fires before a read or write operation. Return `false` to cancel the operation */
|
|
369
516
|
export type PreOperationHook = (args: PreOperationHookArgs) => boolean | void | Promise<boolean | void>
|
|
517
|
+
/** Fires before a read operation */
|
|
370
518
|
export type PreReadHook = (args: PreReadHookArgs) => void | Promise<void>
|
|
519
|
+
/** Fires after a read operation */
|
|
371
520
|
export type PostReadHook = (args: PostReadHookArgs) => void | Promise<void>
|
|
521
|
+
/** Fires before a duplicate operation in the Admin UI. Return `false` to cancel the operation */
|
|
372
522
|
export type PreDuplicateHook = (args: PreDuplicateHookArgs) => boolean | void | Promise<boolean | void>
|
|
523
|
+
/**
|
|
524
|
+
* Fires at write validation time. This is where you can define custom validation logic.
|
|
525
|
+
* Return an object with a boolean indicating whether validation passed, and a message to
|
|
526
|
+
* display to the user if validation has failed
|
|
527
|
+
*/
|
|
373
528
|
export type PreValidateHook = (
|
|
374
529
|
args: PreValidateHookArgs,
|
|
375
530
|
) => { valid: boolean; message?: string } | Promise<{ valid: boolean; message?: string }>
|
|
531
|
+
/** Fires before a write operation. Return `false` to cancel the operation */
|
|
376
532
|
export type PreWriteHook = (args: PreWriteHookArgs) => boolean | void | Promise<boolean | void>
|
|
533
|
+
/** Fires after a write operation */
|
|
377
534
|
export type PostWriteHook = (args: PostWriteHookArgs) => boolean | void | Promise<boolean | void>
|
|
535
|
+
/** Fires when a write operation encounters an error. May fire multiple times per write, so be sure to write idempotent code */
|
|
378
536
|
export type PostWriteErrorHook = (args: PostWriteErrorHookArgs) => boolean | void | Promise<boolean | void>
|
|
537
|
+
/** Fires after a read or write operation */
|
|
379
538
|
export type PostOperationHook = (args: PostOperationHookArgs) => boolean | void | Promise<boolean | void>
|
|
380
539
|
|
|
540
|
+
/** Fires before a file is uploaded. Return `false` to cancel the operation */
|
|
381
541
|
export type PreFileAddHook = (args: PreFileAddHookArgs) => boolean | void | Promise<boolean | void>
|
|
542
|
+
/** Fires before a file is updated. Return `false` to cancel the operation */
|
|
382
543
|
export type PreFileUpdateHook = (args: PreFileUpdateHookArgs) => boolean | void | Promise<boolean | void>
|
|
544
|
+
/** Fires after a file is uploaded */
|
|
383
545
|
export type PostFileAddHook = (args: PostFileAddHookArgs) => boolean | void | Promise<boolean | void>
|
|
546
|
+
/** Fires after a file is updated */
|
|
384
547
|
export type PostFileUpdateHook = (args: PostFileUpdateHookArgs) => boolean | void | Promise<boolean | void>
|
|
548
|
+
/** Fires when a file upload fails */
|
|
385
549
|
export type PostFileAddErrorHook = (args: PostFileAddErrorHookArgs) => void | Promise<void>
|
|
386
550
|
|
|
551
|
+
/** Calculate an embedding value for the record */
|
|
387
552
|
export type SetEmbeddingHook = (args: SetEmbeddingHookArgs) => string | Promise<string>
|
|
388
553
|
|
|
389
554
|
export type Hook =
|
|
@@ -404,45 +569,85 @@ export type Hook =
|
|
|
404
569
|
| SetEmbeddingHook
|
|
405
570
|
|
|
406
571
|
export type Hooks = {
|
|
572
|
+
/** Fires before a read or write operation. Return `false` to cancel the operation */
|
|
407
573
|
preOperation?: PreOperationHook
|
|
574
|
+
/** Fires before a read operation */
|
|
408
575
|
preRead?: PreReadHook
|
|
576
|
+
/** Fires after a read operation */
|
|
409
577
|
postRead?: PostReadHook
|
|
578
|
+
/** Fires before a duplicate operation in the Admin UI. Return `false` to cancel the operation */
|
|
410
579
|
preDuplicate?: PreDuplicateHook
|
|
580
|
+
/**
|
|
581
|
+
* Fires at write validation time. This is where you can define custom validation logic.
|
|
582
|
+
* Return an object with a boolean indicating whether validation passed, and a message to
|
|
583
|
+
* display to the user if validation has failed
|
|
584
|
+
*/
|
|
411
585
|
preValidate?: PreValidateHook
|
|
586
|
+
/** Fires before a write operation. Return `false` to cancel the operation */
|
|
412
587
|
preWrite?: PreWriteHook
|
|
588
|
+
/** Fires after a write operation */
|
|
413
589
|
postWrite?: PostWriteHook
|
|
590
|
+
/** Fires when a write operation encounters an error. May fire multiple times per write, so be sure to write idempotent code */
|
|
414
591
|
postWriteError?: PostWriteErrorHook
|
|
592
|
+
/** Fires after a read or write operation */
|
|
415
593
|
postOperation?: PostOperationHook
|
|
594
|
+
/** Fires before a file is uploaded. Return `false` to cancel the operation */
|
|
416
595
|
preFileAdd?: PreFileAddHook
|
|
596
|
+
/** Fires before a file is updated. Return `false` to cancel the operation */
|
|
417
597
|
preFileUpdate?: PreFileUpdateHook
|
|
598
|
+
/** Fires after a file is uploaded */
|
|
418
599
|
postFileAdd?: PostFileAddHook
|
|
600
|
+
/** Fires when a file upload fails */
|
|
419
601
|
postFileAddError?: PostFileAddErrorHook
|
|
602
|
+
/** Fires after a file is updated */
|
|
420
603
|
postFileUpdate?: PostFileUpdateHook
|
|
604
|
+
/** Calculate an embedding value for the record. Required for AI chat embeddings */
|
|
421
605
|
setEmbedding?: SetEmbeddingHook
|
|
422
606
|
}
|
|
423
607
|
|
|
608
|
+
/** Preload a range of time-series data. The user will be able to update the preloaded range using a date picker in the Admin UI */
|
|
424
609
|
export interface PreloadCacheRange {
|
|
610
|
+
/** Timestamp fields the user can preload by */
|
|
425
611
|
fields: string[]
|
|
612
|
+
/** Ranges of fields to preload, for example `["Start", "End"]`. Fields must also be listed in `fields` */
|
|
426
613
|
ranges?: [string, string][]
|
|
614
|
+
/** Human-readable labels for the fields listed in `fields` */
|
|
427
615
|
labels?: string[]
|
|
616
|
+
/** The default start date for the preloaded range */
|
|
428
617
|
start: "Today" | "Week" | "Month" | "Year" | Date | number
|
|
618
|
+
/** Offset the default start date by this many days */
|
|
429
619
|
startOffsetDays?: number
|
|
620
|
+
/** Offset the default start date by this many hours */
|
|
430
621
|
startOffsetHours?: number
|
|
622
|
+
/** The default end date for the preloaded range */
|
|
431
623
|
end?: Date | number
|
|
624
|
+
/** Offset the default end date by this many days */
|
|
432
625
|
endOffsetDays?: number
|
|
626
|
+
/** Offset the default end date by this many hours */
|
|
433
627
|
endOffsetHours?: number
|
|
628
|
+
/** Which selectors to show in the range picker */
|
|
434
629
|
selector?: "range" | "week" | "month" | ("range" | "week" | "month")[]
|
|
435
630
|
}
|
|
436
631
|
|
|
632
|
+
/**
|
|
633
|
+
* Preload data for the collection on app startup. Preloaded data is cached and is available
|
|
634
|
+
* for the lifetime of the session, resulting in a snappy application that works offline.
|
|
635
|
+
* Highly recommended for time series data
|
|
636
|
+
*/
|
|
437
637
|
export interface PreloadCache {
|
|
638
|
+
/** The user roles that will use the preload cache */
|
|
438
639
|
roles: StokerRole[]
|
|
640
|
+
/** Whether to wait for related collections to load before signalling to the app that the collection is loaded */
|
|
439
641
|
relationCollections?: boolean | (() => boolean | Promise<boolean>)
|
|
642
|
+
/** Preload a range of time-series data. The user can update the preloaded range using a date picker in the Admin UI */
|
|
440
643
|
range?: PreloadCacheRange
|
|
644
|
+
/** Advanced. Additional Firestore constraints to apply to the preload cache */
|
|
441
645
|
constraints?:
|
|
442
646
|
| [string, WhereFilterOp, unknown][]
|
|
443
647
|
| (() => [string, WhereFilterOp, unknown][] | Promise<[string, WhereFilterOp, unknown][]>)
|
|
444
648
|
}
|
|
445
649
|
|
|
650
|
+
/** The initial preload cache state for each collection */
|
|
446
651
|
export interface PreloadCacheInitial {
|
|
447
652
|
[collection: string]: {
|
|
448
653
|
roles: StokerRole[]
|
|
@@ -452,7 +657,13 @@ export interface PreloadCacheInitial {
|
|
|
452
657
|
}
|
|
453
658
|
}
|
|
454
659
|
|
|
660
|
+
/** Custom code config for the collection, including hooks and server access control */
|
|
455
661
|
export interface CollectionCustom extends Hooks {
|
|
662
|
+
/**
|
|
663
|
+
* Define additional access control using code on the server. Only relevant if
|
|
664
|
+
* `access.serverWriteOnly` is set to `true`. Return a boolean indicating whether or not
|
|
665
|
+
* the access check passed. This code is not sent to the client
|
|
666
|
+
*/
|
|
456
667
|
serverAccess?: {
|
|
457
668
|
read?: (permissions: StokerPermissions, user: UserRecord, record?: StokerRecord) => boolean | Promise<boolean>
|
|
458
669
|
create?: (permissions: StokerPermissions, user: UserRecord, record: StokerRecord) => boolean | Promise<boolean>
|
|
@@ -464,15 +675,21 @@ export interface CollectionCustom extends Hooks {
|
|
|
464
675
|
) => boolean | Promise<boolean>
|
|
465
676
|
delete?: (permissions: StokerPermissions, user: UserRecord, record: StokerRecord) => boolean | Promise<boolean>
|
|
466
677
|
}
|
|
678
|
+
/** Advanced. Additional Firestore constraints to apply to the preload cache */
|
|
467
679
|
preloadCacheConstraints?:
|
|
468
680
|
| [string, WhereFilterOp, unknown][]
|
|
469
681
|
| (() => [string, WhereFilterOp, unknown][] | Promise<[string, WhereFilterOp, unknown][]>)
|
|
682
|
+
/** Advanced. Firestore OR query constraints to apply to the preload cache */
|
|
470
683
|
preloadCacheOrQueries?:
|
|
471
684
|
| [string, WhereFilterOp, unknown][]
|
|
472
685
|
| (() => [string, WhereFilterOp, unknown][] | Promise<[string, WhereFilterOp, unknown][]>)
|
|
686
|
+
/** Return `true` to automatically rename duplicate records rather than throwing an error. Only relevant when `access.serverWriteOnly` is falsy */
|
|
473
687
|
autoCorrectUnique?: boolean | (() => boolean | Promise<boolean>)
|
|
688
|
+
/** Return `true` to disable adding new records while offline */
|
|
474
689
|
disableOfflineCreate?: boolean | (() => boolean | Promise<boolean>)
|
|
690
|
+
/** Return `true` to disable updating records while offline */
|
|
475
691
|
disableOfflineUpdate?: boolean | (() => boolean | Promise<boolean>)
|
|
692
|
+
/** Return `true` to disable deleting records while offline */
|
|
476
693
|
disableOfflineDelete?: boolean | (() => boolean | Promise<boolean>)
|
|
477
694
|
}
|
|
478
695
|
export interface CollectionCustomCache {
|
|
@@ -484,37 +701,64 @@ export interface CollectionCustomCache {
|
|
|
484
701
|
disableOfflineDelete?: boolean
|
|
485
702
|
}
|
|
486
703
|
|
|
704
|
+
/** Config for the list view */
|
|
487
705
|
export interface ListConfig {
|
|
706
|
+
/** Limit which user roles can view the list */
|
|
488
707
|
roles?: StokerRole[]
|
|
708
|
+
/** Customise the title for the list tab. Defaults to `"List"` */
|
|
489
709
|
title?: string
|
|
490
710
|
}
|
|
491
711
|
|
|
712
|
+
/** Show a board view with drag and drop and infinite scroll */
|
|
492
713
|
export interface CardsConfig {
|
|
714
|
+
/** Limit which user roles can view the board */
|
|
493
715
|
roles?: StokerRole[]
|
|
716
|
+
/** The field that defines the board columns. Must be a String or Number field with `values`, or a Boolean field. Not required if `admin.statusField` has already been set */
|
|
494
717
|
statusField?: string
|
|
718
|
+
/** Exclude status values from the board */
|
|
495
719
|
excludeValues?: string[] | number[]
|
|
720
|
+
/** The sub-heading shown on cards */
|
|
496
721
|
headerField: string
|
|
722
|
+
/** The number of lines for the header field text */
|
|
497
723
|
maxHeaderLines?: 1 | 2
|
|
724
|
+
/** Sections to display on cards */
|
|
498
725
|
sections: {
|
|
726
|
+
/** The title for the section */
|
|
499
727
|
title?: string
|
|
728
|
+
/** The fields to display in the section */
|
|
500
729
|
fields: string[]
|
|
730
|
+
/** Show multiple columns of fields, rather than listing fields down the card vertically */
|
|
501
731
|
blocks?: boolean
|
|
732
|
+
/** Show a large field value */
|
|
502
733
|
large?: boolean
|
|
734
|
+
/** The number of lines for field text */
|
|
503
735
|
maxSectionLines?: 1 | 2 | 3 | 4
|
|
736
|
+
/** Only relevant when `blocks` is set to `true`. Hide the outermost block at this screen size. Helps with responsiveness */
|
|
504
737
|
collapse?: "sm" | "md" | "lg" | "xl" | "2xl" | ((record?: StokerRecord) => "sm" | "md" | "lg" | "xl" | "2xl")
|
|
505
738
|
}[]
|
|
739
|
+
/** The footer field shown on cards */
|
|
506
740
|
footerField?: string
|
|
741
|
+
/** The number of lines for the footer field text */
|
|
507
742
|
maxFooterLines?: 1 | 2
|
|
743
|
+
/** Customise the title for the board tab. Defaults to `"Board"` */
|
|
508
744
|
title?: string
|
|
745
|
+
/** Tailwind classes to apply to the card component */
|
|
509
746
|
cardClass?: string
|
|
510
747
|
}
|
|
511
748
|
|
|
749
|
+
/** Show a list of image cards with infinite scroll */
|
|
512
750
|
export interface ImagesConfig {
|
|
751
|
+
/** Limit which user roles can view the images page */
|
|
513
752
|
roles?: StokerRole[]
|
|
753
|
+
/** The field that contains the image URL for the record. Must be a String field */
|
|
514
754
|
imageField: string
|
|
755
|
+
/** The image size */
|
|
515
756
|
size: "sm" | "md" | "lg" | "xl"
|
|
757
|
+
/** The number of lines for the header field text */
|
|
516
758
|
maxHeaderLines?: 1 | 2
|
|
759
|
+
/** Customise the title for the images tab. Defaults to `"Pics"` */
|
|
517
760
|
title?: string
|
|
761
|
+
/** An optional custom component shown above each image */
|
|
518
762
|
customComponent?: {
|
|
519
763
|
component: React.FC<{
|
|
520
764
|
record: StokerRecord | undefined
|
|
@@ -535,55 +779,88 @@ export interface ImagesConfig {
|
|
|
535
779
|
}
|
|
536
780
|
}
|
|
537
781
|
|
|
782
|
+
/** Show a map view */
|
|
538
783
|
export interface MapConfig {
|
|
784
|
+
/** Limit which user roles can view the map page */
|
|
539
785
|
roles?: StokerRole[]
|
|
786
|
+
/** The field containing coordinates. Must be an Array field */
|
|
540
787
|
coordinatesField?: string
|
|
788
|
+
/** Alternatively, provide a String field containing an address */
|
|
541
789
|
addressField?: string
|
|
790
|
+
/** The starting coordinates for the map */
|
|
542
791
|
center: {
|
|
543
792
|
lat: number
|
|
544
793
|
lng: number
|
|
545
794
|
}
|
|
795
|
+
/** The starting zoom value for the map */
|
|
546
796
|
zoom: number
|
|
797
|
+
/** Show a column of records without coordinates or an address. Records can be dragged onto the map (only when `coordinatesField` is provided) */
|
|
547
798
|
noLocation?: {
|
|
548
799
|
title: string
|
|
549
800
|
}
|
|
801
|
+
/** Customise the title for the map tab. Defaults to `"Map"` */
|
|
550
802
|
title?: string
|
|
551
803
|
}
|
|
552
804
|
|
|
805
|
+
/** Show a calendar view. Requires a Fullcalendar license */
|
|
553
806
|
export interface CalendarConfig {
|
|
807
|
+
/** Limit which user roles can view the calendar page */
|
|
554
808
|
roles?: StokerRole[]
|
|
809
|
+
/** Timestamp field specifying the start date of the event */
|
|
555
810
|
startField: string
|
|
811
|
+
/** Timestamp field specifying the end date of the event. If omitted, the start date is used */
|
|
556
812
|
endField?: string
|
|
813
|
+
/** Additional Timestamp fields to include as all-day events */
|
|
557
814
|
additionalFields?: string[]
|
|
815
|
+
/** Boolean field indicating whether records are all-day */
|
|
558
816
|
allDayField?: string
|
|
817
|
+
/** Fullcalendar options for desktop screen sizes */
|
|
559
818
|
fullCalendarLarge?: CalendarOptions
|
|
819
|
+
/** Fullcalendar options for mobile screen sizes */
|
|
560
820
|
fullCalendarSmall?: CalendarOptions
|
|
821
|
+
/** Relational field specifying a parent resource. Used for Fullcalendar features that require "resources" */
|
|
561
822
|
resourceField?: string
|
|
823
|
+
/** Field in the `resourceField` collection that acts as the resource title */
|
|
562
824
|
resourceTitleField?: string
|
|
825
|
+
/** Show a column of unscheduled records. Only relevant if `preloadCache.range` is present for the user's role. Records can be dragged onto the calendar */
|
|
563
826
|
unscheduled?: {
|
|
564
827
|
title: string
|
|
565
828
|
roles?: StokerRole[]
|
|
566
829
|
}
|
|
830
|
+
/** Customise the title for the calendar tab. Defaults to `"Calendar"` */
|
|
567
831
|
title?: string
|
|
832
|
+
/** How far into the past to load records for */
|
|
568
833
|
dataStart?: { days: number } | { weeks: number } | { months: number } | { years: number }
|
|
834
|
+
/** How far into the future to load records for */
|
|
569
835
|
dataEnd?: { days: number } | { weeks: number } | { months: number } | { years: number }
|
|
836
|
+
/** Threshold at which more past records will be loaded */
|
|
570
837
|
dataStartOffset?: { days: number } | { weeks: number } | { months: number } | { years: number }
|
|
838
|
+
/** Threshold at which more future records will be loaded */
|
|
571
839
|
dataEndOffset?: { days: number } | { weeks: number } | { months: number } | { years: number }
|
|
840
|
+
/** The color for the provided record's event on the calendar */
|
|
572
841
|
color?: string | ((record: StokerRecord) => string)
|
|
842
|
+
/** A custom title for the provided record's event on the calendar */
|
|
573
843
|
eventTitle?: (record: StokerRecord) => string
|
|
844
|
+
/** Determines whether a record should be displayed on the calendar. This filter only runs in the client, so it should not be used for access control purposes */
|
|
574
845
|
filterRecords?: (record: StokerRecord) => boolean
|
|
846
|
+
/** Additional collections to show on the calendar. Only works when the preload cache is enabled for the user's role for the given collection */
|
|
575
847
|
additionalCollections?: StokerCollection[]
|
|
576
848
|
}
|
|
577
849
|
|
|
850
|
+
/** Filter the list by the collection's status field */
|
|
578
851
|
export type StatusFilter = {
|
|
579
852
|
type: "status"
|
|
580
853
|
value?: string | number
|
|
854
|
+
/** The roles that can see this filter */
|
|
581
855
|
roles?: StokerRole[]
|
|
582
856
|
}
|
|
583
857
|
|
|
858
|
+
/** Filter the list by a Timestamp field */
|
|
584
859
|
export type RangeFilter = {
|
|
585
860
|
type: "range"
|
|
861
|
+
/** The Timestamp field to filter by */
|
|
586
862
|
field: string
|
|
863
|
+
/** Which selectors to show in the range picker */
|
|
587
864
|
selector?:
|
|
588
865
|
| "range"
|
|
589
866
|
| "week"
|
|
@@ -591,29 +868,40 @@ export type RangeFilter = {
|
|
|
591
868
|
| ("range" | "week" | "month")[]
|
|
592
869
|
| (() => "range" | "week" | "month" | ("range" | "week" | "month")[])
|
|
593
870
|
value?: string
|
|
871
|
+
/** Offset the default start date by this many days */
|
|
594
872
|
startOffsetDays?: number
|
|
873
|
+
/** Offset the default start date by this many hours */
|
|
595
874
|
startOffsetHours?: number
|
|
875
|
+
/** Offset the default end date by this many days */
|
|
596
876
|
endOffsetDays?: number
|
|
877
|
+
/** Offset the default end date by this many hours */
|
|
597
878
|
endOffsetHours?: number
|
|
598
879
|
}
|
|
599
880
|
|
|
881
|
+
/** Filter the list by a field with `values` set */
|
|
600
882
|
export type SelectFilter = {
|
|
601
883
|
type: "select"
|
|
884
|
+
/** The field to filter by. Must have `values` set */
|
|
602
885
|
field: string
|
|
886
|
+
/** The title for the filter */
|
|
603
887
|
title?: string | (() => string)
|
|
888
|
+
/** The roles that can see this filter */
|
|
604
889
|
roles?: StokerRole[]
|
|
890
|
+
/** Modify the titles shown for filter values */
|
|
605
891
|
titles?: (
|
|
606
892
|
value: string,
|
|
607
893
|
relationCollection?: CollectionSchema,
|
|
608
894
|
relationParent?: StokerRecord,
|
|
609
895
|
isAssigning?: boolean,
|
|
610
896
|
) => string
|
|
897
|
+
/** Filter which values are shown in the filter */
|
|
611
898
|
filterValues?: (
|
|
612
899
|
value: boolean | string | number | undefined,
|
|
613
900
|
relationCollection?: CollectionSchema,
|
|
614
901
|
relationParent?: StokerRecord,
|
|
615
902
|
isAssigning?: boolean,
|
|
616
903
|
) => boolean
|
|
904
|
+
/** The default value for the filter */
|
|
617
905
|
defaultValue?:
|
|
618
906
|
| string
|
|
619
907
|
| number
|
|
@@ -622,88 +910,147 @@ export type SelectFilter = {
|
|
|
622
910
|
parentRecord?: StokerRecord,
|
|
623
911
|
isAssigning?: boolean,
|
|
624
912
|
) => string | number | undefined)
|
|
913
|
+
/** Show or hide the filter */
|
|
625
914
|
condition?: (parentCollection?: CollectionSchema, parentRecord?: StokerRecord, isAssigning?: boolean) => boolean
|
|
626
915
|
value?: string | number
|
|
916
|
+
/** The style of the filter input */
|
|
627
917
|
style?: "select" | "radio" | "buttons"
|
|
628
918
|
}
|
|
629
919
|
|
|
920
|
+
/** Filter the list by a related field */
|
|
630
921
|
export type RelationFilter = {
|
|
631
922
|
type: "relation"
|
|
923
|
+
/** The relational field to filter by */
|
|
632
924
|
field: string
|
|
925
|
+
/** The title for the filter */
|
|
633
926
|
title?: string | (() => string)
|
|
927
|
+
/** The roles that can see this filter */
|
|
634
928
|
roles?: StokerRole[]
|
|
929
|
+
/** Filter the list of related values using a Firestore where() query */
|
|
635
930
|
constraints?: [string, "==" | "in", unknown][]
|
|
636
931
|
value?: string
|
|
637
932
|
}
|
|
638
933
|
|
|
934
|
+
/** A filter shown in the right-hand-side filter drawer on the list page */
|
|
639
935
|
export type Filter = StatusFilter | RangeFilter | SelectFilter | RelationFilter
|
|
640
936
|
|
|
937
|
+
/** Show a metric (numerical counter) at the top of the list page */
|
|
641
938
|
export interface Metric {
|
|
939
|
+
/** The metric type. For "custom" metrics, use the `formula` method to calculate the value to display */
|
|
642
940
|
type: "sum" | "average" | "count" | "custom"
|
|
941
|
+
/** The field to aggregate. Not required for `count` or `custom` */
|
|
643
942
|
field?: string
|
|
943
|
+
/** Limit which user roles can view the metric */
|
|
644
944
|
roles?: StokerRole[]
|
|
945
|
+
/** The title shown above the metric */
|
|
645
946
|
title?: string
|
|
947
|
+
/** Maximum decimal places to display */
|
|
646
948
|
decimal?: number
|
|
949
|
+
/** Prefix text, for example a currency symbol */
|
|
647
950
|
prefix?: string
|
|
951
|
+
/** Suffix text, for example units */
|
|
648
952
|
suffix?: string
|
|
953
|
+
/** Tailwind text size for the metric value */
|
|
649
954
|
textSize?: "text-xl" | "text-2xl" | "text-3xl"
|
|
955
|
+
/** Compact the metric vertically */
|
|
650
956
|
compact?: boolean
|
|
957
|
+
/** Custom metric calculation */
|
|
651
958
|
formula?: (records: StokerRecord[]) => number | string
|
|
652
959
|
}
|
|
960
|
+
/** Show a chart at the top of the list page */
|
|
653
961
|
export interface Chart {
|
|
962
|
+
/** The chart type */
|
|
654
963
|
type: "area"
|
|
964
|
+
/** The date field used to group points */
|
|
655
965
|
dateField: string
|
|
966
|
+
/** First metric field */
|
|
656
967
|
metricField1?: string
|
|
968
|
+
/** Optional second metric field */
|
|
657
969
|
metricField2?: string
|
|
970
|
+
/** Default chart date range */
|
|
658
971
|
defaultRange: "90d" | "30d" | "7d"
|
|
972
|
+
/** Limit which user roles can view the chart */
|
|
659
973
|
roles?: StokerRole[]
|
|
974
|
+
/** Title shown above the chart */
|
|
660
975
|
title?: string
|
|
976
|
+
/** Currency symbol to display */
|
|
661
977
|
currency?: string | (() => string)
|
|
662
978
|
}
|
|
979
|
+
/** A custom meta title and description for the collection's pages */
|
|
663
980
|
export interface CollectionMeta {
|
|
664
981
|
title?: string
|
|
665
982
|
description?: string
|
|
666
983
|
}
|
|
984
|
+
/** Highlight rows in the list view */
|
|
667
985
|
export interface RowHighlight {
|
|
986
|
+
/** Return `true` to highlight the row for the given record */
|
|
668
987
|
condition: (record: StokerRecord) => boolean
|
|
988
|
+
/** The Tailwind classes to apply to the highlighted row */
|
|
669
989
|
className: string
|
|
990
|
+
/** The user roles to highlight rows for */
|
|
670
991
|
roles?: StokerRole[]
|
|
671
992
|
}
|
|
993
|
+
/** Converting a record creates a new record in the target collection and keeps the original */
|
|
672
994
|
export interface Convert {
|
|
995
|
+
/** The collection to convert records to */
|
|
673
996
|
collection: string
|
|
997
|
+
/** A function that modifies the record before conversion */
|
|
674
998
|
convert: (record: StokerRecord) => Partial<StokerRecord> | Promise<Partial<StokerRecord>>
|
|
999
|
+
/** The roles that can perform this conversion */
|
|
675
1000
|
roles?: StokerRole[]
|
|
676
1001
|
}
|
|
1002
|
+
/** A custom form field component */
|
|
677
1003
|
export interface CustomField {
|
|
1004
|
+
/** The position of the custom component in the form */
|
|
678
1005
|
position?: number | ((record?: StokerRecord) => number)
|
|
1006
|
+
/** The React component */
|
|
679
1007
|
component?: React.FC
|
|
1008
|
+
/** Props to pass to the React component */
|
|
680
1009
|
props?: Record<string, unknown>
|
|
1010
|
+
/** Show or hide the custom component */
|
|
681
1011
|
condition?: (operation: "create" | "update" | "update-many", record?: StokerRecord) => boolean
|
|
682
1012
|
}
|
|
1013
|
+
/** Show a relation list directly on the edit record form page */
|
|
683
1014
|
export interface FormList {
|
|
1015
|
+
/** The collection to show the relation list for */
|
|
684
1016
|
collection: StokerCollection
|
|
1017
|
+
/** Which columns to show in the list */
|
|
685
1018
|
fields: string[]
|
|
1019
|
+
/** The field to sort records by */
|
|
686
1020
|
sortField?: string
|
|
1021
|
+
/** The direction to sort records by */
|
|
687
1022
|
sortDirection?: "asc" | "desc"
|
|
1023
|
+
/** The title for the relation list */
|
|
688
1024
|
label?: string
|
|
689
1025
|
}
|
|
690
1026
|
|
|
1027
|
+
/** A custom button shown at the bottom of the edit record form */
|
|
691
1028
|
export interface FormButton {
|
|
1029
|
+
/** The title text for the custom button */
|
|
692
1030
|
title: string
|
|
1031
|
+
/** The icon shown on the button */
|
|
693
1032
|
icon?: React.FC<{ className?: string }>
|
|
1033
|
+
/** The style of the button */
|
|
694
1034
|
variant?: "default" | "destructive" | "outline" | "secondary" | "ghost" | "link"
|
|
1035
|
+
/** The function that fires when the button is clicked */
|
|
695
1036
|
action: (
|
|
696
1037
|
operation: "create" | "update" | "update-many",
|
|
697
1038
|
formValues: StokerRecord,
|
|
698
1039
|
originalRecord?: StokerRecord,
|
|
699
1040
|
) => void | Promise<void>
|
|
1041
|
+
/** Show or hide the button */
|
|
700
1042
|
condition?: boolean | ((operation: "create" | "update" | "update-many", record?: StokerRecord) => boolean)
|
|
1043
|
+
/** A loading callback that will be called when the button is pressed */
|
|
701
1044
|
setIsLoading?: (isLoading: boolean) => void
|
|
702
1045
|
}
|
|
703
1046
|
|
|
1047
|
+
/** A custom page for the collection, shown in the record page sidebar */
|
|
704
1048
|
export interface CustomRecordPage {
|
|
1049
|
+
/** The title for the custom page in the sidebar */
|
|
705
1050
|
title: string
|
|
1051
|
+
/** The URL segment that the page will load on */
|
|
706
1052
|
url: string
|
|
1053
|
+
/** The custom component */
|
|
707
1054
|
component: React.FC<{
|
|
708
1055
|
record: StokerRecord | undefined
|
|
709
1056
|
collection: CollectionSchema
|
|
@@ -714,8 +1061,11 @@ export interface CustomRecordPage {
|
|
|
714
1061
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
715
1062
|
utils: any
|
|
716
1063
|
}>
|
|
1064
|
+
/** Props to pass to the custom component */
|
|
717
1065
|
props?: Record<string, unknown>
|
|
1066
|
+
/** Show or hide the custom page */
|
|
718
1067
|
condition?: (record: StokerRecord | undefined) => boolean
|
|
1068
|
+
/** The icon shown in the sidebar */
|
|
719
1069
|
icon?: React.FC<{ className?: string }>
|
|
720
1070
|
}
|
|
721
1071
|
|
|
@@ -731,21 +1081,33 @@ export interface Assignable {
|
|
|
731
1081
|
}[]
|
|
732
1082
|
}
|
|
733
1083
|
|
|
1084
|
+
/** A custom action shown in a dropdown menu on the list page */
|
|
734
1085
|
export interface CustomListAction {
|
|
1086
|
+
/** The title for the action */
|
|
735
1087
|
title: string
|
|
1088
|
+
/** The icon shown for the action */
|
|
736
1089
|
icon?: React.FC<{ className?: string }>
|
|
1090
|
+
/** The function that fires when the action is clicked */
|
|
737
1091
|
action: () => void | Promise<void>
|
|
1092
|
+
/** Show or hide the action */
|
|
738
1093
|
condition?: () => boolean
|
|
739
1094
|
}
|
|
740
1095
|
|
|
1096
|
+
/** Options for file uploads */
|
|
741
1097
|
export interface FileOptions {
|
|
1098
|
+
/** The maximum width for uploaded image files. Images above this size will be downscaled */
|
|
742
1099
|
maxImageWidth?: number
|
|
1100
|
+
/** Set to `true` to show thumbnails for images in the files list */
|
|
743
1101
|
thumbnails?: boolean
|
|
744
1102
|
}
|
|
745
1103
|
|
|
1104
|
+
/** Admin UI config for the collection */
|
|
746
1105
|
export interface CollectionAdmin {
|
|
1106
|
+
/** Return `true` to hide the collection in the Admin UI */
|
|
747
1107
|
hidden?: boolean | (() => boolean | Promise<boolean>)
|
|
1108
|
+
/** The collection's position in the navbar */
|
|
748
1109
|
navbarPosition?: number | (() => number)
|
|
1110
|
+
/** Human-readable labels for the collection. Only necessary if the root `labels` are not human-readable */
|
|
749
1111
|
titles?:
|
|
750
1112
|
| {
|
|
751
1113
|
collection: string
|
|
@@ -756,15 +1118,31 @@ export interface CollectionAdmin {
|
|
|
756
1118
|
parentCollection?: CollectionSchema,
|
|
757
1119
|
parentRecord?: StokerRecord,
|
|
758
1120
|
) => { collection: string; record: string } | Promise<{ collection: string; record: string }>)
|
|
1121
|
+
/** An icon component for the collection. We recommend using Lucide icons, which are bundled with Stoker */
|
|
759
1122
|
icon?: React.FC | (() => React.FC | Promise<React.FC>)
|
|
1123
|
+
/** Return `true` to show the "Duplicate" button on the form page */
|
|
760
1124
|
duplicate?: boolean | (() => boolean | Promise<boolean>)
|
|
1125
|
+
/** Define which collections records can be converted to. A "Convert" button will be shown on the form page */
|
|
761
1126
|
convert?: Convert[] | (() => Convert[] | Promise<Convert[]>)
|
|
1127
|
+
/**
|
|
1128
|
+
* Set to `true` to have the form page live-update when the record is updated remotely.
|
|
1129
|
+
* Can also be configured at the field-level. Note: on a live form remote updates will
|
|
1130
|
+
* overwrite local changes, introducing a risk of data loss
|
|
1131
|
+
*/
|
|
762
1132
|
live?: boolean | (() => boolean | Promise<boolean>)
|
|
1133
|
+
/**
|
|
1134
|
+
* Define a field that will be used to sort records into "Active" and "Archived" lists,
|
|
1135
|
+
* i.e. `{ field: "Status", active: ["Not Started", "In Progress"], archived: ["Completed"] }`
|
|
1136
|
+
*/
|
|
763
1137
|
statusField?: {
|
|
1138
|
+
/** The field that defines the active / archived status */
|
|
764
1139
|
field: string
|
|
1140
|
+
/** Values considered active */
|
|
765
1141
|
active?: unknown[]
|
|
1142
|
+
/** Values considered archived */
|
|
766
1143
|
archived?: unknown[]
|
|
767
1144
|
}
|
|
1145
|
+
/** The default view for the collection */
|
|
768
1146
|
defaultView?:
|
|
769
1147
|
| "list"
|
|
770
1148
|
| "cards"
|
|
@@ -775,7 +1153,9 @@ export interface CollectionAdmin {
|
|
|
775
1153
|
parentCollection: CollectionSchema,
|
|
776
1154
|
parentRecord?: StokerRecord,
|
|
777
1155
|
) => "list" | "cards" | "images" | "map" | "calendar")
|
|
1156
|
+
/** The default route for the record page. Can be "edit", "files", a relation list collection name or a custom record page url */
|
|
778
1157
|
defaultRoute?: string | (() => string)
|
|
1158
|
+
/** The default field to sort the list by */
|
|
779
1159
|
defaultSort?:
|
|
780
1160
|
| {
|
|
781
1161
|
field: string
|
|
@@ -790,6 +1170,7 @@ export interface CollectionAdmin {
|
|
|
790
1170
|
field: string
|
|
791
1171
|
direction?: "asc" | "desc"
|
|
792
1172
|
}>)
|
|
1173
|
+
/** The secondary field to sort the list by. Only works for collections with `preloadCache` or `access.serverReadOnly` enabled */
|
|
793
1174
|
secondarySort?:
|
|
794
1175
|
| {
|
|
795
1176
|
field: string
|
|
@@ -804,52 +1185,93 @@ export interface CollectionAdmin {
|
|
|
804
1185
|
field: string
|
|
805
1186
|
direction?: "asc" | "desc"
|
|
806
1187
|
}>)
|
|
1188
|
+
/** The number of items to show per page */
|
|
807
1189
|
itemsPerPage?: number | (() => number | Promise<number>)
|
|
1190
|
+
/**
|
|
1191
|
+
* Full text search options. For roles with the preload cache or `access.serverReadOnly`
|
|
1192
|
+
* enabled, provide MiniSearch settings. For other roles, provide `{ hitsPerPage?: number }`
|
|
1193
|
+
* to specify the maximum number of results to retrieve from Algolia
|
|
1194
|
+
*/
|
|
808
1195
|
searchOptions?: SearchOptions & { hitsPerPage?: number }
|
|
1196
|
+
/** Config for the list view */
|
|
809
1197
|
list?: ListConfig | (() => ListConfig | Promise<ListConfig>)
|
|
1198
|
+
/** Show a board view with drag and drop and infinite scroll */
|
|
810
1199
|
cards?: CardsConfig | (() => CardsConfig | Promise<CardsConfig>)
|
|
1200
|
+
/** Show a list of image cards with infinite scroll */
|
|
811
1201
|
images?: ImagesConfig | (() => ImagesConfig | Promise<ImagesConfig>)
|
|
1202
|
+
/** Show a map view */
|
|
812
1203
|
map?: MapConfig | (() => MapConfig | Promise<MapConfig>)
|
|
1204
|
+
/** Show a calendar view. Requires a Fullcalendar license */
|
|
813
1205
|
calendar?: CalendarConfig | (() => CalendarConfig | Promise<CalendarConfig>)
|
|
1206
|
+
/** Filters that will appear in the right-hand-side filter drawer on the list page */
|
|
814
1207
|
filters?: Filter[]
|
|
1208
|
+
/** The date range selector options to be shown to the user. Only relevant when `preloadCache.range` is present */
|
|
815
1209
|
rangeSelectorValues?:
|
|
816
1210
|
| "range"
|
|
817
1211
|
| "week"
|
|
818
1212
|
| "month"
|
|
819
1213
|
| ("range" | "week" | "month")[]
|
|
820
1214
|
| (() => "range" | "week" | "month" | ("range" | "week" | "month")[])
|
|
1215
|
+
/** The default date range selector to be shown to the user. Only relevant when `preloadCache.range` is present or a range filter has been applied */
|
|
821
1216
|
defaultRangeSelector?: "range" | "week" | "month" | (() => "range" | "week" | "month")
|
|
1217
|
+
/** Restrict CSV export to the defined roles */
|
|
822
1218
|
restrictExport?: StokerRole[] | (() => StokerRole[] | Promise<StokerRole[]>)
|
|
1219
|
+
/** Display a counter in the title bar showing the number of items in the list */
|
|
823
1220
|
titleCount?: boolean | (() => boolean | Promise<boolean>)
|
|
1221
|
+
/** Show metrics (numerical counters) and a chart at the top of the list page. We recommend 1-2 metrics and a chart */
|
|
824
1222
|
metrics?: (Metric | Chart)[] | (() => (Metric | Chart)[] | Promise<(Metric | Chart)[]>)
|
|
1223
|
+
/** Define a custom meta title and description for the collection's pages */
|
|
825
1224
|
meta?: CollectionMeta | (() => CollectionMeta | Promise<CollectionMeta>)
|
|
1225
|
+
/** Highlight rows in the list view */
|
|
826
1226
|
rowHighlight?: RowHighlight[] | (() => RowHighlight[])
|
|
1227
|
+
/** An array of relational field names that will be used to show breadcrumbs at the top of the record page */
|
|
827
1228
|
breadcrumbs?: string[] | (() => string[] | Promise<string[]>)
|
|
1229
|
+
/** Create custom form field components */
|
|
828
1230
|
customFields?: CustomField[] | (() => CustomField[] | Promise<CustomField[]>)
|
|
1231
|
+
/** Create custom pages for the collection */
|
|
829
1232
|
customRecordPages?: CustomRecordPage[] | (() => CustomRecordPage[] | Promise<CustomRecordPage[]>)
|
|
1233
|
+
/** Show custom buttons at the bottom of the edit record form */
|
|
830
1234
|
formButtons?: FormButton[] | (() => FormButton[] | Promise<FormButton[]>)
|
|
1235
|
+
/** Show a file upload button on the add record form */
|
|
831
1236
|
formUpload?: boolean | (() => boolean | Promise<boolean>)
|
|
1237
|
+
/** Show an image carousel at the top of the edit record form. All image files uploaded to the record will be displayed */
|
|
832
1238
|
formImages?: boolean | (() => boolean | Promise<boolean>)
|
|
1239
|
+
/** Show relation lists directly on the edit record form page */
|
|
833
1240
|
formLists?: FormList[] | (() => FormList[] | Promise<FormList[]>)
|
|
1241
|
+
/** Hide the add record button */
|
|
834
1242
|
hideCreate?: boolean | ((relationList?: StokerCollection) => boolean | Promise<boolean>)
|
|
1243
|
+
/**
|
|
1244
|
+
* Disable the edit record form. Warning: this only disables editing client side.
|
|
1245
|
+
* Use `restrictUpdate` or `access.operations` to securely block record updates
|
|
1246
|
+
*/
|
|
835
1247
|
disableUpdate?: boolean | ((operation: "create" | "update", record: StokerRecord) => boolean | Promise<boolean>)
|
|
1248
|
+
/**
|
|
1249
|
+
* A hook that fires when the record form is opened. When the "create" form is opened from
|
|
1250
|
+
* within another record's relation list, the parent collection and parent record are provided
|
|
1251
|
+
*/
|
|
836
1252
|
onFormOpen?: (
|
|
837
1253
|
operation: "create" | "update",
|
|
838
1254
|
record: StokerRecord,
|
|
839
1255
|
parentCollection?: StokerCollection,
|
|
840
1256
|
parentRecord?: StokerRecord,
|
|
841
1257
|
) => void | Promise<void>
|
|
1258
|
+
/** A hook that fires whenever the form is updated. Optionally return an object with field updates */
|
|
842
1259
|
onChange?: (
|
|
843
1260
|
operation: "create" | "update",
|
|
844
1261
|
record: StokerRecord,
|
|
845
1262
|
originalRecord: StokerRecord,
|
|
846
1263
|
) => Partial<StokerRecord> | void | Promise<Partial<StokerRecord> | void>
|
|
1264
|
+
/** Override the default behaviour of opening the add record form */
|
|
847
1265
|
addRecordButtonOverride?: (record?: StokerRecord) => void | Promise<void>
|
|
1266
|
+
/** Disable the date range selector for the user */
|
|
848
1267
|
disableRangeSelector?: boolean | (() => boolean)
|
|
1268
|
+
/** Load data for use in your computed fields, once per query */
|
|
849
1269
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
850
1270
|
retriever?: () => any | Promise<any>
|
|
851
1271
|
assignable?: Assignable[] | (() => Assignable[] | Promise<Assignable[]>)
|
|
1272
|
+
/** Custom actions that will be shown in a dropdown menu on the list page */
|
|
852
1273
|
customListActions?: CustomListAction[] | (() => CustomListAction[] | Promise<CustomListAction[]>)
|
|
1274
|
+
/** Options for file uploads */
|
|
853
1275
|
fileOptions?: FileOptions | (() => FileOptions | Promise<FileOptions>)
|
|
854
1276
|
}
|
|
855
1277
|
export interface CollectionAdminCache {
|
|
@@ -907,8 +1329,15 @@ export interface CollectionAdminCache {
|
|
|
907
1329
|
fileOptions?: FileOptions
|
|
908
1330
|
}
|
|
909
1331
|
|
|
1332
|
+
/** Custom code config for the field, including hooks and server access control */
|
|
910
1333
|
export interface FieldCustom extends Hooks {
|
|
1334
|
+
/** Calculate an initial value for this field when creating the record */
|
|
911
1335
|
initialValue?: unknown | ((record?: StokerRecord) => unknown | Promise<unknown>)
|
|
1336
|
+
/**
|
|
1337
|
+
* Define additional access control using code on the server. Only relevant if
|
|
1338
|
+
* `access.serverWriteOnly` is set to `true`. Return a boolean indicating whether or not
|
|
1339
|
+
* the access check passed. This code is not sent to the client
|
|
1340
|
+
*/
|
|
912
1341
|
serverAccess?: {
|
|
913
1342
|
read?: (permissions: StokerPermissions, user: UserRecord, record?: StokerRecord) => boolean | Promise<boolean>
|
|
914
1343
|
create?: (permissions: StokerPermissions, user: UserRecord, record: StokerRecord) => boolean | Promise<boolean>
|
|
@@ -921,68 +1350,121 @@ export interface FieldCustom extends Hooks {
|
|
|
921
1350
|
}
|
|
922
1351
|
}
|
|
923
1352
|
|
|
1353
|
+
/** Display a conditional description message under the field in the Admin UI */
|
|
924
1354
|
export interface FieldDescription {
|
|
1355
|
+
/** The description message to display */
|
|
925
1356
|
message: string | ((record?: StokerRecord) => string | Promise<string>)
|
|
1357
|
+
/** Show or hide the description */
|
|
926
1358
|
condition?: boolean | ((record?: StokerRecord) => boolean | Promise<boolean>)
|
|
927
1359
|
}
|
|
928
1360
|
|
|
1361
|
+
/** Config for a coordinates field, providing the starting location and zoom for the map */
|
|
929
1362
|
export interface LocationFieldAdmin {
|
|
1363
|
+
/** The starting coordinates for the map */
|
|
930
1364
|
center: {
|
|
931
1365
|
lat: number
|
|
932
1366
|
lng: number
|
|
933
1367
|
}
|
|
1368
|
+
/** The starting zoom value for the map */
|
|
934
1369
|
zoom: number
|
|
935
1370
|
}
|
|
936
1371
|
|
|
1372
|
+
/** An icon shown for the field on the form page */
|
|
937
1373
|
export interface FormFieldIcon {
|
|
1374
|
+
/** The icon component */
|
|
938
1375
|
component: React.FC
|
|
1376
|
+
/** Additional Tailwind classes for the icon */
|
|
939
1377
|
className?: string
|
|
940
1378
|
}
|
|
941
1379
|
|
|
1380
|
+
/** Admin UI config for the field */
|
|
942
1381
|
export interface FieldAdmin {
|
|
1382
|
+
/** A human-readable name for the field. Only necessary if `name` is not human-readable */
|
|
943
1383
|
label?: string | (() => string)
|
|
1384
|
+
/** Override the field name shown in the list view */
|
|
944
1385
|
listLabel?: string | (() => string)
|
|
1386
|
+
/** An icon that will be shown for the field on the form page */
|
|
945
1387
|
icon?: FormFieldIcon | (() => FormFieldIcon | Promise<FormFieldIcon>)
|
|
1388
|
+
/**
|
|
1389
|
+
* Show or hide the field in the list view and on the form page. The list method receives
|
|
1390
|
+
* the parent collection and parent record when shown on a relation list page. The form
|
|
1391
|
+
* method receives `isExport` as `true` during CSV export operations
|
|
1392
|
+
*/
|
|
946
1393
|
condition?: {
|
|
947
1394
|
list?: boolean | ((parentCollection?: CollectionSchema, parentRecord?: StokerRecord) => boolean)
|
|
948
1395
|
form?: boolean | ((operation?: "create" | "update", record?: StokerRecord, isExport?: boolean) => boolean)
|
|
949
1396
|
}
|
|
1397
|
+
/** Return `true` to set this as a read-only field in the Admin UI */
|
|
950
1398
|
readOnly?: boolean | ((operation?: "create" | "update", record?: StokerRecord) => boolean)
|
|
1399
|
+
/** Display a conditional description message under the field in the Admin UI */
|
|
951
1400
|
description?: FieldDescription
|
|
1401
|
+
/** Set to `true` on a String field to make it a textarea */
|
|
952
1402
|
textarea?: boolean | (() => boolean | Promise<boolean>)
|
|
1403
|
+
/** Set to `true` on a String field with `values` to make it a radio group */
|
|
953
1404
|
radio?: boolean | (() => boolean | Promise<boolean>)
|
|
1405
|
+
/** Set to `true` on a String field with `values` to make it a button group */
|
|
954
1406
|
buttonGroup?: boolean | (() => boolean | Promise<boolean>)
|
|
1407
|
+
/** Set to `true` on a Boolean field to make it a switch */
|
|
955
1408
|
switch?: boolean | (() => boolean | Promise<boolean>)
|
|
1409
|
+
/** Set to `true` on a Timestamp field to make it a month picker */
|
|
956
1410
|
month?: boolean | (() => boolean | Promise<boolean>)
|
|
1411
|
+
/** Set to `true` on a Number field to make it a slider */
|
|
957
1412
|
slider?: boolean | (() => boolean | Promise<boolean>)
|
|
1413
|
+
/** Set to `true` on a Map field to make it a rich text field */
|
|
958
1414
|
richText?: boolean | (() => boolean | Promise<boolean>)
|
|
1415
|
+
/** Set on an Array field to make it a coordinates field. Provide starting location coordinates and zoom */
|
|
959
1416
|
location?: LocationFieldAdmin | (() => LocationFieldAdmin | Promise<LocationFieldAdmin>)
|
|
1417
|
+
/** Set to `true` on a String field to make it a time field, or on a Timestamp field to make it a datetime field */
|
|
960
1418
|
time?: boolean | (() => boolean)
|
|
1419
|
+
/** Set on a String field to make it an image field. Images can be uploaded, or selected from files uploaded to the record */
|
|
961
1420
|
image?: boolean | (() => boolean)
|
|
1421
|
+
/** For Array fields. Provide an array of Tailwind classes to have values appear as colored badges. The order must match the field's `values` array */
|
|
962
1422
|
tags?: string[] | (() => string[])
|
|
1423
|
+
/** Set to `true` to have the field live-update on the form page when the record is updated remotely */
|
|
963
1424
|
live?: boolean | (() => boolean | Promise<boolean>)
|
|
1425
|
+
/** Set the position of the field in the list and the form. Defaults to the position of the field in the fields array */
|
|
964
1426
|
column?: boolean | number | (() => boolean | number)
|
|
1427
|
+
/** Set on a String field to make it a badge. Return a Tailwind class specifying the color for the badge */
|
|
965
1428
|
badge?: boolean | string | ((record?: StokerRecord) => boolean | string)
|
|
1429
|
+
/** The screen size at which the field should be hidden from the list view. This is useful for responsiveness */
|
|
966
1430
|
hidden?: "sm" | "md" | "lg" | "xl" | "2xl" | ((record?: StokerRecord) => "sm" | "md" | "lg" | "xl" | "2xl")
|
|
1431
|
+
/** Set to `true` on a String field to make it italic */
|
|
967
1432
|
italic?: boolean | ((record?: StokerRecord) => boolean)
|
|
1433
|
+
/** Set to a currency symbol to make the field a currency */
|
|
968
1434
|
currency?: string | ((record?: StokerRecord) => string)
|
|
1435
|
+
/** The returned value will be used for sorting in the list view */
|
|
969
1436
|
sort?: (record?: StokerRecord) => unknown
|
|
1437
|
+
/** Set to `true` to exclude this field from CSV export */
|
|
970
1438
|
noExport?: boolean | (() => boolean)
|
|
1439
|
+
/** Set on an Array or relational field to specify the separator to be used between items in CSV export. Defaults to `", "` */
|
|
971
1440
|
exportSeparator?: string | (() => string)
|
|
1441
|
+
/**
|
|
1442
|
+
* Set to `true` to skip required validation on the form page. This is useful if the required
|
|
1443
|
+
* field value will be set after the form has been submitted, for example in `custom.initialValue` or a hook
|
|
1444
|
+
*/
|
|
972
1445
|
skipFormRequiredValidation?: boolean | (() => boolean)
|
|
1446
|
+
/** Conditionally set a field to "required". This overrides `required`, however `required` will still be enforced on the server if present */
|
|
973
1447
|
overrideFormRequiredValidation?: (
|
|
974
1448
|
operation: "create" | "update",
|
|
975
1449
|
record?: StokerRecord,
|
|
976
1450
|
originalRecord?: StokerRecord,
|
|
977
1451
|
) => boolean
|
|
1452
|
+
/** Filter the options in the dropdown for String or Number fields with `values` set */
|
|
978
1453
|
filterValues?: (value: string | number, parentCollection: CollectionSchema, parentRecord?: StokerRecord) => boolean
|
|
1454
|
+
/** Filter the options in the dropdown for relational fields. Only works when `preloadCache` is enabled for the user's role */
|
|
979
1455
|
filterResults?: (result: StokerRecord, parentCollection: CollectionSchema, parentRecord?: StokerRecord) => boolean
|
|
1456
|
+
/** Modify the results in the dropdown for relational fields */
|
|
980
1457
|
modifyResultTitle?: (
|
|
981
1458
|
record: StokerRecord,
|
|
982
1459
|
parentCollection: CollectionSchema,
|
|
983
1460
|
parentRecord?: StokerRecord,
|
|
984
1461
|
) => string
|
|
1462
|
+
/** Modify the displayed value for the field, for example when shown in the list view or when read-only on a form */
|
|
985
1463
|
modifyDisplayValue?: (record?: StokerRecord, context?: "card" | "form" | "list" | "export") => unknown
|
|
1464
|
+
/**
|
|
1465
|
+
* Return a custom component to be used in the list view. Set `receiveClick` to `true` to have the
|
|
1466
|
+
* component receive the click and override the default behaviour of navigating to the record page
|
|
1467
|
+
*/
|
|
986
1468
|
customListView?: (
|
|
987
1469
|
record?: StokerRecord,
|
|
988
1470
|
parentCollection?: CollectionSchema,
|
|
@@ -994,18 +1476,34 @@ export interface FieldAdmin {
|
|
|
994
1476
|
receiveClick?: boolean
|
|
995
1477
|
}
|
|
996
1478
|
| undefined
|
|
1479
|
+
/** When using include fields on a relation field, return `true` to force the full relation record to be loaded (on the form page only) */
|
|
997
1480
|
queryFullRecord?: boolean | (() => boolean)
|
|
1481
|
+
/** Display a Computed field value as rich text */
|
|
998
1482
|
asRichText?: boolean | (() => boolean)
|
|
999
1483
|
}
|
|
1000
1484
|
|
|
1485
|
+
/**
|
|
1486
|
+
* Grant users access to the specified field in the related collection. This lets users select
|
|
1487
|
+
* values from a dropdown without giving them full access to the related collection
|
|
1488
|
+
*/
|
|
1001
1489
|
export interface DependencyField {
|
|
1490
|
+
/** The field in the related collection to grant access to */
|
|
1002
1491
|
field: string
|
|
1492
|
+
/** The roles to grant access to */
|
|
1003
1493
|
roles: StokerRole[]
|
|
1004
1494
|
}
|
|
1495
|
+
/** Enforce the relational integrity of the field. For example, ensure that the record's "Site" is actually related to the record's "Company" */
|
|
1005
1496
|
export interface EnforceHierarchy {
|
|
1497
|
+
/** Another relational field in the collection that is above the current field in the relational hierarchy */
|
|
1006
1498
|
field: string
|
|
1499
|
+
/** The field in the related collection above that links to the same collection as the current field */
|
|
1007
1500
|
recordLinkField: string
|
|
1008
1501
|
}
|
|
1502
|
+
/**
|
|
1503
|
+
* Place a single field exemption on the field in Firestore. If `indexExemption` is set at the
|
|
1504
|
+
* collection level, this option will re-enable indexing for the field. Consider exempting
|
|
1505
|
+
* incrementally increasing monotonic fields, large String fields, Map fields and Array fields
|
|
1506
|
+
*/
|
|
1009
1507
|
export interface SingleFieldExemption {
|
|
1010
1508
|
queryScope: "COLLECTION" | "COLLECTION_GROUP"
|
|
1011
1509
|
order?: "ASCENDING" | "DESCENDING"
|
|
@@ -1048,11 +1546,23 @@ export interface FieldAccessGroupReference {
|
|
|
1048
1546
|
group: string
|
|
1049
1547
|
}
|
|
1050
1548
|
|
|
1549
|
+
/** Properties that can be set on any field type */
|
|
1051
1550
|
export interface StandardField {
|
|
1551
|
+
/** The name of the field. It must not have spaces (use underscores). You can set a human-readable name in `admin.label` */
|
|
1052
1552
|
name: string
|
|
1553
|
+
/** A description for the field for LLMs. Only relevant if `ai` is configured */
|
|
1053
1554
|
description?: string | (() => string | Promise<string>)
|
|
1054
1555
|
|
|
1556
|
+
/**
|
|
1557
|
+
* Place a single field exemption on the field in Firestore. If `indexExemption` is set at
|
|
1558
|
+
* the collection level, this option will re-enable indexing for the field
|
|
1559
|
+
*/
|
|
1055
1560
|
singleFieldExemption?: SingleFieldExemption[] | boolean
|
|
1561
|
+
/**
|
|
1562
|
+
* Specifies that this field will be used for sorting. Not required if all user roles have
|
|
1563
|
+
* `preloadCache` or `access.serverReadOnly` enabled (sorting is automatic in these cases).
|
|
1564
|
+
* Set to `true` to sort by "asc" and "desc" for all user roles, or provide more granular config
|
|
1565
|
+
*/
|
|
1056
1566
|
sorting?:
|
|
1057
1567
|
| boolean
|
|
1058
1568
|
| {
|
|
@@ -1060,17 +1570,45 @@ export interface StandardField {
|
|
|
1060
1570
|
roles?: StokerRole[]
|
|
1061
1571
|
}
|
|
1062
1572
|
|
|
1573
|
+
/** Set to `true` if the field is a required field */
|
|
1063
1574
|
required?: boolean
|
|
1575
|
+
/** Set to `true` if the field is a nullable field */
|
|
1064
1576
|
nullable?: boolean
|
|
1065
1577
|
|
|
1578
|
+
/**
|
|
1579
|
+
* In auth collections, set to `true` to add the field to the linked user's auth token.
|
|
1580
|
+
* Be sure to control access to auth token fields using `restrictCreate` and `restrictUpdate`
|
|
1581
|
+
*/
|
|
1066
1582
|
saveToAuthToken?: boolean
|
|
1067
1583
|
|
|
1584
|
+
/**
|
|
1585
|
+
* Controls which users can access the field. Provide an array of user roles for static access,
|
|
1586
|
+
* or reference a field access group with `{ group }` for conditional access.
|
|
1587
|
+
* Warning: omitting the access property altogether allows access by ALL roles
|
|
1588
|
+
*/
|
|
1068
1589
|
access?: StokerRole[] | FieldAccessGroupReference
|
|
1590
|
+
/**
|
|
1591
|
+
* Set to `true` to prevent this field from being included when the record is created.
|
|
1592
|
+
* Alternatively, provide an array of user roles that CAN provide the field when creating
|
|
1593
|
+
* a record, or a FieldAccessCondition for even more granular access control
|
|
1594
|
+
*/
|
|
1069
1595
|
restrictCreate?: StokerRole[] | boolean | FieldAccessCondition
|
|
1596
|
+
/**
|
|
1597
|
+
* Set to `true` to prevent this field from being changed when the record is updated.
|
|
1598
|
+
* Alternatively, provide an array of user roles that CAN change the field when updating
|
|
1599
|
+
* a record, or a FieldAccessCondition for even more granular access control
|
|
1600
|
+
*/
|
|
1070
1601
|
restrictUpdate?: StokerRole[] | boolean | FieldAccessCondition
|
|
1602
|
+
/**
|
|
1603
|
+
* Skip Firestore Security Rules validation for this field. This can help to keep the size of
|
|
1604
|
+
* the security ruleset down. Validation will be performed post-write in a Cloud Function, and
|
|
1605
|
+
* you will receive an email if invalid data has been submitted
|
|
1606
|
+
*/
|
|
1071
1607
|
skipRulesValidation?: boolean
|
|
1072
1608
|
|
|
1609
|
+
/** Custom code config for the field, including hooks and server access control */
|
|
1073
1610
|
custom?: FieldCustom
|
|
1611
|
+
/** Admin UI config for the field */
|
|
1074
1612
|
admin?: FieldAdmin
|
|
1075
1613
|
}
|
|
1076
1614
|
export interface BooleanField extends StandardField {
|
|
@@ -1078,44 +1616,79 @@ export interface BooleanField extends StandardField {
|
|
|
1078
1616
|
}
|
|
1079
1617
|
export interface StringField extends StandardField {
|
|
1080
1618
|
type: "String"
|
|
1619
|
+
/** An optional list of values. This will result in a dropdown list being shown in the Admin UI */
|
|
1081
1620
|
values?: string[]
|
|
1621
|
+
/**
|
|
1622
|
+
* Set to `true` to make the field a unique field. Be sparing with this option unless
|
|
1623
|
+
* `access.serverWriteOnly` is set to `true`. Case is ignored when determining whether or not
|
|
1624
|
+
* a value is a duplicate. Unique field values are NOT freed up when a record is soft-deleted
|
|
1625
|
+
*/
|
|
1082
1626
|
unique?: boolean
|
|
1083
1627
|
|
|
1628
|
+
/** Specify a fixed length for the field */
|
|
1084
1629
|
length?: number
|
|
1630
|
+
/** Specify a minimum length for the field */
|
|
1085
1631
|
minlength?: number
|
|
1632
|
+
/** Specify a maximum length for the field */
|
|
1086
1633
|
maxlength?: number
|
|
1634
|
+
/** Specify a regex pattern for the field */
|
|
1087
1635
|
pattern?: string
|
|
1088
1636
|
|
|
1637
|
+
/** Set to `true` if the field is an email address. Only validated server-side if `access.serverWriteOnly` is `true` */
|
|
1089
1638
|
email?: boolean
|
|
1639
|
+
/** Set to `true` if the field is a url. Only validated server-side if `access.serverWriteOnly` is `true` */
|
|
1090
1640
|
url?: boolean
|
|
1641
|
+
/** Set to `true` if the field is an emoji. Only validated server-side if `access.serverWriteOnly` is `true` */
|
|
1091
1642
|
emoji?: boolean
|
|
1643
|
+
/** Set to `true` if the field is a UUID. Only validated server-side if `access.serverWriteOnly` is `true` */
|
|
1092
1644
|
uuid?: boolean
|
|
1645
|
+
/** Set to `true` if the field is an IP address. Only validated server-side if `access.serverWriteOnly` is `true` */
|
|
1093
1646
|
ip?: boolean
|
|
1094
1647
|
}
|
|
1095
1648
|
export interface NumberField extends StandardField {
|
|
1096
1649
|
type: "Number"
|
|
1650
|
+
/** An optional list of values. This will result in a dropdown list being shown in the Admin UI */
|
|
1097
1651
|
values?: number[]
|
|
1652
|
+
/**
|
|
1653
|
+
* Set to `true` to make the field a unique field. Be sparing with this option unless
|
|
1654
|
+
* `access.serverWriteOnly` is set to `true`. Unique field values are NOT freed up when a record is soft-deleted
|
|
1655
|
+
*/
|
|
1098
1656
|
unique?: boolean
|
|
1099
1657
|
|
|
1658
|
+
/**
|
|
1659
|
+
* Set to `true` to make the field an auto-incremented number. Auto-incremented numbers are
|
|
1660
|
+
* written by a Cloud Function after the record has been saved to the server, so numbers for
|
|
1661
|
+
* offline writes won't appear until the user has reconnected
|
|
1662
|
+
*/
|
|
1100
1663
|
autoIncrement?: boolean
|
|
1664
|
+
/** Set the maximum number of decimal places for this field */
|
|
1101
1665
|
decimal?: number
|
|
1102
1666
|
|
|
1667
|
+
/** Set the maximum number value for this field */
|
|
1103
1668
|
max?: number
|
|
1669
|
+
/** Set the minimum number value for this field */
|
|
1104
1670
|
min?: number
|
|
1105
1671
|
}
|
|
1106
1672
|
export interface TimestampField extends StandardField {
|
|
1107
1673
|
type: "Timestamp"
|
|
1674
|
+
/** An optional list of dates in milliseconds format. This will result in a dropdown list being shown in the Admin UI */
|
|
1108
1675
|
values?: number[]
|
|
1109
1676
|
|
|
1677
|
+
/** Set the maximum milliseconds value for this field */
|
|
1110
1678
|
max?: number
|
|
1679
|
+
/** Set the minimum milliseconds value for this field */
|
|
1111
1680
|
min?: number
|
|
1112
1681
|
}
|
|
1113
1682
|
export interface ArrayField extends StandardField {
|
|
1114
1683
|
type: "Array"
|
|
1684
|
+
/** A list of values. A dropdown selector will be shown in the Admin UI */
|
|
1115
1685
|
values?: string[]
|
|
1116
1686
|
|
|
1687
|
+
/** Set the exact required length for this field */
|
|
1117
1688
|
length?: number
|
|
1689
|
+
/** Set the minimum length for this field */
|
|
1118
1690
|
minlength?: number
|
|
1691
|
+
/** Set the maximum length for this field */
|
|
1119
1692
|
maxlength?: number
|
|
1120
1693
|
}
|
|
1121
1694
|
export interface MapField extends StandardField {
|
|
@@ -1123,17 +1696,42 @@ export interface MapField extends StandardField {
|
|
|
1123
1696
|
}
|
|
1124
1697
|
export interface RelationField extends StandardField {
|
|
1125
1698
|
type: "OneToOne" | "OneToMany" | "ManyToOne" | "ManyToMany"
|
|
1699
|
+
/** The collection for the relational field */
|
|
1126
1700
|
collection: StokerCollection
|
|
1701
|
+
/**
|
|
1702
|
+
* Enable a two-way relation. Provide the name of a relational field in the target collection
|
|
1703
|
+
* to link with. Requires `access.serverWriteOnly`
|
|
1704
|
+
*/
|
|
1127
1705
|
twoWay?: string
|
|
1706
|
+
/**
|
|
1707
|
+
* Save fields from the related record to the target record. Field values will be denormalized
|
|
1708
|
+
* and will automatically update when the source record is updated. Updates are written by a
|
|
1709
|
+
* Cloud Function, so updates made in offline mode won't appear until the user has reconnected
|
|
1710
|
+
*/
|
|
1128
1711
|
includeFields?: string[]
|
|
1712
|
+
/** Choose one of the `includeFields` values to act as the title field for the related record */
|
|
1129
1713
|
titleField?: string
|
|
1714
|
+
/** Set to `true` to preserve relation data when the related record is deleted. Warning: this may have privacy implications */
|
|
1130
1715
|
preserve?: boolean
|
|
1716
|
+
/**
|
|
1717
|
+
* Set to `true` to allow users to write any value to the relational field. By default, users
|
|
1718
|
+
* can only write values for records that they have access to. Warning: this may have security implications
|
|
1719
|
+
*/
|
|
1131
1720
|
writeAny?: boolean
|
|
1721
|
+
/**
|
|
1722
|
+
* Grant users access to the specified fields in the related collection. This lets users select
|
|
1723
|
+
* values from a dropdown without giving them full access to the related collection
|
|
1724
|
+
*/
|
|
1132
1725
|
dependencyFields?: DependencyField[]
|
|
1726
|
+
/** Enforce the relational integrity of the field. For example, ensure that the record's "Site" is actually related to the record's "Company" */
|
|
1133
1727
|
enforceHierarchy?: EnforceHierarchy
|
|
1728
|
+
/** Set the minimum number of relations for this field */
|
|
1134
1729
|
min?: number
|
|
1730
|
+
/** Set the maximum number of relations for this field */
|
|
1135
1731
|
max?: number
|
|
1732
|
+
/** Set the exact number of relations required for this field */
|
|
1136
1733
|
length?: number
|
|
1734
|
+
/** Firestore where() query constraints that will be applied when retrieving records for the dropdown selector */
|
|
1137
1735
|
constraints?: [string, "==" | "in", unknown][]
|
|
1138
1736
|
}
|
|
1139
1737
|
export interface EmbeddingField extends StandardField {
|
|
@@ -1141,9 +1739,15 @@ export interface EmbeddingField extends StandardField {
|
|
|
1141
1739
|
}
|
|
1142
1740
|
export interface ComputedField extends StandardField {
|
|
1143
1741
|
type: "Computed"
|
|
1742
|
+
/**
|
|
1743
|
+
* Calculates the value for the field. When using `getSome` or `subscribeMany`, `retrieverData`
|
|
1744
|
+
* will return the data provided by the collection's `retriever` function. This lets you load
|
|
1745
|
+
* data sets for your computed field formulas once per query
|
|
1746
|
+
*/
|
|
1144
1747
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1145
1748
|
formula: (record: StokerRecord, retrieverData?: any) => string | number | Promise<string | number>
|
|
1146
1749
|
}
|
|
1750
|
+
/** A field in a Stoker collection */
|
|
1147
1751
|
export type CollectionField =
|
|
1148
1752
|
| BooleanField
|
|
1149
1753
|
| StringField
|
|
@@ -1155,11 +1759,15 @@ export type CollectionField =
|
|
|
1155
1759
|
| EmbeddingField
|
|
1156
1760
|
| ComputedField
|
|
1157
1761
|
|
|
1762
|
+
/** Make a system field (i.e. `Created_At`, `Last_Write_By`) accessible to the given roles */
|
|
1158
1763
|
export interface RoleSystemField {
|
|
1764
|
+
/** The name of the system field */
|
|
1159
1765
|
field: string
|
|
1766
|
+
/** The roles that can access the field */
|
|
1160
1767
|
roles?: StokerRole[]
|
|
1161
1768
|
}
|
|
1162
1769
|
|
|
1770
|
+
/** The customization (custom code and Admin UI config) for a collection */
|
|
1163
1771
|
export interface CollectionCustomization {
|
|
1164
1772
|
custom?: CollectionCustom
|
|
1165
1773
|
admin?: CollectionAdmin
|
|
@@ -1171,31 +1779,61 @@ export interface CollectionCustomization {
|
|
|
1171
1779
|
}[]
|
|
1172
1780
|
}
|
|
1173
1781
|
|
|
1782
|
+
/**
|
|
1783
|
+
* Advanced. Define fields that will be indexed for querying. Only relevant if you are using
|
|
1784
|
+
* Stoker as a headless CMS. This option is handled automatically by the Admin UI
|
|
1785
|
+
*/
|
|
1174
1786
|
export interface Query {
|
|
1787
|
+
/** The name of the field */
|
|
1175
1788
|
field: string
|
|
1789
|
+
/** Set to `true` if the field is a Timestamp field */
|
|
1176
1790
|
range?: boolean
|
|
1791
|
+
/** Set to `true` if the field needs to be indexed independently of sorting */
|
|
1177
1792
|
standalone?: boolean
|
|
1793
|
+
/** The user roles that will run the query */
|
|
1178
1794
|
roles?: StokerRole[]
|
|
1179
1795
|
}
|
|
1180
1796
|
|
|
1797
|
+
/** A "child list" that will appear in the Admin UI for records in this collection, i.e. lists of related "Sites" on a "Clients" record page */
|
|
1181
1798
|
export interface RelationList {
|
|
1799
|
+
/** The collection for the relation list */
|
|
1182
1800
|
collection: StokerCollection
|
|
1801
|
+
/** The field in the current collection that relates to the collection above */
|
|
1183
1802
|
field: string
|
|
1803
|
+
/** The roles that can see this relation list */
|
|
1184
1804
|
roles?: StokerRole[]
|
|
1805
|
+
/** Firestore constraints to apply to the relation list query */
|
|
1185
1806
|
constraints?: [string, "==" | "in", unknown][]
|
|
1807
|
+
/** When `preloadCache.range` is enabled, setting this option will ignore the range restrictions and load all records available for the relation list */
|
|
1186
1808
|
loadAll?: boolean
|
|
1809
|
+
/** Show metrics above the list in the Admin UI */
|
|
1187
1810
|
showMetrics?: boolean
|
|
1811
|
+
/** A list of filters to show in the LHS sidebar when the relation list is active */
|
|
1188
1812
|
showFilters?: string[]
|
|
1189
1813
|
}
|
|
1190
1814
|
|
|
1815
|
+
/** The schema for a Stoker collection. Each collection represents a collection in Cloud Firestore, and a page in the Admin UI */
|
|
1191
1816
|
export interface CollectionSchema {
|
|
1817
|
+
/** The names for the collection. Names must start with a capital letter and contain only letters, digits, and underscores */
|
|
1192
1818
|
labels: CollectionLabels
|
|
1819
|
+
/** Access control config for the collection */
|
|
1193
1820
|
access: CollectionAccess
|
|
1821
|
+
/** The fields for the collection */
|
|
1194
1822
|
fields: (CollectionField | RelationField)[]
|
|
1823
|
+
/** The field in the collection that will be used as the record's title, i.e. "Name" */
|
|
1195
1824
|
recordTitleField: string
|
|
1196
1825
|
|
|
1826
|
+
/** Set to `true` if this collection is a "users" collection. Records in the collection can then be assigned access credentials */
|
|
1197
1827
|
auth?: boolean
|
|
1828
|
+
/**
|
|
1829
|
+
* Set to `true` if the collection will only have one record / page, i.e. "Settings".
|
|
1830
|
+
* No list page will be shown in the Admin UI; the user will be sent straight to the form page
|
|
1831
|
+
*/
|
|
1198
1832
|
singleton?: boolean
|
|
1833
|
+
/**
|
|
1834
|
+
* Advanced. Set to the collection's parent collection if this collection will be a subcollection
|
|
1835
|
+
* in Firestore. Subcollections are not currently supported in the Admin UI
|
|
1836
|
+
*/
|
|
1199
1837
|
parentCollection?: StokerCollection
|
|
1200
1838
|
|
|
1201
1839
|
/**
|
|
@@ -1204,34 +1842,80 @@ export interface CollectionSchema {
|
|
|
1204
1842
|
*/
|
|
1205
1843
|
fieldAccessGroups?: Record<string, FieldAccessCondition>
|
|
1206
1844
|
|
|
1845
|
+
/**
|
|
1846
|
+
* Preload data for the collection on app startup. Preloaded data is cached and is available
|
|
1847
|
+
* for the lifetime of the session. Highly recommended for time series data
|
|
1848
|
+
*/
|
|
1207
1849
|
preloadCache?: PreloadCache
|
|
1850
|
+
/** Enable soft-delete for this collection */
|
|
1208
1851
|
softDelete?: {
|
|
1852
|
+
/** The name of a Boolean field. This field will be set to `true` when the record is soft-deleted */
|
|
1209
1853
|
archivedField: string
|
|
1854
|
+
/** The name of a Timestamp field. This field will be set to the current time when the record is soft-deleted */
|
|
1210
1855
|
timestampField: string
|
|
1856
|
+
/** The number of days after which soft-deleted records will be permanently deleted */
|
|
1211
1857
|
retentionPeriod: number
|
|
1212
1858
|
}
|
|
1213
1859
|
|
|
1860
|
+
/** Advanced. Define fields that will be indexed for querying. Only relevant if you are using Stoker as a headless CMS */
|
|
1214
1861
|
queries?: Query[]
|
|
1862
|
+
/** Define "child lists" that will appear in the Admin UI for records in this collection */
|
|
1215
1863
|
relationLists?: RelationList[]
|
|
1864
|
+
/** Set to `true` to allow fields that are not defined in the schema to be written to records in the collection */
|
|
1216
1865
|
allowSchemalessFields?: boolean
|
|
1866
|
+
/**
|
|
1867
|
+
* Set to `true` to enable the write log for this collection. Every write to a record will be
|
|
1868
|
+
* logged in Firestore, creating a history that can be used for data recovery and audit purposes
|
|
1869
|
+
*/
|
|
1217
1870
|
enableWriteLog?: boolean
|
|
1871
|
+
/**
|
|
1872
|
+
* Set to `true` to preserve write log entries for deleted records. If not enabled, all write
|
|
1873
|
+
* log entries for a record will be deleted on record delete
|
|
1874
|
+
*/
|
|
1218
1875
|
preserveWriteLog?: boolean
|
|
1876
|
+
/**
|
|
1877
|
+
* An array of field names. These fields will be searchable. For collections without
|
|
1878
|
+
* `preloadCache` or `serverReadOnly` set to `true`, you will need to set up Algolia
|
|
1879
|
+
*/
|
|
1219
1880
|
fullTextSearch?: string[]
|
|
1881
|
+
/**
|
|
1882
|
+
* The name of a Timestamp field containing an automatic deletion date for the record,
|
|
1883
|
+
* i.e. "Expires_At". Warning: denormalized data is not currently deleted by TTL policies
|
|
1884
|
+
*/
|
|
1220
1885
|
ttl?: string
|
|
1886
|
+
/**
|
|
1887
|
+
* Set to `true` to exempt this collection from Firestore indexing. Indexes that are required
|
|
1888
|
+
* for your app to function will be re-added automatically. Improves performance and reduces
|
|
1889
|
+
* costs, but may prevent queries outside of the standard queries used by your app
|
|
1890
|
+
*/
|
|
1221
1891
|
indexExemption?: boolean
|
|
1892
|
+
/** Make system fields (i.e. `Created_At`, `Last_Write_By`) accessible to your app's users */
|
|
1222
1893
|
roleSystemFields?: RoleSystemField[]
|
|
1894
|
+
/**
|
|
1895
|
+
* Set to `true` to skip Firestore Security Rules validation of writes, for collections that hit
|
|
1896
|
+
* the limit of 1000 expressions per request. Validation will be run post-write in a Cloud
|
|
1897
|
+
* Function, and you will get an email if invalid data is submitted
|
|
1898
|
+
*/
|
|
1223
1899
|
skipRulesValidation?: boolean
|
|
1900
|
+
/** Enable an AI chat bot for the collection. The chat bot uses Retrieval Augmented Generation (RAG) to converse with the user about the data in the collection */
|
|
1224
1901
|
ai?: {
|
|
1902
|
+
/** Set to `true` to save embeddings for records in this collection. Requires the `custom.setEmbedding` hook */
|
|
1225
1903
|
embedding?: boolean
|
|
1226
1904
|
chat?: {
|
|
1905
|
+
/** The name for the chat bot */
|
|
1227
1906
|
name: string
|
|
1907
|
+
/** The number of records the LLM should retrieve for context */
|
|
1228
1908
|
defaultQueryLimit?: number
|
|
1909
|
+
/** The roles that can view the chat bot. Warning: Only assign AI chat access to roles that have access to ALL fields used to calculate embeddings */
|
|
1229
1910
|
roles: StokerRole[]
|
|
1230
1911
|
}
|
|
1231
1912
|
}
|
|
1913
|
+
/** The priority of this collection when seeding test data using `stoker seed-data` */
|
|
1232
1914
|
seedOrder?: number
|
|
1233
1915
|
|
|
1916
|
+
/** Custom code config for the collection, including hooks and server access control */
|
|
1234
1917
|
custom?: CollectionCustom
|
|
1918
|
+
/** Admin UI config for the collection */
|
|
1235
1919
|
admin?: CollectionAdmin
|
|
1236
1920
|
}
|
|
1237
1921
|
|