@tellescope/schema 0.0.7 → 0.0.8
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/lib/cjs/schema.d.ts +138 -1
- package/lib/cjs/schema.d.ts.map +1 -1
- package/lib/cjs/schema.js +153 -166
- package/lib/cjs/schema.js.map +1 -1
- package/lib/esm/schema.d.ts +138 -1
- package/lib/esm/schema.d.ts.map +1 -1
- package/lib/esm/schema.js +154 -167
- package/lib/esm/schema.js.map +1 -1
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +7 -6
- package/src/schema.ts +320 -196
- package/tsconfig.json +1 -1
package/src/schema.ts
CHANGED
|
@@ -1,7 +1,29 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
1
|
+
import {
|
|
2
|
+
ServerModelForName,
|
|
3
|
+
DatabaseModel,
|
|
4
|
+
DatabaseRecord,
|
|
5
|
+
Enduser,
|
|
6
|
+
ObjectId,
|
|
7
|
+
ModelName,
|
|
8
|
+
} from "@tellescope/types-server"
|
|
9
|
+
import {
|
|
10
|
+
ErrorInfo,
|
|
11
|
+
Indexable,
|
|
12
|
+
Operation,
|
|
13
|
+
JSONType,
|
|
14
|
+
CRUD,
|
|
15
|
+
HTTPMethod,
|
|
16
|
+
} from "@tellescope/types-utilities"
|
|
17
|
+
import {
|
|
18
|
+
EnduserSession,
|
|
19
|
+
ConfiguredSession,
|
|
20
|
+
JourneyState,
|
|
21
|
+
UserSession,
|
|
22
|
+
} from "@tellescope/types-models"
|
|
3
23
|
|
|
4
24
|
import {
|
|
25
|
+
EscapeBuilder,
|
|
26
|
+
|
|
5
27
|
booleanValidator,
|
|
6
28
|
dateValidator,
|
|
7
29
|
emailValidator,
|
|
@@ -33,6 +55,8 @@ import {
|
|
|
33
55
|
stringValidator250,
|
|
34
56
|
stringValidator5000,
|
|
35
57
|
listOfDisplayNameInfo,
|
|
58
|
+
fileTypeValidator,
|
|
59
|
+
fileSizeValidator,
|
|
36
60
|
} from "@tellescope/validation"
|
|
37
61
|
|
|
38
62
|
import {
|
|
@@ -40,123 +64,126 @@ import {
|
|
|
40
64
|
DEFAULT_OPERATIONS,
|
|
41
65
|
PLACEHOLDER_ID,
|
|
42
66
|
} from "@tellescope/constants"
|
|
67
|
+
export type RelationshipConstraint<T> = {
|
|
68
|
+
explanation: string; // human readable, for documentation purposes
|
|
69
|
+
evaluate: (v: T, dependencies: Indexable<Partial<DatabaseModel>>) => string | void;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export type DependencyAccessConstraint <T> = { type: 'dependency', foreignModel: ModelName, foreignField: string, accessField: keyof T }
|
|
73
|
+
|
|
74
|
+
export type AccessConstraint <T> = { type: 'creatorOnly' }
|
|
75
|
+
| { type: 'filter', field: string }
|
|
76
|
+
| DependencyAccessConstraint<T>
|
|
77
|
+
|
|
78
|
+
export type UniqueArrayConstraint <T> = { array: keyof T, itemKey?: string }
|
|
79
|
+
|
|
80
|
+
export type Constraint <T> = {
|
|
81
|
+
unique: (keyof T & string | UniqueArrayConstraint<T>)[];
|
|
82
|
+
globalUnique?: (keyof T)[];
|
|
83
|
+
relationship: RelationshipConstraint<Partial<T>>[];
|
|
84
|
+
access?: AccessConstraint<T>[];
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export type Initializer <T, R> = (a: T, s: ConfiguredSession | EnduserSession) => R
|
|
88
|
+
|
|
89
|
+
export type EndpointOptions = {
|
|
90
|
+
// parameters used for endpoint that aren't stored in the model
|
|
91
|
+
parameters?: { [index: string]: EscapeBuilder<any> },
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export type DependencyDeletionAction = 'delete' | 'unset' | 'setNull' | 'nop'
|
|
95
|
+
export type DependecyRelationship = 'foreignKey' | 'value'
|
|
96
|
+
|
|
97
|
+
export type Dependency <T=DatabaseRecord> = {
|
|
98
|
+
dependsOn: ModelName[], // list of => OR, multiple dependency records => AND
|
|
99
|
+
dependencyField: string,
|
|
100
|
+
relationship: DependecyRelationship,
|
|
101
|
+
onDependencyDelete: DependencyDeletionAction,
|
|
102
|
+
getDependentValues?: (t: T) => JSONType[], // for accessing the values of a Dependency
|
|
103
|
+
filterByDependency?: (foreignValue: JSONType, foreignModel?: DatabaseModel) => { // for filtering against a Dependency
|
|
104
|
+
field: string,
|
|
105
|
+
value: JSONType | 'any',
|
|
106
|
+
},
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export type ModelFieldInfo <T, R> = {
|
|
110
|
+
validator: EscapeBuilder<R>,
|
|
111
|
+
readonly?: boolean,
|
|
112
|
+
required?: boolean,
|
|
113
|
+
updatesDisabled?: boolean,
|
|
114
|
+
examples?: JSONType[],
|
|
115
|
+
initializer?: Initializer<Partial<T>, R>, // should include the required fields of T, not just partial
|
|
116
|
+
dependencies?: Dependency<Partial<T>>[],
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export type ModelFields<T> = {
|
|
120
|
+
[K in keyof T]: ModelFieldInfo<T, T[K]>
|
|
121
|
+
}
|
|
122
|
+
export type extractFields<Type> = Type extends ModelFields<infer X> ? X : never
|
|
123
|
+
|
|
124
|
+
type ArgumentInfo = {
|
|
125
|
+
description?: string;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
type ActionInfo = {
|
|
129
|
+
name?: string,
|
|
130
|
+
description?: string,
|
|
131
|
+
notes?: string[],
|
|
132
|
+
warnings?: string[],
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
type CustomAction <P=any, R=any> = {
|
|
136
|
+
op: Operation | 'custom',
|
|
137
|
+
access: CRUD,
|
|
138
|
+
// parameters: InputValidation<P>,
|
|
139
|
+
parameters: ModelFields<P>,
|
|
140
|
+
returns: R extends Array<any> ? ModelFieldInfo<any, R> : ModelFields<R>,
|
|
141
|
+
path?: string,
|
|
142
|
+
method?: HTTPMethod,
|
|
143
|
+
enduserOnly?: boolean,
|
|
144
|
+
} & ActionInfo
|
|
145
|
+
|
|
146
|
+
export type EnduserAction = {
|
|
147
|
+
field?: string,
|
|
148
|
+
} & ActionInfo
|
|
149
|
+
|
|
150
|
+
type CustomActionsForModel = {
|
|
151
|
+
[K in ModelName]: { [index: string]: CustomAction }
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
type ReadFilter <T> = { [K in keyof T]?: { required: boolean } }
|
|
43
155
|
|
|
44
|
-
|
|
45
|
-
//
|
|
46
|
-
//
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
// dependsOn: ModelName[], // list of => OR, multiple dependency records => AND
|
|
76
|
-
// dependencyField: string,
|
|
77
|
-
// relationship: DependecyRelationship,
|
|
78
|
-
// onDependencyDelete: DependencyDeletionAction,
|
|
79
|
-
// getDependentValues?: (t: T) => JSONType[], // for accessing the values of a Dependency
|
|
80
|
-
// filterByDependency?: (foreignValue: JSONType, foreignModel?: DatabaseModel) => { // for filtering against a Dependency
|
|
81
|
-
// field: string,
|
|
82
|
-
// value: JSONType | 'any',
|
|
83
|
-
// },
|
|
84
|
-
// }
|
|
85
|
-
|
|
86
|
-
// type ModelFieldInfo <T, R> = {
|
|
87
|
-
// validator: EscapeBuilder<R>,
|
|
88
|
-
// readonly?: boolean,
|
|
89
|
-
// required?: boolean,
|
|
90
|
-
// updatesDisabled?: boolean,
|
|
91
|
-
// examples?: JSONType[],
|
|
92
|
-
// initializer?: Initializer<Partial<T>, R>, // should include the required fields of T, not just partial
|
|
93
|
-
// dependencies?: Dependency<Partial<T>>[],
|
|
94
|
-
// }
|
|
95
|
-
|
|
96
|
-
// export type ModelFields<T> = {
|
|
97
|
-
// [K in keyof T]: ModelFieldInfo<T, T[K]>
|
|
98
|
-
// }
|
|
99
|
-
// type extractFields<Type> = Type extends ModelFields<infer X> ? X : never
|
|
100
|
-
|
|
101
|
-
// type ArgumentInfo = {
|
|
102
|
-
// description?: string;
|
|
103
|
-
// }
|
|
104
|
-
|
|
105
|
-
// type ActionInfo = {
|
|
106
|
-
// name?: string,
|
|
107
|
-
// description?: string,
|
|
108
|
-
// notes?: string[],
|
|
109
|
-
// warnings?: string[],
|
|
110
|
-
// }
|
|
111
|
-
|
|
112
|
-
// type CustomAction <P=any, R=any> = {
|
|
113
|
-
// op: Operation | 'custom',
|
|
114
|
-
// access: CRUD,
|
|
115
|
-
// // parameters: InputValidation<P>,
|
|
116
|
-
// parameters: ModelFields<P>,
|
|
117
|
-
// returns: ModelFields<R>,
|
|
118
|
-
// path?: string,
|
|
119
|
-
// method?: HTTPMethod,
|
|
120
|
-
// } & ActionInfo
|
|
121
|
-
|
|
122
|
-
// type CustomActionsForModel = {
|
|
123
|
-
// [K in ModelName]: { [index: string]: CustomAction }
|
|
124
|
-
// }
|
|
125
|
-
|
|
126
|
-
// type ReadFilter <T> = { [K in keyof T]?: { required: boolean } }
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
// // m is the original model (or undefined, if create)
|
|
130
|
-
// // allows for easier event handling based on specific updates (by comparing args to pre-update model)
|
|
131
|
-
// type SideEffectHandler <T, O=any> = (args: Partial<T>[], m: (Partial<T> | undefined)[] | undefined, n: (Partial<T> & { _id: ObjectId })[], s: ConfiguredSession, o: O) => Promise<ErrorInfo[]>;
|
|
132
|
-
|
|
133
|
-
// type SideEffect = {
|
|
134
|
-
// name: string;
|
|
135
|
-
// description: string;
|
|
136
|
-
// }
|
|
137
|
-
|
|
138
|
-
// export type Model<T, N extends ModelName> = {
|
|
139
|
-
// info: {
|
|
140
|
-
// name?: string,
|
|
141
|
-
// description?: string,
|
|
142
|
-
// sideEffects?: { [K in Operation]?: SideEffect[] }
|
|
143
|
-
// },
|
|
144
|
-
// fields: ModelFields<T>,
|
|
145
|
-
// constraints: Constraint<T>,
|
|
146
|
-
// defaultActions: { [K in Operation]?: ActionInfo },
|
|
147
|
-
// customActions: CustomActionsForModel[N],
|
|
148
|
-
// readFilter?: ReadFilter<T>,
|
|
149
|
-
// options?: {
|
|
150
|
-
// create?: EndpointOptions,
|
|
151
|
-
// }
|
|
152
|
-
// }
|
|
153
|
-
// type extractModelType<Type> = Type extends Model<infer T, infer N> ? T : never
|
|
154
|
-
|
|
155
|
-
// type DatabaseModelForName = ToServerModels<ModelForName>
|
|
156
|
-
|
|
157
|
-
// type Schema = {
|
|
158
|
-
// [N in keyof DatabaseModelForName]: Model<DatabaseModelForName[N], ModelName>
|
|
159
|
-
// }
|
|
156
|
+
|
|
157
|
+
// m is the original model (or undefined, if create)
|
|
158
|
+
// allows for easier event handling based on specific updates (by comparing args to pre-update model)
|
|
159
|
+
export type SideEffectHandler <T, O=any> = (args: Partial<T>[], m: (Partial<T> | undefined)[] | undefined, n: (Partial<T> & { _id: ObjectId })[], s: ConfiguredSession | EnduserSession, o: O) => Promise<ErrorInfo[]>;
|
|
160
|
+
|
|
161
|
+
type SideEffect = {
|
|
162
|
+
name: string;
|
|
163
|
+
description: string;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
export type Model<T, N extends ModelName> = {
|
|
167
|
+
info: {
|
|
168
|
+
name?: string,
|
|
169
|
+
description?: string,
|
|
170
|
+
sideEffects?: { [K in Operation]?: SideEffect[] }
|
|
171
|
+
},
|
|
172
|
+
fields: ModelFields<T>,
|
|
173
|
+
constraints: Constraint<T>,
|
|
174
|
+
defaultActions: { [k in Operation]?: ActionInfo },
|
|
175
|
+
enduserActions?: { [index: string]: EnduserAction },
|
|
176
|
+
customActions: CustomActionsForModel[N],
|
|
177
|
+
readFilter?: ReadFilter<T>,
|
|
178
|
+
options?: {
|
|
179
|
+
create?: EndpointOptions,
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
export type extractModelType<Type> = Type extends Model<infer T, infer N> ? T : never
|
|
183
|
+
|
|
184
|
+
export type Schema = {
|
|
185
|
+
[N in keyof ServerModelForName]: Model<ServerModelForName[N], ModelName>
|
|
186
|
+
}
|
|
160
187
|
|
|
161
188
|
const sideEffects = {
|
|
162
189
|
trackJourneyEngagement: {
|
|
@@ -203,7 +230,11 @@ export type BuiltInFields_T = typeof BuiltInFields
|
|
|
203
230
|
export type CustomActions = {
|
|
204
231
|
api_keys: {
|
|
205
232
|
create: CustomAction<{}, { id: string, key: string}>,
|
|
206
|
-
}
|
|
233
|
+
},
|
|
234
|
+
files: {
|
|
235
|
+
prepare_file_upload: CustomAction<{ name: string, size: number, type: string }, { presignedUpload: object, file: File }>,
|
|
236
|
+
file_download_URL: CustomAction<{ secureName: string }, { downloadURL: string }>,
|
|
237
|
+
},
|
|
207
238
|
journeys: {
|
|
208
239
|
update_state: CustomAction<{ updates: JourneyState, id: string, name: string }, {}>,
|
|
209
240
|
},
|
|
@@ -246,72 +277,26 @@ export const schema: SchemaV1 = {
|
|
|
246
277
|
update: [sideEffects.trackJourneyEngagement],
|
|
247
278
|
}
|
|
248
279
|
},
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
},
|
|
261
|
-
is_authenticated: {
|
|
262
|
-
op: "custom", access: 'read', method: "get",
|
|
263
|
-
name: 'Check enduser authentication',
|
|
264
|
-
path: '/enduser-is-authenticated',
|
|
265
|
-
description: "Checks the validity of an enduser's authToken",
|
|
266
|
-
parameters: {
|
|
267
|
-
id: { validator: mongoIdStringValidator, required: true },
|
|
268
|
-
authToken: { validator: stringValidator5000, required: true },
|
|
269
|
-
},
|
|
270
|
-
returns: {
|
|
271
|
-
isAuthenticated: { validator: booleanValidator, required: true },
|
|
272
|
-
enduser: { validator: 'enduser' },
|
|
273
|
-
} as any // add enduser eventually, when validator defined
|
|
274
|
-
},
|
|
275
|
-
refresh_session: {
|
|
276
|
-
op: "custom", access: 'update', method: "post",
|
|
277
|
-
name: 'Refresh enduser authentication',
|
|
278
|
-
path: '/refresh-enduser-session',
|
|
279
|
-
description: "When called by an authenticated enduser, generates a new session",
|
|
280
|
-
parameters: { },
|
|
281
|
-
enduserOnly: true,
|
|
282
|
-
returns: {
|
|
283
|
-
authToken: { validator: stringValidator, required: true },
|
|
284
|
-
enduser: { validator: 'enduser' },
|
|
285
|
-
} as any // add enduser eventually, when validator defined
|
|
286
|
-
},
|
|
287
|
-
logout: {
|
|
288
|
-
op: "custom", access: 'update', method: "post",
|
|
289
|
-
name: 'Logout enduser',
|
|
290
|
-
path: '/logout-enduser',
|
|
291
|
-
description: "Logs out an enduser",
|
|
292
|
-
parameters: {},
|
|
293
|
-
returns: {},
|
|
294
|
-
},
|
|
280
|
+
constraints: {
|
|
281
|
+
unique: ['email', 'phone', 'externalId'],
|
|
282
|
+
relationship: [
|
|
283
|
+
{
|
|
284
|
+
explanation: 'One of email or phone is required',
|
|
285
|
+
evaluate: ({ email, phone }) => {
|
|
286
|
+
if (!(email || phone))
|
|
287
|
+
return 'One of email or phone is required'
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
],
|
|
295
291
|
},
|
|
292
|
+
defaultActions: DEFAULT_OPERATIONS,
|
|
296
293
|
enduserActions: { logout: {}, refresh_session: {} },
|
|
297
|
-
publicActions: {
|
|
298
|
-
login: {
|
|
299
|
-
op: "custom", access: 'read', method: "post",
|
|
300
|
-
name: 'Login enduser',
|
|
301
|
-
path: '/login-enduser',
|
|
302
|
-
description: "Generates an authentication token for access to enduser-facing endpoints",
|
|
303
|
-
enduserOnly: true, // implemented as authenticate in enduser sdk only
|
|
304
|
-
parameters: {
|
|
305
|
-
id: { validator: mongoIdStringValidator },
|
|
306
|
-
password: { validator: stringValidator100, required: true }, // required until optional challenge token available
|
|
307
|
-
phone: { validator: phoneValidator },
|
|
308
|
-
email: { validator: emailValidator },
|
|
309
|
-
},
|
|
310
|
-
returns: { authToken: { validator: stringValidator5000 } },
|
|
311
|
-
},
|
|
312
|
-
},
|
|
313
294
|
fields: {
|
|
314
295
|
...BuiltInFields,
|
|
296
|
+
externalId: {
|
|
297
|
+
validator: stringValidator250,
|
|
298
|
+
examples: ['addfed3e-ddea-415b-b52b-df820c944dbb'],
|
|
299
|
+
},
|
|
315
300
|
email: {
|
|
316
301
|
validator: emailValidator,
|
|
317
302
|
examples: ['test@tellescope.com'],
|
|
@@ -374,23 +359,84 @@ export const schema: SchemaV1 = {
|
|
|
374
359
|
lastCommunication: {
|
|
375
360
|
validator: dateValidator,
|
|
376
361
|
},
|
|
362
|
+
avatar: {
|
|
363
|
+
validator: stringValidator100,
|
|
364
|
+
dependencies: [
|
|
365
|
+
{
|
|
366
|
+
dependsOn: ['files'],
|
|
367
|
+
dependencyField: 'secureName',
|
|
368
|
+
relationship: 'foreignKey',
|
|
369
|
+
onDependencyDelete: 'unset',
|
|
370
|
+
},
|
|
371
|
+
]
|
|
372
|
+
},
|
|
377
373
|
// recentMessagePreview: {
|
|
378
374
|
// validator: stringValidator,
|
|
379
375
|
// },
|
|
380
376
|
},
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
}
|
|
390
|
-
}
|
|
391
|
-
|
|
377
|
+
customActions: {
|
|
378
|
+
set_password: {
|
|
379
|
+
op: "custom", access: 'update', method: "post",
|
|
380
|
+
name: 'Set enduser password',
|
|
381
|
+
path: '/set-enduser-password',
|
|
382
|
+
description: "Sets (or resets) an enduser's password. Minimum length 8 characters.",
|
|
383
|
+
parameters: {
|
|
384
|
+
id: { validator: mongoIdStringValidator, required: true },
|
|
385
|
+
password: { validator: stringValidator100, required: true },
|
|
386
|
+
},
|
|
387
|
+
returns: { } //authToken: { validator: stringValidator5000 } },
|
|
388
|
+
},
|
|
389
|
+
is_authenticated: {
|
|
390
|
+
op: "custom", access: 'read', method: "get",
|
|
391
|
+
name: 'Check enduser authentication',
|
|
392
|
+
path: '/enduser-is-authenticated',
|
|
393
|
+
description: "Checks the validity of an enduser's authToken",
|
|
394
|
+
parameters: {
|
|
395
|
+
id: { validator: mongoIdStringValidator, required: true },
|
|
396
|
+
authToken: { validator: stringValidator5000, required: true },
|
|
397
|
+
},
|
|
398
|
+
returns: {
|
|
399
|
+
isAuthenticated: { validator: booleanValidator, required: true },
|
|
400
|
+
enduser: { validator: 'enduser' },
|
|
401
|
+
} as any // todo: add enduser eventually, when validator defined
|
|
402
|
+
},
|
|
403
|
+
refresh_session: {
|
|
404
|
+
op: "custom", access: 'update', method: "post",
|
|
405
|
+
name: 'Refresh enduser authentication',
|
|
406
|
+
path: '/refresh-enduser-session',
|
|
407
|
+
description: "When called by an authenticated enduser, generates a new session",
|
|
408
|
+
parameters: { },
|
|
409
|
+
enduserOnly: true,
|
|
410
|
+
returns: {
|
|
411
|
+
authToken: { validator: stringValidator, required: true },
|
|
412
|
+
enduser: { validator: 'enduser' },
|
|
413
|
+
} as any // todo: add enduser eventually, when validator defined
|
|
414
|
+
},
|
|
415
|
+
logout: {
|
|
416
|
+
op: "custom", access: 'update', method: "post",
|
|
417
|
+
name: 'Logout enduser',
|
|
418
|
+
path: '/logout-enduser',
|
|
419
|
+
description: "Logs out an enduser",
|
|
420
|
+
parameters: {},
|
|
421
|
+
returns: {},
|
|
422
|
+
},
|
|
423
|
+
},
|
|
424
|
+
publicActions: {
|
|
425
|
+
login: {
|
|
426
|
+
op: "custom", access: 'read', method: "post",
|
|
427
|
+
name: 'Login enduser',
|
|
428
|
+
path: '/login-enduser',
|
|
429
|
+
description: "Generates an authentication token for access to enduser-facing endpoints",
|
|
430
|
+
enduserOnly: true, // implemented as authenticate in enduser sdk only
|
|
431
|
+
parameters: {
|
|
432
|
+
id: { validator: mongoIdStringValidator },
|
|
433
|
+
password: { validator: stringValidator100, required: true }, // required until optional challenge token available
|
|
434
|
+
phone: { validator: phoneValidator },
|
|
435
|
+
email: { validator: emailValidator },
|
|
436
|
+
},
|
|
437
|
+
returns: { authToken: { validator: stringValidator5000 } },
|
|
438
|
+
},
|
|
392
439
|
},
|
|
393
|
-
defaultActions: DEFAULT_OPERATIONS,
|
|
394
440
|
},
|
|
395
441
|
api_keys: {
|
|
396
442
|
info: {},
|
|
@@ -608,7 +654,7 @@ export const schema: SchemaV1 = {
|
|
|
608
654
|
validator: mongoIdStringValidator,
|
|
609
655
|
examples: [PLACEHOLDER_ID],
|
|
610
656
|
readonly: true,
|
|
611
|
-
initializer: (a, s) => (s as UserSession).
|
|
657
|
+
initializer: (a, s) => (s as UserSession).id,
|
|
612
658
|
},
|
|
613
659
|
subject: {
|
|
614
660
|
validator: stringValidator,
|
|
@@ -728,7 +774,7 @@ export const schema: SchemaV1 = {
|
|
|
728
774
|
businessUserId: {
|
|
729
775
|
validator: mongoIdStringValidator,
|
|
730
776
|
readonly: true, // default to only self-sending, for now
|
|
731
|
-
initializer: (a, s) => (s as UserSession).
|
|
777
|
+
initializer: (a, s) => (s as UserSession).id,
|
|
732
778
|
dependencies: [{
|
|
733
779
|
dependsOn: ['users'],
|
|
734
780
|
dependencyField: '_id',
|
|
@@ -845,7 +891,7 @@ export const schema: SchemaV1 = {
|
|
|
845
891
|
senderId: {
|
|
846
892
|
validator: mongoIdStringValidator,
|
|
847
893
|
readonly: true, // create a separate endpoint for storing enduser chats
|
|
848
|
-
initializer: (a, s) => (s as UserSession).
|
|
894
|
+
initializer: (a, s) => (s as UserSession).id ?? (s as EnduserSession).id,
|
|
849
895
|
examples: [PLACEHOLDER_ID],
|
|
850
896
|
dependencies: [{ // can be userId or enduserId
|
|
851
897
|
dependsOn: ['users', 'endusers'],
|
|
@@ -939,6 +985,17 @@ export const schema: SchemaV1 = {
|
|
|
939
985
|
roles: {
|
|
940
986
|
validator: listOfStringsValidator,
|
|
941
987
|
},
|
|
988
|
+
avatar: {
|
|
989
|
+
validator: stringValidator100,
|
|
990
|
+
dependencies: [
|
|
991
|
+
{
|
|
992
|
+
dependsOn: ['files'],
|
|
993
|
+
dependencyField: 'secureName',
|
|
994
|
+
relationship: 'foreignKey',
|
|
995
|
+
onDependencyDelete: 'unset',
|
|
996
|
+
},
|
|
997
|
+
]
|
|
998
|
+
},
|
|
942
999
|
}
|
|
943
1000
|
},
|
|
944
1001
|
templates: {
|
|
@@ -971,5 +1028,72 @@ export const schema: SchemaV1 = {
|
|
|
971
1028
|
initializer: () => 'enduser'
|
|
972
1029
|
},
|
|
973
1030
|
}
|
|
1031
|
+
},
|
|
1032
|
+
files: {
|
|
1033
|
+
info: {},
|
|
1034
|
+
constraints: { unique: [], relationship: [] },
|
|
1035
|
+
defaultActions: { read: {}, readMany: {}, update: {} },
|
|
1036
|
+
fields: {
|
|
1037
|
+
...BuiltInFields,
|
|
1038
|
+
name: {
|
|
1039
|
+
validator: stringValidator250,
|
|
1040
|
+
required: true,
|
|
1041
|
+
},
|
|
1042
|
+
size: {
|
|
1043
|
+
validator: fileSizeValidator,
|
|
1044
|
+
required: true,
|
|
1045
|
+
},
|
|
1046
|
+
type: {
|
|
1047
|
+
validator: fileTypeValidator,
|
|
1048
|
+
required: true
|
|
1049
|
+
},
|
|
1050
|
+
secureName: {
|
|
1051
|
+
validator: stringValidator250,
|
|
1052
|
+
readonly: true,
|
|
1053
|
+
},
|
|
1054
|
+
},
|
|
1055
|
+
enduserActions: { prepare_file_upload: {} },
|
|
1056
|
+
customActions: {
|
|
1057
|
+
prepare_file_upload: {
|
|
1058
|
+
op: "custom", access: 'create', method: "post",
|
|
1059
|
+
name: 'Prepare File Upload',
|
|
1060
|
+
path: '/prepare-file-upload',
|
|
1061
|
+
description: "Generates an upload link for a file, storing metadata as a File record.",
|
|
1062
|
+
parameters: {
|
|
1063
|
+
name: {
|
|
1064
|
+
validator: stringValidator250,
|
|
1065
|
+
required: true,
|
|
1066
|
+
},
|
|
1067
|
+
size: {
|
|
1068
|
+
validator: fileSizeValidator,
|
|
1069
|
+
required: true,
|
|
1070
|
+
},
|
|
1071
|
+
type: {
|
|
1072
|
+
validator: fileTypeValidator,
|
|
1073
|
+
required: true
|
|
1074
|
+
},
|
|
1075
|
+
},
|
|
1076
|
+
returns: {
|
|
1077
|
+
presignedUpload: {
|
|
1078
|
+
validator: objectAnyFieldsValidator,
|
|
1079
|
+
},
|
|
1080
|
+
file: {
|
|
1081
|
+
validator: 'file' as any, // todo: add file validator
|
|
1082
|
+
},
|
|
1083
|
+
},
|
|
1084
|
+
},
|
|
1085
|
+
file_download_URL: {
|
|
1086
|
+
op: "custom", access: 'read', method: "get",
|
|
1087
|
+
name: 'Generate File Download',
|
|
1088
|
+
path: '/file-download-link',
|
|
1089
|
+
description: "Generates a temporary download link for a file.",
|
|
1090
|
+
parameters: {
|
|
1091
|
+
secureName: { validator: stringValidator250 },
|
|
1092
|
+
},
|
|
1093
|
+
returns: {
|
|
1094
|
+
downloadURL: { validator: stringValidator250 },
|
|
1095
|
+
},
|
|
1096
|
+
},
|
|
1097
|
+
},
|
|
974
1098
|
}
|
|
975
1099
|
}
|