@stoker-platform/types 0.5.69 → 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 +1 -1
- package/src/types/app.ts +194 -1
- package/src/types/schema.ts +687 -1
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,147 +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
266
|
IndividualEntityParentFilter | ParentEntityParentFilter | ParentPropertyEntityParentFilter
|
|
180
267
|
|
|
268
|
+
/** Define which roles can perform which CRUD operations for the collection */
|
|
181
269
|
export interface AccessOperations {
|
|
270
|
+
/** Set to `true` or an array of user roles to allow disabling of access in the user's profile */
|
|
182
271
|
assignable?: boolean | StokerRole[]
|
|
272
|
+
/** Roles that can read records in the collection */
|
|
183
273
|
read?: StokerRole[]
|
|
274
|
+
/** Roles that can create records in the collection */
|
|
184
275
|
create?: StokerRole[]
|
|
276
|
+
/** Roles that can update records in the collection */
|
|
185
277
|
update?: StokerRole[]
|
|
278
|
+
/** Roles that can delete records in the collection */
|
|
186
279
|
delete?: StokerRole[]
|
|
187
280
|
}
|
|
188
281
|
|
|
282
|
+
/** The roles that must be granted each file operation */
|
|
189
283
|
export interface AccessFilesAssignmentRoles {
|
|
284
|
+
/** Roles for read access to the file */
|
|
190
285
|
read?: StokerRole[]
|
|
286
|
+
/** Roles for update access to the file */
|
|
191
287
|
update?: StokerRole[]
|
|
288
|
+
/** Roles for delete access to the file */
|
|
192
289
|
delete?: StokerRole[]
|
|
193
290
|
}
|
|
291
|
+
/** File access assignment rules for a user role */
|
|
194
292
|
export interface AccessFilesAssignment {
|
|
293
|
+
/** Access assignments the user may optionally grant */
|
|
195
294
|
optional?: AccessFilesAssignmentRoles
|
|
295
|
+
/** Access assignments the user must grant */
|
|
196
296
|
required?: AccessFilesAssignmentRoles
|
|
197
297
|
}
|
|
298
|
+
/** Access rules for file uploads */
|
|
198
299
|
export interface AccessFiles {
|
|
300
|
+
/** Define the user roles that the user must assign access to for each file */
|
|
199
301
|
assignment?: {
|
|
200
302
|
[role: StokerRole]: AccessFilesAssignment
|
|
201
303
|
}
|
|
304
|
+
/** Enforce Firebase Storage metadata constraints, i.e. `{ size: " <= (5 * 1024 * 1024)" }` */
|
|
202
305
|
metadata?: {
|
|
203
306
|
[key: string]: string
|
|
204
307
|
}
|
|
308
|
+
/** Enforce custom metadata constraints */
|
|
205
309
|
customMetadata?: {
|
|
206
310
|
[key: string]: string
|
|
207
311
|
}
|
|
208
312
|
}
|
|
209
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) */
|
|
210
315
|
export interface EntityRestrictions {
|
|
316
|
+
/** User roles for which entity restrictions can be disabled for individual users */
|
|
211
317
|
assignable?: StokerRole[]
|
|
318
|
+
/** The entity restrictions to apply */
|
|
212
319
|
restrictions?: EntityRestriction[]
|
|
320
|
+
/** Apply entity restrictions from a parent collection onto this collection, i.e. "All Jobs on Sites for Company X" */
|
|
213
321
|
parentFilters?: EntityParentFilter[]
|
|
214
322
|
}
|
|
323
|
+
/** Access control config for the collection */
|
|
215
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
|
+
*/
|
|
216
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
|
+
*/
|
|
217
336
|
serverWriteOnly?: boolean
|
|
337
|
+
/** Set to `true` to write custom Firestore Security Rules for the collection, at `firebase-rules/firestore.custom.rules` */
|
|
218
338
|
customSecurityRules?: boolean
|
|
339
|
+
/** Set to `true` to write custom Firebase Storage Rules for the collection */
|
|
219
340
|
customStorageRules?: boolean
|
|
341
|
+
/** Restrict a user's access to records with certain attributes */
|
|
220
342
|
attributeRestrictions?: AttributeRestriction[]
|
|
343
|
+
/** Explicitly define which specific records or groups of records can be accessed by a user */
|
|
221
344
|
entityRestrictions?: EntityRestrictions
|
|
345
|
+
/** Restrict which permissions a user role can assign to other user roles */
|
|
222
346
|
permissionWriteRestrictions?: PermissionWriteRestriction[]
|
|
347
|
+
/** Define which roles can perform which CRUD operations for the collection */
|
|
223
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
|
+
*/
|
|
224
355
|
auth?: { roles: StokerRole[]; assignable?: StokerRole[] }
|
|
356
|
+
/** Define access rules for file uploads */
|
|
225
357
|
files?: AccessFiles
|
|
226
358
|
}
|
|
227
359
|
|
|
360
|
+
/** Arguments for the preOperation hook, which fires before a read or write operation */
|
|
228
361
|
export type PreOperationHookArgs = {
|
|
229
362
|
operation: "read" | "create" | "update" | "delete"
|
|
230
363
|
data?: StokerRecord
|
|
@@ -234,6 +367,7 @@ export type PreOperationHookArgs = {
|
|
|
234
367
|
batch?: WriteBatch
|
|
235
368
|
originalRecord?: StokerRecord
|
|
236
369
|
}
|
|
370
|
+
/** Arguments for the preRead hook, which fires before a read operation */
|
|
237
371
|
export type PreReadHookArgs = {
|
|
238
372
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
239
373
|
context: any
|
|
@@ -241,6 +375,7 @@ export type PreReadHookArgs = {
|
|
|
241
375
|
multiple?: boolean
|
|
242
376
|
listener?: boolean
|
|
243
377
|
}
|
|
378
|
+
/** Arguments for the postRead hook, which fires after a read operation */
|
|
244
379
|
export type PostReadHookArgs = {
|
|
245
380
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
246
381
|
context: any
|
|
@@ -248,7 +383,9 @@ export type PostReadHookArgs = {
|
|
|
248
383
|
record?: StokerRecord
|
|
249
384
|
listener?: boolean
|
|
250
385
|
}
|
|
386
|
+
/** Arguments for the preDuplicate hook, which fires before a duplicate operation in the Admin UI */
|
|
251
387
|
export type PreDuplicateHookArgs = { data: Partial<StokerRecord> }
|
|
388
|
+
/** Arguments for the preValidate hook, which fires at write validation time */
|
|
252
389
|
export type PreValidateHookArgs = {
|
|
253
390
|
operation: "create" | "update"
|
|
254
391
|
data: StokerRecord
|
|
@@ -257,6 +394,7 @@ export type PreValidateHookArgs = {
|
|
|
257
394
|
batch?: WriteBatch
|
|
258
395
|
originalRecord?: StokerRecord
|
|
259
396
|
}
|
|
397
|
+
/** Arguments for the preWrite hook, which fires before a write operation */
|
|
260
398
|
export type PreWriteHookArgs = {
|
|
261
399
|
operation: "create" | "update" | "delete"
|
|
262
400
|
data: StokerRecord
|
|
@@ -266,6 +404,7 @@ export type PreWriteHookArgs = {
|
|
|
266
404
|
batch?: WriteBatch
|
|
267
405
|
originalRecord?: StokerRecord
|
|
268
406
|
}
|
|
407
|
+
/** Arguments for the postWrite hook, which fires after a write operation */
|
|
269
408
|
export type PostWriteHookArgs = {
|
|
270
409
|
operation: "create" | "update" | "delete"
|
|
271
410
|
data: StokerRecord
|
|
@@ -275,6 +414,7 @@ export type PostWriteHookArgs = {
|
|
|
275
414
|
retry?: boolean
|
|
276
415
|
originalRecord?: StokerRecord
|
|
277
416
|
}
|
|
417
|
+
/** Arguments for the postWriteError hook, which fires when a write operation encounters an error */
|
|
278
418
|
export type PostWriteErrorHookArgs = {
|
|
279
419
|
operation: "create" | "update" | "delete"
|
|
280
420
|
data: StokerRecord
|
|
@@ -287,6 +427,7 @@ export type PostWriteErrorHookArgs = {
|
|
|
287
427
|
retries?: number
|
|
288
428
|
originalRecord?: StokerRecord
|
|
289
429
|
}
|
|
430
|
+
/** Arguments for the postOperation hook, which fires after a read or write operation */
|
|
290
431
|
export type PostOperationHookArgs = {
|
|
291
432
|
operation: "read" | "create" | "update" | "delete"
|
|
292
433
|
data?: StokerRecord
|
|
@@ -297,12 +438,14 @@ export type PostOperationHookArgs = {
|
|
|
297
438
|
originalRecord?: StokerRecord
|
|
298
439
|
}
|
|
299
440
|
|
|
441
|
+
/** The access permissions assigned to an uploaded file */
|
|
300
442
|
export type FilePermissions = {
|
|
301
443
|
read?: string
|
|
302
444
|
update?: string
|
|
303
445
|
delete?: string
|
|
304
446
|
}
|
|
305
447
|
|
|
448
|
+
/** Arguments for the preFileAdd hook, which fires before a file is uploaded */
|
|
306
449
|
export type PreFileAddHookArgs = {
|
|
307
450
|
record: StokerRecord
|
|
308
451
|
fullPath: string
|
|
@@ -310,6 +453,7 @@ export type PreFileAddHookArgs = {
|
|
|
310
453
|
permissions: FilePermissions
|
|
311
454
|
}
|
|
312
455
|
|
|
456
|
+
/** Arguments for the preFileUpdate hook, which fires before a file is updated */
|
|
313
457
|
export type PreFileUpdateHookArgs = {
|
|
314
458
|
record: StokerRecord
|
|
315
459
|
update:
|
|
@@ -322,6 +466,7 @@ export type PreFileUpdateHookArgs = {
|
|
|
322
466
|
}
|
|
323
467
|
}
|
|
324
468
|
|
|
469
|
+
/** Arguments for the postFileAdd hook, which fires after a file is uploaded */
|
|
325
470
|
export type PostFileAddHookArgs = {
|
|
326
471
|
record: StokerRecord
|
|
327
472
|
fullPath: string
|
|
@@ -329,6 +474,7 @@ export type PostFileAddHookArgs = {
|
|
|
329
474
|
permissions: FilePermissions
|
|
330
475
|
}
|
|
331
476
|
|
|
477
|
+
/** Arguments for the postFileUpdate hook, which fires after a file is updated */
|
|
332
478
|
export type PostFileUpdateHookArgs = {
|
|
333
479
|
record: StokerRecord
|
|
334
480
|
update:
|
|
@@ -341,10 +487,12 @@ export type PostFileUpdateHookArgs = {
|
|
|
341
487
|
}
|
|
342
488
|
}
|
|
343
489
|
|
|
490
|
+
/** Arguments for the postFileAddError hook, which fires when a file upload fails */
|
|
344
491
|
export type PostFileAddErrorHookArgs = PostFileAddHookArgs & {
|
|
345
492
|
error: unknown
|
|
346
493
|
}
|
|
347
494
|
|
|
495
|
+
/** Arguments for the setEmbedding hook, which calculates an embedding value for the record */
|
|
348
496
|
export type SetEmbeddingHookArgs = { record: StokerRecord }
|
|
349
497
|
|
|
350
498
|
export type HookArgs =
|
|
@@ -364,24 +512,43 @@ export type HookArgs =
|
|
|
364
512
|
| PostFileUpdateHookArgs
|
|
365
513
|
| SetEmbeddingHookArgs
|
|
366
514
|
|
|
515
|
+
/** Fires before a read or write operation. Return `false` to cancel the operation */
|
|
367
516
|
export type PreOperationHook = (args: PreOperationHookArgs) => boolean | void | Promise<boolean | void>
|
|
517
|
+
/** Fires before a read operation */
|
|
368
518
|
export type PreReadHook = (args: PreReadHookArgs) => void | Promise<void>
|
|
519
|
+
/** Fires after a read operation */
|
|
369
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 */
|
|
370
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
|
+
*/
|
|
371
528
|
export type PreValidateHook = (
|
|
372
529
|
args: PreValidateHookArgs,
|
|
373
530
|
) => { valid: boolean; message?: string } | Promise<{ valid: boolean; message?: string }>
|
|
531
|
+
/** Fires before a write operation. Return `false` to cancel the operation */
|
|
374
532
|
export type PreWriteHook = (args: PreWriteHookArgs) => boolean | void | Promise<boolean | void>
|
|
533
|
+
/** Fires after a write operation */
|
|
375
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 */
|
|
376
536
|
export type PostWriteErrorHook = (args: PostWriteErrorHookArgs) => boolean | void | Promise<boolean | void>
|
|
537
|
+
/** Fires after a read or write operation */
|
|
377
538
|
export type PostOperationHook = (args: PostOperationHookArgs) => boolean | void | Promise<boolean | void>
|
|
378
539
|
|
|
540
|
+
/** Fires before a file is uploaded. Return `false` to cancel the operation */
|
|
379
541
|
export type PreFileAddHook = (args: PreFileAddHookArgs) => boolean | void | Promise<boolean | void>
|
|
542
|
+
/** Fires before a file is updated. Return `false` to cancel the operation */
|
|
380
543
|
export type PreFileUpdateHook = (args: PreFileUpdateHookArgs) => boolean | void | Promise<boolean | void>
|
|
544
|
+
/** Fires after a file is uploaded */
|
|
381
545
|
export type PostFileAddHook = (args: PostFileAddHookArgs) => boolean | void | Promise<boolean | void>
|
|
546
|
+
/** Fires after a file is updated */
|
|
382
547
|
export type PostFileUpdateHook = (args: PostFileUpdateHookArgs) => boolean | void | Promise<boolean | void>
|
|
548
|
+
/** Fires when a file upload fails */
|
|
383
549
|
export type PostFileAddErrorHook = (args: PostFileAddErrorHookArgs) => void | Promise<void>
|
|
384
550
|
|
|
551
|
+
/** Calculate an embedding value for the record */
|
|
385
552
|
export type SetEmbeddingHook = (args: SetEmbeddingHookArgs) => string | Promise<string>
|
|
386
553
|
|
|
387
554
|
export type Hook =
|
|
@@ -402,45 +569,85 @@ export type Hook =
|
|
|
402
569
|
| SetEmbeddingHook
|
|
403
570
|
|
|
404
571
|
export type Hooks = {
|
|
572
|
+
/** Fires before a read or write operation. Return `false` to cancel the operation */
|
|
405
573
|
preOperation?: PreOperationHook
|
|
574
|
+
/** Fires before a read operation */
|
|
406
575
|
preRead?: PreReadHook
|
|
576
|
+
/** Fires after a read operation */
|
|
407
577
|
postRead?: PostReadHook
|
|
578
|
+
/** Fires before a duplicate operation in the Admin UI. Return `false` to cancel the operation */
|
|
408
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
|
+
*/
|
|
409
585
|
preValidate?: PreValidateHook
|
|
586
|
+
/** Fires before a write operation. Return `false` to cancel the operation */
|
|
410
587
|
preWrite?: PreWriteHook
|
|
588
|
+
/** Fires after a write operation */
|
|
411
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 */
|
|
412
591
|
postWriteError?: PostWriteErrorHook
|
|
592
|
+
/** Fires after a read or write operation */
|
|
413
593
|
postOperation?: PostOperationHook
|
|
594
|
+
/** Fires before a file is uploaded. Return `false` to cancel the operation */
|
|
414
595
|
preFileAdd?: PreFileAddHook
|
|
596
|
+
/** Fires before a file is updated. Return `false` to cancel the operation */
|
|
415
597
|
preFileUpdate?: PreFileUpdateHook
|
|
598
|
+
/** Fires after a file is uploaded */
|
|
416
599
|
postFileAdd?: PostFileAddHook
|
|
600
|
+
/** Fires when a file upload fails */
|
|
417
601
|
postFileAddError?: PostFileAddErrorHook
|
|
602
|
+
/** Fires after a file is updated */
|
|
418
603
|
postFileUpdate?: PostFileUpdateHook
|
|
604
|
+
/** Calculate an embedding value for the record. Required for AI chat embeddings */
|
|
419
605
|
setEmbedding?: SetEmbeddingHook
|
|
420
606
|
}
|
|
421
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 */
|
|
422
609
|
export interface PreloadCacheRange {
|
|
610
|
+
/** Timestamp fields the user can preload by */
|
|
423
611
|
fields: string[]
|
|
612
|
+
/** Ranges of fields to preload, for example `["Start", "End"]`. Fields must also be listed in `fields` */
|
|
424
613
|
ranges?: [string, string][]
|
|
614
|
+
/** Human-readable labels for the fields listed in `fields` */
|
|
425
615
|
labels?: string[]
|
|
616
|
+
/** The default start date for the preloaded range */
|
|
426
617
|
start: "Today" | "Week" | "Month" | "Year" | Date | number
|
|
618
|
+
/** Offset the default start date by this many days */
|
|
427
619
|
startOffsetDays?: number
|
|
620
|
+
/** Offset the default start date by this many hours */
|
|
428
621
|
startOffsetHours?: number
|
|
622
|
+
/** The default end date for the preloaded range */
|
|
429
623
|
end?: Date | number
|
|
624
|
+
/** Offset the default end date by this many days */
|
|
430
625
|
endOffsetDays?: number
|
|
626
|
+
/** Offset the default end date by this many hours */
|
|
431
627
|
endOffsetHours?: number
|
|
628
|
+
/** Which selectors to show in the range picker */
|
|
432
629
|
selector?: "range" | "week" | "month" | ("range" | "week" | "month")[]
|
|
433
630
|
}
|
|
434
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
|
+
*/
|
|
435
637
|
export interface PreloadCache {
|
|
638
|
+
/** The user roles that will use the preload cache */
|
|
436
639
|
roles: StokerRole[]
|
|
640
|
+
/** Whether to wait for related collections to load before signalling to the app that the collection is loaded */
|
|
437
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 */
|
|
438
643
|
range?: PreloadCacheRange
|
|
644
|
+
/** Advanced. Additional Firestore constraints to apply to the preload cache */
|
|
439
645
|
constraints?:
|
|
440
646
|
| [string, WhereFilterOp, unknown][]
|
|
441
647
|
| (() => [string, WhereFilterOp, unknown][] | Promise<[string, WhereFilterOp, unknown][]>)
|
|
442
648
|
}
|
|
443
649
|
|
|
650
|
+
/** The initial preload cache state for each collection */
|
|
444
651
|
export interface PreloadCacheInitial {
|
|
445
652
|
[collection: string]: {
|
|
446
653
|
roles: StokerRole[]
|
|
@@ -450,7 +657,13 @@ export interface PreloadCacheInitial {
|
|
|
450
657
|
}
|
|
451
658
|
}
|
|
452
659
|
|
|
660
|
+
/** Custom code config for the collection, including hooks and server access control */
|
|
453
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
|
+
*/
|
|
454
667
|
serverAccess?: {
|
|
455
668
|
read?: (permissions: StokerPermissions, user: UserRecord, record?: StokerRecord) => boolean | Promise<boolean>
|
|
456
669
|
create?: (permissions: StokerPermissions, user: UserRecord, record: StokerRecord) => boolean | Promise<boolean>
|
|
@@ -462,15 +675,21 @@ export interface CollectionCustom extends Hooks {
|
|
|
462
675
|
) => boolean | Promise<boolean>
|
|
463
676
|
delete?: (permissions: StokerPermissions, user: UserRecord, record: StokerRecord) => boolean | Promise<boolean>
|
|
464
677
|
}
|
|
678
|
+
/** Advanced. Additional Firestore constraints to apply to the preload cache */
|
|
465
679
|
preloadCacheConstraints?:
|
|
466
680
|
| [string, WhereFilterOp, unknown][]
|
|
467
681
|
| (() => [string, WhereFilterOp, unknown][] | Promise<[string, WhereFilterOp, unknown][]>)
|
|
682
|
+
/** Advanced. Firestore OR query constraints to apply to the preload cache */
|
|
468
683
|
preloadCacheOrQueries?:
|
|
469
684
|
| [string, WhereFilterOp, unknown][]
|
|
470
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 */
|
|
471
687
|
autoCorrectUnique?: boolean | (() => boolean | Promise<boolean>)
|
|
688
|
+
/** Return `true` to disable adding new records while offline */
|
|
472
689
|
disableOfflineCreate?: boolean | (() => boolean | Promise<boolean>)
|
|
690
|
+
/** Return `true` to disable updating records while offline */
|
|
473
691
|
disableOfflineUpdate?: boolean | (() => boolean | Promise<boolean>)
|
|
692
|
+
/** Return `true` to disable deleting records while offline */
|
|
474
693
|
disableOfflineDelete?: boolean | (() => boolean | Promise<boolean>)
|
|
475
694
|
}
|
|
476
695
|
export interface CollectionCustomCache {
|
|
@@ -482,37 +701,64 @@ export interface CollectionCustomCache {
|
|
|
482
701
|
disableOfflineDelete?: boolean
|
|
483
702
|
}
|
|
484
703
|
|
|
704
|
+
/** Config for the list view */
|
|
485
705
|
export interface ListConfig {
|
|
706
|
+
/** Limit which user roles can view the list */
|
|
486
707
|
roles?: StokerRole[]
|
|
708
|
+
/** Customise the title for the list tab. Defaults to `"List"` */
|
|
487
709
|
title?: string
|
|
488
710
|
}
|
|
489
711
|
|
|
712
|
+
/** Show a board view with drag and drop and infinite scroll */
|
|
490
713
|
export interface CardsConfig {
|
|
714
|
+
/** Limit which user roles can view the board */
|
|
491
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 */
|
|
492
717
|
statusField?: string
|
|
718
|
+
/** Exclude status values from the board */
|
|
493
719
|
excludeValues?: string[] | number[]
|
|
720
|
+
/** The sub-heading shown on cards */
|
|
494
721
|
headerField: string
|
|
722
|
+
/** The number of lines for the header field text */
|
|
495
723
|
maxHeaderLines?: 1 | 2
|
|
724
|
+
/** Sections to display on cards */
|
|
496
725
|
sections: {
|
|
726
|
+
/** The title for the section */
|
|
497
727
|
title?: string
|
|
728
|
+
/** The fields to display in the section */
|
|
498
729
|
fields: string[]
|
|
730
|
+
/** Show multiple columns of fields, rather than listing fields down the card vertically */
|
|
499
731
|
blocks?: boolean
|
|
732
|
+
/** Show a large field value */
|
|
500
733
|
large?: boolean
|
|
734
|
+
/** The number of lines for field text */
|
|
501
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 */
|
|
502
737
|
collapse?: "sm" | "md" | "lg" | "xl" | "2xl" | ((record?: StokerRecord) => "sm" | "md" | "lg" | "xl" | "2xl")
|
|
503
738
|
}[]
|
|
739
|
+
/** The footer field shown on cards */
|
|
504
740
|
footerField?: string
|
|
741
|
+
/** The number of lines for the footer field text */
|
|
505
742
|
maxFooterLines?: 1 | 2
|
|
743
|
+
/** Customise the title for the board tab. Defaults to `"Board"` */
|
|
506
744
|
title?: string
|
|
745
|
+
/** Tailwind classes to apply to the card component */
|
|
507
746
|
cardClass?: string
|
|
508
747
|
}
|
|
509
748
|
|
|
749
|
+
/** Show a list of image cards with infinite scroll */
|
|
510
750
|
export interface ImagesConfig {
|
|
751
|
+
/** Limit which user roles can view the images page */
|
|
511
752
|
roles?: StokerRole[]
|
|
753
|
+
/** The field that contains the image URL for the record. Must be a String field */
|
|
512
754
|
imageField: string
|
|
755
|
+
/** The image size */
|
|
513
756
|
size: "sm" | "md" | "lg" | "xl"
|
|
757
|
+
/** The number of lines for the header field text */
|
|
514
758
|
maxHeaderLines?: 1 | 2
|
|
759
|
+
/** Customise the title for the images tab. Defaults to `"Pics"` */
|
|
515
760
|
title?: string
|
|
761
|
+
/** An optional custom component shown above each image */
|
|
516
762
|
customComponent?: {
|
|
517
763
|
component: React.FC<{
|
|
518
764
|
record: StokerRecord | undefined
|
|
@@ -533,55 +779,88 @@ export interface ImagesConfig {
|
|
|
533
779
|
}
|
|
534
780
|
}
|
|
535
781
|
|
|
782
|
+
/** Show a map view */
|
|
536
783
|
export interface MapConfig {
|
|
784
|
+
/** Limit which user roles can view the map page */
|
|
537
785
|
roles?: StokerRole[]
|
|
786
|
+
/** The field containing coordinates. Must be an Array field */
|
|
538
787
|
coordinatesField?: string
|
|
788
|
+
/** Alternatively, provide a String field containing an address */
|
|
539
789
|
addressField?: string
|
|
790
|
+
/** The starting coordinates for the map */
|
|
540
791
|
center: {
|
|
541
792
|
lat: number
|
|
542
793
|
lng: number
|
|
543
794
|
}
|
|
795
|
+
/** The starting zoom value for the map */
|
|
544
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) */
|
|
545
798
|
noLocation?: {
|
|
546
799
|
title: string
|
|
547
800
|
}
|
|
801
|
+
/** Customise the title for the map tab. Defaults to `"Map"` */
|
|
548
802
|
title?: string
|
|
549
803
|
}
|
|
550
804
|
|
|
805
|
+
/** Show a calendar view. Requires a Fullcalendar license */
|
|
551
806
|
export interface CalendarConfig {
|
|
807
|
+
/** Limit which user roles can view the calendar page */
|
|
552
808
|
roles?: StokerRole[]
|
|
809
|
+
/** Timestamp field specifying the start date of the event */
|
|
553
810
|
startField: string
|
|
811
|
+
/** Timestamp field specifying the end date of the event. If omitted, the start date is used */
|
|
554
812
|
endField?: string
|
|
813
|
+
/** Additional Timestamp fields to include as all-day events */
|
|
555
814
|
additionalFields?: string[]
|
|
815
|
+
/** Boolean field indicating whether records are all-day */
|
|
556
816
|
allDayField?: string
|
|
817
|
+
/** Fullcalendar options for desktop screen sizes */
|
|
557
818
|
fullCalendarLarge?: CalendarOptions
|
|
819
|
+
/** Fullcalendar options for mobile screen sizes */
|
|
558
820
|
fullCalendarSmall?: CalendarOptions
|
|
821
|
+
/** Relational field specifying a parent resource. Used for Fullcalendar features that require "resources" */
|
|
559
822
|
resourceField?: string
|
|
823
|
+
/** Field in the `resourceField` collection that acts as the resource title */
|
|
560
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 */
|
|
561
826
|
unscheduled?: {
|
|
562
827
|
title: string
|
|
563
828
|
roles?: StokerRole[]
|
|
564
829
|
}
|
|
830
|
+
/** Customise the title for the calendar tab. Defaults to `"Calendar"` */
|
|
565
831
|
title?: string
|
|
832
|
+
/** How far into the past to load records for */
|
|
566
833
|
dataStart?: { days: number } | { weeks: number } | { months: number } | { years: number }
|
|
834
|
+
/** How far into the future to load records for */
|
|
567
835
|
dataEnd?: { days: number } | { weeks: number } | { months: number } | { years: number }
|
|
836
|
+
/** Threshold at which more past records will be loaded */
|
|
568
837
|
dataStartOffset?: { days: number } | { weeks: number } | { months: number } | { years: number }
|
|
838
|
+
/** Threshold at which more future records will be loaded */
|
|
569
839
|
dataEndOffset?: { days: number } | { weeks: number } | { months: number } | { years: number }
|
|
840
|
+
/** The color for the provided record's event on the calendar */
|
|
570
841
|
color?: string | ((record: StokerRecord) => string)
|
|
842
|
+
/** A custom title for the provided record's event on the calendar */
|
|
571
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 */
|
|
572
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 */
|
|
573
847
|
additionalCollections?: StokerCollection[]
|
|
574
848
|
}
|
|
575
849
|
|
|
850
|
+
/** Filter the list by the collection's status field */
|
|
576
851
|
export type StatusFilter = {
|
|
577
852
|
type: "status"
|
|
578
853
|
value?: string | number
|
|
854
|
+
/** The roles that can see this filter */
|
|
579
855
|
roles?: StokerRole[]
|
|
580
856
|
}
|
|
581
857
|
|
|
858
|
+
/** Filter the list by a Timestamp field */
|
|
582
859
|
export type RangeFilter = {
|
|
583
860
|
type: "range"
|
|
861
|
+
/** The Timestamp field to filter by */
|
|
584
862
|
field: string
|
|
863
|
+
/** Which selectors to show in the range picker */
|
|
585
864
|
selector?:
|
|
586
865
|
| "range"
|
|
587
866
|
| "week"
|
|
@@ -589,29 +868,40 @@ export type RangeFilter = {
|
|
|
589
868
|
| ("range" | "week" | "month")[]
|
|
590
869
|
| (() => "range" | "week" | "month" | ("range" | "week" | "month")[])
|
|
591
870
|
value?: string
|
|
871
|
+
/** Offset the default start date by this many days */
|
|
592
872
|
startOffsetDays?: number
|
|
873
|
+
/** Offset the default start date by this many hours */
|
|
593
874
|
startOffsetHours?: number
|
|
875
|
+
/** Offset the default end date by this many days */
|
|
594
876
|
endOffsetDays?: number
|
|
877
|
+
/** Offset the default end date by this many hours */
|
|
595
878
|
endOffsetHours?: number
|
|
596
879
|
}
|
|
597
880
|
|
|
881
|
+
/** Filter the list by a field with `values` set */
|
|
598
882
|
export type SelectFilter = {
|
|
599
883
|
type: "select"
|
|
884
|
+
/** The field to filter by. Must have `values` set */
|
|
600
885
|
field: string
|
|
886
|
+
/** The title for the filter */
|
|
601
887
|
title?: string | (() => string)
|
|
888
|
+
/** The roles that can see this filter */
|
|
602
889
|
roles?: StokerRole[]
|
|
890
|
+
/** Modify the titles shown for filter values */
|
|
603
891
|
titles?: (
|
|
604
892
|
value: string,
|
|
605
893
|
relationCollection?: CollectionSchema,
|
|
606
894
|
relationParent?: StokerRecord,
|
|
607
895
|
isAssigning?: boolean,
|
|
608
896
|
) => string
|
|
897
|
+
/** Filter which values are shown in the filter */
|
|
609
898
|
filterValues?: (
|
|
610
899
|
value: boolean | string | number | undefined,
|
|
611
900
|
relationCollection?: CollectionSchema,
|
|
612
901
|
relationParent?: StokerRecord,
|
|
613
902
|
isAssigning?: boolean,
|
|
614
903
|
) => boolean
|
|
904
|
+
/** The default value for the filter */
|
|
615
905
|
defaultValue?:
|
|
616
906
|
| string
|
|
617
907
|
| number
|
|
@@ -620,88 +910,147 @@ export type SelectFilter = {
|
|
|
620
910
|
parentRecord?: StokerRecord,
|
|
621
911
|
isAssigning?: boolean,
|
|
622
912
|
) => string | number | undefined)
|
|
913
|
+
/** Show or hide the filter */
|
|
623
914
|
condition?: (parentCollection?: CollectionSchema, parentRecord?: StokerRecord, isAssigning?: boolean) => boolean
|
|
624
915
|
value?: string | number
|
|
916
|
+
/** The style of the filter input */
|
|
625
917
|
style?: "select" | "radio" | "buttons"
|
|
626
918
|
}
|
|
627
919
|
|
|
920
|
+
/** Filter the list by a related field */
|
|
628
921
|
export type RelationFilter = {
|
|
629
922
|
type: "relation"
|
|
923
|
+
/** The relational field to filter by */
|
|
630
924
|
field: string
|
|
925
|
+
/** The title for the filter */
|
|
631
926
|
title?: string | (() => string)
|
|
927
|
+
/** The roles that can see this filter */
|
|
632
928
|
roles?: StokerRole[]
|
|
929
|
+
/** Filter the list of related values using a Firestore where() query */
|
|
633
930
|
constraints?: [string, "==" | "in", unknown][]
|
|
634
931
|
value?: string
|
|
635
932
|
}
|
|
636
933
|
|
|
934
|
+
/** A filter shown in the right-hand-side filter drawer on the list page */
|
|
637
935
|
export type Filter = StatusFilter | RangeFilter | SelectFilter | RelationFilter
|
|
638
936
|
|
|
937
|
+
/** Show a metric (numerical counter) at the top of the list page */
|
|
639
938
|
export interface Metric {
|
|
939
|
+
/** The metric type. For "custom" metrics, use the `formula` method to calculate the value to display */
|
|
640
940
|
type: "sum" | "average" | "count" | "custom"
|
|
941
|
+
/** The field to aggregate. Not required for `count` or `custom` */
|
|
641
942
|
field?: string
|
|
943
|
+
/** Limit which user roles can view the metric */
|
|
642
944
|
roles?: StokerRole[]
|
|
945
|
+
/** The title shown above the metric */
|
|
643
946
|
title?: string
|
|
947
|
+
/** Maximum decimal places to display */
|
|
644
948
|
decimal?: number
|
|
949
|
+
/** Prefix text, for example a currency symbol */
|
|
645
950
|
prefix?: string
|
|
951
|
+
/** Suffix text, for example units */
|
|
646
952
|
suffix?: string
|
|
953
|
+
/** Tailwind text size for the metric value */
|
|
647
954
|
textSize?: "text-xl" | "text-2xl" | "text-3xl"
|
|
955
|
+
/** Compact the metric vertically */
|
|
648
956
|
compact?: boolean
|
|
957
|
+
/** Custom metric calculation */
|
|
649
958
|
formula?: (records: StokerRecord[]) => number | string
|
|
650
959
|
}
|
|
960
|
+
/** Show a chart at the top of the list page */
|
|
651
961
|
export interface Chart {
|
|
962
|
+
/** The chart type */
|
|
652
963
|
type: "area"
|
|
964
|
+
/** The date field used to group points */
|
|
653
965
|
dateField: string
|
|
966
|
+
/** First metric field */
|
|
654
967
|
metricField1?: string
|
|
968
|
+
/** Optional second metric field */
|
|
655
969
|
metricField2?: string
|
|
970
|
+
/** Default chart date range */
|
|
656
971
|
defaultRange: "90d" | "30d" | "7d"
|
|
972
|
+
/** Limit which user roles can view the chart */
|
|
657
973
|
roles?: StokerRole[]
|
|
974
|
+
/** Title shown above the chart */
|
|
658
975
|
title?: string
|
|
976
|
+
/** Currency symbol to display */
|
|
659
977
|
currency?: string | (() => string)
|
|
660
978
|
}
|
|
979
|
+
/** A custom meta title and description for the collection's pages */
|
|
661
980
|
export interface CollectionMeta {
|
|
662
981
|
title?: string
|
|
663
982
|
description?: string
|
|
664
983
|
}
|
|
984
|
+
/** Highlight rows in the list view */
|
|
665
985
|
export interface RowHighlight {
|
|
986
|
+
/** Return `true` to highlight the row for the given record */
|
|
666
987
|
condition: (record: StokerRecord) => boolean
|
|
988
|
+
/** The Tailwind classes to apply to the highlighted row */
|
|
667
989
|
className: string
|
|
990
|
+
/** The user roles to highlight rows for */
|
|
668
991
|
roles?: StokerRole[]
|
|
669
992
|
}
|
|
993
|
+
/** Converting a record creates a new record in the target collection and keeps the original */
|
|
670
994
|
export interface Convert {
|
|
995
|
+
/** The collection to convert records to */
|
|
671
996
|
collection: string
|
|
997
|
+
/** A function that modifies the record before conversion */
|
|
672
998
|
convert: (record: StokerRecord) => Partial<StokerRecord> | Promise<Partial<StokerRecord>>
|
|
999
|
+
/** The roles that can perform this conversion */
|
|
673
1000
|
roles?: StokerRole[]
|
|
674
1001
|
}
|
|
1002
|
+
/** A custom form field component */
|
|
675
1003
|
export interface CustomField {
|
|
1004
|
+
/** The position of the custom component in the form */
|
|
676
1005
|
position?: number | ((record?: StokerRecord) => number)
|
|
1006
|
+
/** The React component */
|
|
677
1007
|
component?: React.FC
|
|
1008
|
+
/** Props to pass to the React component */
|
|
678
1009
|
props?: Record<string, unknown>
|
|
1010
|
+
/** Show or hide the custom component */
|
|
679
1011
|
condition?: (operation: "create" | "update" | "update-many", record?: StokerRecord) => boolean
|
|
680
1012
|
}
|
|
1013
|
+
/** Show a relation list directly on the edit record form page */
|
|
681
1014
|
export interface FormList {
|
|
1015
|
+
/** The collection to show the relation list for */
|
|
682
1016
|
collection: StokerCollection
|
|
1017
|
+
/** Which columns to show in the list */
|
|
683
1018
|
fields: string[]
|
|
1019
|
+
/** The field to sort records by */
|
|
684
1020
|
sortField?: string
|
|
1021
|
+
/** The direction to sort records by */
|
|
685
1022
|
sortDirection?: "asc" | "desc"
|
|
1023
|
+
/** The title for the relation list */
|
|
686
1024
|
label?: string
|
|
687
1025
|
}
|
|
688
1026
|
|
|
1027
|
+
/** A custom button shown at the bottom of the edit record form */
|
|
689
1028
|
export interface FormButton {
|
|
1029
|
+
/** The title text for the custom button */
|
|
690
1030
|
title: string
|
|
1031
|
+
/** The icon shown on the button */
|
|
691
1032
|
icon?: React.FC<{ className?: string }>
|
|
1033
|
+
/** The style of the button */
|
|
692
1034
|
variant?: "default" | "destructive" | "outline" | "secondary" | "ghost" | "link"
|
|
1035
|
+
/** The function that fires when the button is clicked */
|
|
693
1036
|
action: (
|
|
694
1037
|
operation: "create" | "update" | "update-many",
|
|
695
1038
|
formValues: StokerRecord,
|
|
696
1039
|
originalRecord?: StokerRecord,
|
|
697
1040
|
) => void | Promise<void>
|
|
1041
|
+
/** Show or hide the button */
|
|
698
1042
|
condition?: boolean | ((operation: "create" | "update" | "update-many", record?: StokerRecord) => boolean)
|
|
1043
|
+
/** A loading callback that will be called when the button is pressed */
|
|
699
1044
|
setIsLoading?: (isLoading: boolean) => void
|
|
700
1045
|
}
|
|
701
1046
|
|
|
1047
|
+
/** A custom page for the collection, shown in the record page sidebar */
|
|
702
1048
|
export interface CustomRecordPage {
|
|
1049
|
+
/** The title for the custom page in the sidebar */
|
|
703
1050
|
title: string
|
|
1051
|
+
/** The URL segment that the page will load on */
|
|
704
1052
|
url: string
|
|
1053
|
+
/** The custom component */
|
|
705
1054
|
component: React.FC<{
|
|
706
1055
|
record: StokerRecord | undefined
|
|
707
1056
|
collection: CollectionSchema
|
|
@@ -712,8 +1061,11 @@ export interface CustomRecordPage {
|
|
|
712
1061
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
713
1062
|
utils: any
|
|
714
1063
|
}>
|
|
1064
|
+
/** Props to pass to the custom component */
|
|
715
1065
|
props?: Record<string, unknown>
|
|
1066
|
+
/** Show or hide the custom page */
|
|
716
1067
|
condition?: (record: StokerRecord | undefined) => boolean
|
|
1068
|
+
/** The icon shown in the sidebar */
|
|
717
1069
|
icon?: React.FC<{ className?: string }>
|
|
718
1070
|
}
|
|
719
1071
|
|
|
@@ -729,21 +1081,33 @@ export interface Assignable {
|
|
|
729
1081
|
}[]
|
|
730
1082
|
}
|
|
731
1083
|
|
|
1084
|
+
/** A custom action shown in a dropdown menu on the list page */
|
|
732
1085
|
export interface CustomListAction {
|
|
1086
|
+
/** The title for the action */
|
|
733
1087
|
title: string
|
|
1088
|
+
/** The icon shown for the action */
|
|
734
1089
|
icon?: React.FC<{ className?: string }>
|
|
1090
|
+
/** The function that fires when the action is clicked */
|
|
735
1091
|
action: () => void | Promise<void>
|
|
1092
|
+
/** Show or hide the action */
|
|
736
1093
|
condition?: () => boolean
|
|
737
1094
|
}
|
|
738
1095
|
|
|
1096
|
+
/** Options for file uploads */
|
|
739
1097
|
export interface FileOptions {
|
|
1098
|
+
/** The maximum width for uploaded image files. Images above this size will be downscaled */
|
|
740
1099
|
maxImageWidth?: number
|
|
1100
|
+
/** Set to `true` to show thumbnails for images in the files list */
|
|
741
1101
|
thumbnails?: boolean
|
|
742
1102
|
}
|
|
743
1103
|
|
|
1104
|
+
/** Admin UI config for the collection */
|
|
744
1105
|
export interface CollectionAdmin {
|
|
1106
|
+
/** Return `true` to hide the collection in the Admin UI */
|
|
745
1107
|
hidden?: boolean | (() => boolean | Promise<boolean>)
|
|
1108
|
+
/** The collection's position in the navbar */
|
|
746
1109
|
navbarPosition?: number | (() => number)
|
|
1110
|
+
/** Human-readable labels for the collection. Only necessary if the root `labels` are not human-readable */
|
|
747
1111
|
titles?:
|
|
748
1112
|
| {
|
|
749
1113
|
collection: string
|
|
@@ -754,15 +1118,31 @@ export interface CollectionAdmin {
|
|
|
754
1118
|
parentCollection?: CollectionSchema,
|
|
755
1119
|
parentRecord?: StokerRecord,
|
|
756
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 */
|
|
757
1122
|
icon?: React.FC | (() => React.FC | Promise<React.FC>)
|
|
1123
|
+
/** Return `true` to show the "Duplicate" button on the form page */
|
|
758
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 */
|
|
759
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
|
+
*/
|
|
760
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
|
+
*/
|
|
761
1137
|
statusField?: {
|
|
1138
|
+
/** The field that defines the active / archived status */
|
|
762
1139
|
field: string
|
|
1140
|
+
/** Values considered active */
|
|
763
1141
|
active?: unknown[]
|
|
1142
|
+
/** Values considered archived */
|
|
764
1143
|
archived?: unknown[]
|
|
765
1144
|
}
|
|
1145
|
+
/** The default view for the collection */
|
|
766
1146
|
defaultView?:
|
|
767
1147
|
| "list"
|
|
768
1148
|
| "cards"
|
|
@@ -773,7 +1153,9 @@ export interface CollectionAdmin {
|
|
|
773
1153
|
parentCollection: CollectionSchema,
|
|
774
1154
|
parentRecord?: StokerRecord,
|
|
775
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 */
|
|
776
1157
|
defaultRoute?: string | (() => string)
|
|
1158
|
+
/** The default field to sort the list by */
|
|
777
1159
|
defaultSort?:
|
|
778
1160
|
| {
|
|
779
1161
|
field: string
|
|
@@ -788,6 +1170,7 @@ export interface CollectionAdmin {
|
|
|
788
1170
|
field: string
|
|
789
1171
|
direction?: "asc" | "desc"
|
|
790
1172
|
}>)
|
|
1173
|
+
/** The secondary field to sort the list by. Only works for collections with `preloadCache` or `access.serverReadOnly` enabled */
|
|
791
1174
|
secondarySort?:
|
|
792
1175
|
| {
|
|
793
1176
|
field: string
|
|
@@ -802,52 +1185,93 @@ export interface CollectionAdmin {
|
|
|
802
1185
|
field: string
|
|
803
1186
|
direction?: "asc" | "desc"
|
|
804
1187
|
}>)
|
|
1188
|
+
/** The number of items to show per page */
|
|
805
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
|
+
*/
|
|
806
1195
|
searchOptions?: SearchOptions & { hitsPerPage?: number }
|
|
1196
|
+
/** Config for the list view */
|
|
807
1197
|
list?: ListConfig | (() => ListConfig | Promise<ListConfig>)
|
|
1198
|
+
/** Show a board view with drag and drop and infinite scroll */
|
|
808
1199
|
cards?: CardsConfig | (() => CardsConfig | Promise<CardsConfig>)
|
|
1200
|
+
/** Show a list of image cards with infinite scroll */
|
|
809
1201
|
images?: ImagesConfig | (() => ImagesConfig | Promise<ImagesConfig>)
|
|
1202
|
+
/** Show a map view */
|
|
810
1203
|
map?: MapConfig | (() => MapConfig | Promise<MapConfig>)
|
|
1204
|
+
/** Show a calendar view. Requires a Fullcalendar license */
|
|
811
1205
|
calendar?: CalendarConfig | (() => CalendarConfig | Promise<CalendarConfig>)
|
|
1206
|
+
/** Filters that will appear in the right-hand-side filter drawer on the list page */
|
|
812
1207
|
filters?: Filter[]
|
|
1208
|
+
/** The date range selector options to be shown to the user. Only relevant when `preloadCache.range` is present */
|
|
813
1209
|
rangeSelectorValues?:
|
|
814
1210
|
| "range"
|
|
815
1211
|
| "week"
|
|
816
1212
|
| "month"
|
|
817
1213
|
| ("range" | "week" | "month")[]
|
|
818
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 */
|
|
819
1216
|
defaultRangeSelector?: "range" | "week" | "month" | (() => "range" | "week" | "month")
|
|
1217
|
+
/** Restrict CSV export to the defined roles */
|
|
820
1218
|
restrictExport?: StokerRole[] | (() => StokerRole[] | Promise<StokerRole[]>)
|
|
1219
|
+
/** Display a counter in the title bar showing the number of items in the list */
|
|
821
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 */
|
|
822
1222
|
metrics?: (Metric | Chart)[] | (() => (Metric | Chart)[] | Promise<(Metric | Chart)[]>)
|
|
1223
|
+
/** Define a custom meta title and description for the collection's pages */
|
|
823
1224
|
meta?: CollectionMeta | (() => CollectionMeta | Promise<CollectionMeta>)
|
|
1225
|
+
/** Highlight rows in the list view */
|
|
824
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 */
|
|
825
1228
|
breadcrumbs?: string[] | (() => string[] | Promise<string[]>)
|
|
1229
|
+
/** Create custom form field components */
|
|
826
1230
|
customFields?: CustomField[] | (() => CustomField[] | Promise<CustomField[]>)
|
|
1231
|
+
/** Create custom pages for the collection */
|
|
827
1232
|
customRecordPages?: CustomRecordPage[] | (() => CustomRecordPage[] | Promise<CustomRecordPage[]>)
|
|
1233
|
+
/** Show custom buttons at the bottom of the edit record form */
|
|
828
1234
|
formButtons?: FormButton[] | (() => FormButton[] | Promise<FormButton[]>)
|
|
1235
|
+
/** Show a file upload button on the add record form */
|
|
829
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 */
|
|
830
1238
|
formImages?: boolean | (() => boolean | Promise<boolean>)
|
|
1239
|
+
/** Show relation lists directly on the edit record form page */
|
|
831
1240
|
formLists?: FormList[] | (() => FormList[] | Promise<FormList[]>)
|
|
1241
|
+
/** Hide the add record button */
|
|
832
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
|
+
*/
|
|
833
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
|
+
*/
|
|
834
1252
|
onFormOpen?: (
|
|
835
1253
|
operation: "create" | "update",
|
|
836
1254
|
record: StokerRecord,
|
|
837
1255
|
parentCollection?: StokerCollection,
|
|
838
1256
|
parentRecord?: StokerRecord,
|
|
839
1257
|
) => void | Promise<void>
|
|
1258
|
+
/** A hook that fires whenever the form is updated. Optionally return an object with field updates */
|
|
840
1259
|
onChange?: (
|
|
841
1260
|
operation: "create" | "update",
|
|
842
1261
|
record: StokerRecord,
|
|
843
1262
|
originalRecord: StokerRecord,
|
|
844
1263
|
) => Partial<StokerRecord> | void | Promise<Partial<StokerRecord> | void>
|
|
1264
|
+
/** Override the default behaviour of opening the add record form */
|
|
845
1265
|
addRecordButtonOverride?: (record?: StokerRecord) => void | Promise<void>
|
|
1266
|
+
/** Disable the date range selector for the user */
|
|
846
1267
|
disableRangeSelector?: boolean | (() => boolean)
|
|
1268
|
+
/** Load data for use in your computed fields, once per query */
|
|
847
1269
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
848
1270
|
retriever?: () => any | Promise<any>
|
|
849
1271
|
assignable?: Assignable[] | (() => Assignable[] | Promise<Assignable[]>)
|
|
1272
|
+
/** Custom actions that will be shown in a dropdown menu on the list page */
|
|
850
1273
|
customListActions?: CustomListAction[] | (() => CustomListAction[] | Promise<CustomListAction[]>)
|
|
1274
|
+
/** Options for file uploads */
|
|
851
1275
|
fileOptions?: FileOptions | (() => FileOptions | Promise<FileOptions>)
|
|
852
1276
|
}
|
|
853
1277
|
export interface CollectionAdminCache {
|
|
@@ -905,8 +1329,15 @@ export interface CollectionAdminCache {
|
|
|
905
1329
|
fileOptions?: FileOptions
|
|
906
1330
|
}
|
|
907
1331
|
|
|
1332
|
+
/** Custom code config for the field, including hooks and server access control */
|
|
908
1333
|
export interface FieldCustom extends Hooks {
|
|
1334
|
+
/** Calculate an initial value for this field when creating the record */
|
|
909
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
|
+
*/
|
|
910
1341
|
serverAccess?: {
|
|
911
1342
|
read?: (permissions: StokerPermissions, user: UserRecord, record?: StokerRecord) => boolean | Promise<boolean>
|
|
912
1343
|
create?: (permissions: StokerPermissions, user: UserRecord, record: StokerRecord) => boolean | Promise<boolean>
|
|
@@ -919,68 +1350,121 @@ export interface FieldCustom extends Hooks {
|
|
|
919
1350
|
}
|
|
920
1351
|
}
|
|
921
1352
|
|
|
1353
|
+
/** Display a conditional description message under the field in the Admin UI */
|
|
922
1354
|
export interface FieldDescription {
|
|
1355
|
+
/** The description message to display */
|
|
923
1356
|
message: string | ((record?: StokerRecord) => string | Promise<string>)
|
|
1357
|
+
/** Show or hide the description */
|
|
924
1358
|
condition?: boolean | ((record?: StokerRecord) => boolean | Promise<boolean>)
|
|
925
1359
|
}
|
|
926
1360
|
|
|
1361
|
+
/** Config for a coordinates field, providing the starting location and zoom for the map */
|
|
927
1362
|
export interface LocationFieldAdmin {
|
|
1363
|
+
/** The starting coordinates for the map */
|
|
928
1364
|
center: {
|
|
929
1365
|
lat: number
|
|
930
1366
|
lng: number
|
|
931
1367
|
}
|
|
1368
|
+
/** The starting zoom value for the map */
|
|
932
1369
|
zoom: number
|
|
933
1370
|
}
|
|
934
1371
|
|
|
1372
|
+
/** An icon shown for the field on the form page */
|
|
935
1373
|
export interface FormFieldIcon {
|
|
1374
|
+
/** The icon component */
|
|
936
1375
|
component: React.FC
|
|
1376
|
+
/** Additional Tailwind classes for the icon */
|
|
937
1377
|
className?: string
|
|
938
1378
|
}
|
|
939
1379
|
|
|
1380
|
+
/** Admin UI config for the field */
|
|
940
1381
|
export interface FieldAdmin {
|
|
1382
|
+
/** A human-readable name for the field. Only necessary if `name` is not human-readable */
|
|
941
1383
|
label?: string | (() => string)
|
|
1384
|
+
/** Override the field name shown in the list view */
|
|
942
1385
|
listLabel?: string | (() => string)
|
|
1386
|
+
/** An icon that will be shown for the field on the form page */
|
|
943
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
|
+
*/
|
|
944
1393
|
condition?: {
|
|
945
1394
|
list?: boolean | ((parentCollection?: CollectionSchema, parentRecord?: StokerRecord) => boolean)
|
|
946
1395
|
form?: boolean | ((operation?: "create" | "update", record?: StokerRecord, isExport?: boolean) => boolean)
|
|
947
1396
|
}
|
|
1397
|
+
/** Return `true` to set this as a read-only field in the Admin UI */
|
|
948
1398
|
readOnly?: boolean | ((operation?: "create" | "update", record?: StokerRecord) => boolean)
|
|
1399
|
+
/** Display a conditional description message under the field in the Admin UI */
|
|
949
1400
|
description?: FieldDescription
|
|
1401
|
+
/** Set to `true` on a String field to make it a textarea */
|
|
950
1402
|
textarea?: boolean | (() => boolean | Promise<boolean>)
|
|
1403
|
+
/** Set to `true` on a String field with `values` to make it a radio group */
|
|
951
1404
|
radio?: boolean | (() => boolean | Promise<boolean>)
|
|
1405
|
+
/** Set to `true` on a String field with `values` to make it a button group */
|
|
952
1406
|
buttonGroup?: boolean | (() => boolean | Promise<boolean>)
|
|
1407
|
+
/** Set to `true` on a Boolean field to make it a switch */
|
|
953
1408
|
switch?: boolean | (() => boolean | Promise<boolean>)
|
|
1409
|
+
/** Set to `true` on a Timestamp field to make it a month picker */
|
|
954
1410
|
month?: boolean | (() => boolean | Promise<boolean>)
|
|
1411
|
+
/** Set to `true` on a Number field to make it a slider */
|
|
955
1412
|
slider?: boolean | (() => boolean | Promise<boolean>)
|
|
1413
|
+
/** Set to `true` on a Map field to make it a rich text field */
|
|
956
1414
|
richText?: boolean | (() => boolean | Promise<boolean>)
|
|
1415
|
+
/** Set on an Array field to make it a coordinates field. Provide starting location coordinates and zoom */
|
|
957
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 */
|
|
958
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 */
|
|
959
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 */
|
|
960
1422
|
tags?: string[] | (() => string[])
|
|
1423
|
+
/** Set to `true` to have the field live-update on the form page when the record is updated remotely */
|
|
961
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 */
|
|
962
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 */
|
|
963
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 */
|
|
964
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 */
|
|
965
1432
|
italic?: boolean | ((record?: StokerRecord) => boolean)
|
|
1433
|
+
/** Set to a currency symbol to make the field a currency */
|
|
966
1434
|
currency?: string | ((record?: StokerRecord) => string)
|
|
1435
|
+
/** The returned value will be used for sorting in the list view */
|
|
967
1436
|
sort?: (record?: StokerRecord) => unknown
|
|
1437
|
+
/** Set to `true` to exclude this field from CSV export */
|
|
968
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 `", "` */
|
|
969
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
|
+
*/
|
|
970
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 */
|
|
971
1447
|
overrideFormRequiredValidation?: (
|
|
972
1448
|
operation: "create" | "update",
|
|
973
1449
|
record?: StokerRecord,
|
|
974
1450
|
originalRecord?: StokerRecord,
|
|
975
1451
|
) => boolean
|
|
1452
|
+
/** Filter the options in the dropdown for String or Number fields with `values` set */
|
|
976
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 */
|
|
977
1455
|
filterResults?: (result: StokerRecord, parentCollection: CollectionSchema, parentRecord?: StokerRecord) => boolean
|
|
1456
|
+
/** Modify the results in the dropdown for relational fields */
|
|
978
1457
|
modifyResultTitle?: (
|
|
979
1458
|
record: StokerRecord,
|
|
980
1459
|
parentCollection: CollectionSchema,
|
|
981
1460
|
parentRecord?: StokerRecord,
|
|
982
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 */
|
|
983
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
|
+
*/
|
|
984
1468
|
customListView?: (
|
|
985
1469
|
record?: StokerRecord,
|
|
986
1470
|
parentCollection?: CollectionSchema,
|
|
@@ -992,18 +1476,34 @@ export interface FieldAdmin {
|
|
|
992
1476
|
receiveClick?: boolean
|
|
993
1477
|
}
|
|
994
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) */
|
|
995
1480
|
queryFullRecord?: boolean | (() => boolean)
|
|
1481
|
+
/** Display a Computed field value as rich text */
|
|
996
1482
|
asRichText?: boolean | (() => boolean)
|
|
997
1483
|
}
|
|
998
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
|
+
*/
|
|
999
1489
|
export interface DependencyField {
|
|
1490
|
+
/** The field in the related collection to grant access to */
|
|
1000
1491
|
field: string
|
|
1492
|
+
/** The roles to grant access to */
|
|
1001
1493
|
roles: StokerRole[]
|
|
1002
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" */
|
|
1003
1496
|
export interface EnforceHierarchy {
|
|
1497
|
+
/** Another relational field in the collection that is above the current field in the relational hierarchy */
|
|
1004
1498
|
field: string
|
|
1499
|
+
/** The field in the related collection above that links to the same collection as the current field */
|
|
1005
1500
|
recordLinkField: string
|
|
1006
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
|
+
*/
|
|
1007
1507
|
export interface SingleFieldExemption {
|
|
1008
1508
|
queryScope: "COLLECTION" | "COLLECTION_GROUP"
|
|
1009
1509
|
order?: "ASCENDING" | "DESCENDING"
|
|
@@ -1046,11 +1546,23 @@ export interface FieldAccessGroupReference {
|
|
|
1046
1546
|
group: string
|
|
1047
1547
|
}
|
|
1048
1548
|
|
|
1549
|
+
/** Properties that can be set on any field type */
|
|
1049
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` */
|
|
1050
1552
|
name: string
|
|
1553
|
+
/** A description for the field for LLMs. Only relevant if `ai` is configured */
|
|
1051
1554
|
description?: string | (() => string | Promise<string>)
|
|
1052
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
|
+
*/
|
|
1053
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
|
+
*/
|
|
1054
1566
|
sorting?:
|
|
1055
1567
|
| boolean
|
|
1056
1568
|
| {
|
|
@@ -1058,17 +1570,45 @@ export interface StandardField {
|
|
|
1058
1570
|
roles?: StokerRole[]
|
|
1059
1571
|
}
|
|
1060
1572
|
|
|
1573
|
+
/** Set to `true` if the field is a required field */
|
|
1061
1574
|
required?: boolean
|
|
1575
|
+
/** Set to `true` if the field is a nullable field */
|
|
1062
1576
|
nullable?: boolean
|
|
1063
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
|
+
*/
|
|
1064
1582
|
saveToAuthToken?: boolean
|
|
1065
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
|
+
*/
|
|
1066
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
|
+
*/
|
|
1067
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
|
+
*/
|
|
1068
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
|
+
*/
|
|
1069
1607
|
skipRulesValidation?: boolean
|
|
1070
1608
|
|
|
1609
|
+
/** Custom code config for the field, including hooks and server access control */
|
|
1071
1610
|
custom?: FieldCustom
|
|
1611
|
+
/** Admin UI config for the field */
|
|
1072
1612
|
admin?: FieldAdmin
|
|
1073
1613
|
}
|
|
1074
1614
|
export interface BooleanField extends StandardField {
|
|
@@ -1076,44 +1616,79 @@ export interface BooleanField extends StandardField {
|
|
|
1076
1616
|
}
|
|
1077
1617
|
export interface StringField extends StandardField {
|
|
1078
1618
|
type: "String"
|
|
1619
|
+
/** An optional list of values. This will result in a dropdown list being shown in the Admin UI */
|
|
1079
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
|
+
*/
|
|
1080
1626
|
unique?: boolean
|
|
1081
1627
|
|
|
1628
|
+
/** Specify a fixed length for the field */
|
|
1082
1629
|
length?: number
|
|
1630
|
+
/** Specify a minimum length for the field */
|
|
1083
1631
|
minlength?: number
|
|
1632
|
+
/** Specify a maximum length for the field */
|
|
1084
1633
|
maxlength?: number
|
|
1634
|
+
/** Specify a regex pattern for the field */
|
|
1085
1635
|
pattern?: string
|
|
1086
1636
|
|
|
1637
|
+
/** Set to `true` if the field is an email address. Only validated server-side if `access.serverWriteOnly` is `true` */
|
|
1087
1638
|
email?: boolean
|
|
1639
|
+
/** Set to `true` if the field is a url. Only validated server-side if `access.serverWriteOnly` is `true` */
|
|
1088
1640
|
url?: boolean
|
|
1641
|
+
/** Set to `true` if the field is an emoji. Only validated server-side if `access.serverWriteOnly` is `true` */
|
|
1089
1642
|
emoji?: boolean
|
|
1643
|
+
/** Set to `true` if the field is a UUID. Only validated server-side if `access.serverWriteOnly` is `true` */
|
|
1090
1644
|
uuid?: boolean
|
|
1645
|
+
/** Set to `true` if the field is an IP address. Only validated server-side if `access.serverWriteOnly` is `true` */
|
|
1091
1646
|
ip?: boolean
|
|
1092
1647
|
}
|
|
1093
1648
|
export interface NumberField extends StandardField {
|
|
1094
1649
|
type: "Number"
|
|
1650
|
+
/** An optional list of values. This will result in a dropdown list being shown in the Admin UI */
|
|
1095
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
|
+
*/
|
|
1096
1656
|
unique?: boolean
|
|
1097
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
|
+
*/
|
|
1098
1663
|
autoIncrement?: boolean
|
|
1664
|
+
/** Set the maximum number of decimal places for this field */
|
|
1099
1665
|
decimal?: number
|
|
1100
1666
|
|
|
1667
|
+
/** Set the maximum number value for this field */
|
|
1101
1668
|
max?: number
|
|
1669
|
+
/** Set the minimum number value for this field */
|
|
1102
1670
|
min?: number
|
|
1103
1671
|
}
|
|
1104
1672
|
export interface TimestampField extends StandardField {
|
|
1105
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 */
|
|
1106
1675
|
values?: number[]
|
|
1107
1676
|
|
|
1677
|
+
/** Set the maximum milliseconds value for this field */
|
|
1108
1678
|
max?: number
|
|
1679
|
+
/** Set the minimum milliseconds value for this field */
|
|
1109
1680
|
min?: number
|
|
1110
1681
|
}
|
|
1111
1682
|
export interface ArrayField extends StandardField {
|
|
1112
1683
|
type: "Array"
|
|
1684
|
+
/** A list of values. A dropdown selector will be shown in the Admin UI */
|
|
1113
1685
|
values?: string[]
|
|
1114
1686
|
|
|
1687
|
+
/** Set the exact required length for this field */
|
|
1115
1688
|
length?: number
|
|
1689
|
+
/** Set the minimum length for this field */
|
|
1116
1690
|
minlength?: number
|
|
1691
|
+
/** Set the maximum length for this field */
|
|
1117
1692
|
maxlength?: number
|
|
1118
1693
|
}
|
|
1119
1694
|
export interface MapField extends StandardField {
|
|
@@ -1121,17 +1696,42 @@ export interface MapField extends StandardField {
|
|
|
1121
1696
|
}
|
|
1122
1697
|
export interface RelationField extends StandardField {
|
|
1123
1698
|
type: "OneToOne" | "OneToMany" | "ManyToOne" | "ManyToMany"
|
|
1699
|
+
/** The collection for the relational field */
|
|
1124
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
|
+
*/
|
|
1125
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
|
+
*/
|
|
1126
1711
|
includeFields?: string[]
|
|
1712
|
+
/** Choose one of the `includeFields` values to act as the title field for the related record */
|
|
1127
1713
|
titleField?: string
|
|
1714
|
+
/** Set to `true` to preserve relation data when the related record is deleted. Warning: this may have privacy implications */
|
|
1128
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
|
+
*/
|
|
1129
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
|
+
*/
|
|
1130
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" */
|
|
1131
1727
|
enforceHierarchy?: EnforceHierarchy
|
|
1728
|
+
/** Set the minimum number of relations for this field */
|
|
1132
1729
|
min?: number
|
|
1730
|
+
/** Set the maximum number of relations for this field */
|
|
1133
1731
|
max?: number
|
|
1732
|
+
/** Set the exact number of relations required for this field */
|
|
1134
1733
|
length?: number
|
|
1734
|
+
/** Firestore where() query constraints that will be applied when retrieving records for the dropdown selector */
|
|
1135
1735
|
constraints?: [string, "==" | "in", unknown][]
|
|
1136
1736
|
}
|
|
1137
1737
|
export interface EmbeddingField extends StandardField {
|
|
@@ -1139,9 +1739,15 @@ export interface EmbeddingField extends StandardField {
|
|
|
1139
1739
|
}
|
|
1140
1740
|
export interface ComputedField extends StandardField {
|
|
1141
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
|
+
*/
|
|
1142
1747
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1143
1748
|
formula: (record: StokerRecord, retrieverData?: any) => string | number | Promise<string | number>
|
|
1144
1749
|
}
|
|
1750
|
+
/** A field in a Stoker collection */
|
|
1145
1751
|
export type CollectionField =
|
|
1146
1752
|
| BooleanField
|
|
1147
1753
|
| StringField
|
|
@@ -1153,11 +1759,15 @@ export type CollectionField =
|
|
|
1153
1759
|
| EmbeddingField
|
|
1154
1760
|
| ComputedField
|
|
1155
1761
|
|
|
1762
|
+
/** Make a system field (i.e. `Created_At`, `Last_Write_By`) accessible to the given roles */
|
|
1156
1763
|
export interface RoleSystemField {
|
|
1764
|
+
/** The name of the system field */
|
|
1157
1765
|
field: string
|
|
1766
|
+
/** The roles that can access the field */
|
|
1158
1767
|
roles?: StokerRole[]
|
|
1159
1768
|
}
|
|
1160
1769
|
|
|
1770
|
+
/** The customization (custom code and Admin UI config) for a collection */
|
|
1161
1771
|
export interface CollectionCustomization {
|
|
1162
1772
|
custom?: CollectionCustom
|
|
1163
1773
|
admin?: CollectionAdmin
|
|
@@ -1169,31 +1779,61 @@ export interface CollectionCustomization {
|
|
|
1169
1779
|
}[]
|
|
1170
1780
|
}
|
|
1171
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
|
+
*/
|
|
1172
1786
|
export interface Query {
|
|
1787
|
+
/** The name of the field */
|
|
1173
1788
|
field: string
|
|
1789
|
+
/** Set to `true` if the field is a Timestamp field */
|
|
1174
1790
|
range?: boolean
|
|
1791
|
+
/** Set to `true` if the field needs to be indexed independently of sorting */
|
|
1175
1792
|
standalone?: boolean
|
|
1793
|
+
/** The user roles that will run the query */
|
|
1176
1794
|
roles?: StokerRole[]
|
|
1177
1795
|
}
|
|
1178
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 */
|
|
1179
1798
|
export interface RelationList {
|
|
1799
|
+
/** The collection for the relation list */
|
|
1180
1800
|
collection: StokerCollection
|
|
1801
|
+
/** The field in the current collection that relates to the collection above */
|
|
1181
1802
|
field: string
|
|
1803
|
+
/** The roles that can see this relation list */
|
|
1182
1804
|
roles?: StokerRole[]
|
|
1805
|
+
/** Firestore constraints to apply to the relation list query */
|
|
1183
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 */
|
|
1184
1808
|
loadAll?: boolean
|
|
1809
|
+
/** Show metrics above the list in the Admin UI */
|
|
1185
1810
|
showMetrics?: boolean
|
|
1811
|
+
/** A list of filters to show in the LHS sidebar when the relation list is active */
|
|
1186
1812
|
showFilters?: string[]
|
|
1187
1813
|
}
|
|
1188
1814
|
|
|
1815
|
+
/** The schema for a Stoker collection. Each collection represents a collection in Cloud Firestore, and a page in the Admin UI */
|
|
1189
1816
|
export interface CollectionSchema {
|
|
1817
|
+
/** The names for the collection. Names must start with a capital letter and contain only letters, digits, and underscores */
|
|
1190
1818
|
labels: CollectionLabels
|
|
1819
|
+
/** Access control config for the collection */
|
|
1191
1820
|
access: CollectionAccess
|
|
1821
|
+
/** The fields for the collection */
|
|
1192
1822
|
fields: (CollectionField | RelationField)[]
|
|
1823
|
+
/** The field in the collection that will be used as the record's title, i.e. "Name" */
|
|
1193
1824
|
recordTitleField: string
|
|
1194
1825
|
|
|
1826
|
+
/** Set to `true` if this collection is a "users" collection. Records in the collection can then be assigned access credentials */
|
|
1195
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
|
+
*/
|
|
1196
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
|
+
*/
|
|
1197
1837
|
parentCollection?: StokerCollection
|
|
1198
1838
|
|
|
1199
1839
|
/**
|
|
@@ -1202,34 +1842,80 @@ export interface CollectionSchema {
|
|
|
1202
1842
|
*/
|
|
1203
1843
|
fieldAccessGroups?: Record<string, FieldAccessCondition>
|
|
1204
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
|
+
*/
|
|
1205
1849
|
preloadCache?: PreloadCache
|
|
1850
|
+
/** Enable soft-delete for this collection */
|
|
1206
1851
|
softDelete?: {
|
|
1852
|
+
/** The name of a Boolean field. This field will be set to `true` when the record is soft-deleted */
|
|
1207
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 */
|
|
1208
1855
|
timestampField: string
|
|
1856
|
+
/** The number of days after which soft-deleted records will be permanently deleted */
|
|
1209
1857
|
retentionPeriod: number
|
|
1210
1858
|
}
|
|
1211
1859
|
|
|
1860
|
+
/** Advanced. Define fields that will be indexed for querying. Only relevant if you are using Stoker as a headless CMS */
|
|
1212
1861
|
queries?: Query[]
|
|
1862
|
+
/** Define "child lists" that will appear in the Admin UI for records in this collection */
|
|
1213
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 */
|
|
1214
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
|
+
*/
|
|
1215
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
|
+
*/
|
|
1216
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
|
+
*/
|
|
1217
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
|
+
*/
|
|
1218
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
|
+
*/
|
|
1219
1891
|
indexExemption?: boolean
|
|
1892
|
+
/** Make system fields (i.e. `Created_At`, `Last_Write_By`) accessible to your app's users */
|
|
1220
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
|
+
*/
|
|
1221
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 */
|
|
1222
1901
|
ai?: {
|
|
1902
|
+
/** Set to `true` to save embeddings for records in this collection. Requires the `custom.setEmbedding` hook */
|
|
1223
1903
|
embedding?: boolean
|
|
1224
1904
|
chat?: {
|
|
1905
|
+
/** The name for the chat bot */
|
|
1225
1906
|
name: string
|
|
1907
|
+
/** The number of records the LLM should retrieve for context */
|
|
1226
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 */
|
|
1227
1910
|
roles: StokerRole[]
|
|
1228
1911
|
}
|
|
1229
1912
|
}
|
|
1913
|
+
/** The priority of this collection when seeding test data using `stoker seed-data` */
|
|
1230
1914
|
seedOrder?: number
|
|
1231
1915
|
|
|
1916
|
+
/** Custom code config for the collection, including hooks and server access control */
|
|
1232
1917
|
custom?: CollectionCustom
|
|
1918
|
+
/** Admin UI config for the collection */
|
|
1233
1919
|
admin?: CollectionAdmin
|
|
1234
1920
|
}
|
|
1235
1921
|
|