@tellescope/schema 1.3.48 → 1.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/schema.ts CHANGED
@@ -31,6 +31,7 @@ import {
31
31
  MeetingInfo,
32
32
  PreviousFormField,
33
33
  OrganizationTheme,
34
+ AvailabilityBlock,
34
35
  } from "@tellescope/types-models"
35
36
 
36
37
  import {
@@ -47,7 +48,7 @@ import {
47
48
  } from "@tellescope/types-client"
48
49
 
49
50
  import {
50
- EscapeBuilder,
51
+ ValidatorDefinition,
51
52
 
52
53
  booleanValidator,
53
54
  dateValidator,
@@ -59,7 +60,7 @@ import {
59
60
  nameValidator,
60
61
  nonNegNumberValidator,
61
62
  mongoIdValidator,
62
- mongoIdStringValidator,
63
+ mongoIdStringRequired as mongoIdStringValidator,
63
64
  listOfMongoIdStringValidator,
64
65
  preferenceValidator,
65
66
  objectAnyFieldsAnyValuesValidator,
@@ -99,7 +100,6 @@ import {
99
100
  listOfCalendarEventRemindersValidator,
100
101
  messageTemplateModeValidator,
101
102
  listOfAutomationConditionsValidator,
102
- journeyStateUpdateValidator,
103
103
  chatRoomUserInfoValidator,
104
104
  CUDStringValidator,
105
105
  listOfRelatedRecordsValidator,
@@ -123,7 +123,7 @@ import {
123
123
  sessionTypeValidator,
124
124
  portalSettingsValidator,
125
125
  emailValidatorEmptyOkay,
126
- phoneValidatorEmptyOkay,
126
+ phoneValidatorOptional,
127
127
  stringValidator1000,
128
128
  databaseFieldsValidator,
129
129
  databaseRecordValuesValidator,
@@ -132,6 +132,11 @@ import {
132
132
  portalBlocksValidator,
133
133
  enduserFormResponsesForEventValidator,
134
134
  enduserTasksForEventValidator,
135
+ stateCredentialsValidator,
136
+ stateValidator,
137
+ availabilityBlocksValidator,
138
+ weeklyAvailabilitiesValidator,
139
+ timezoneValidator,
135
140
  } from "@tellescope/validation"
136
141
 
137
142
  import {
@@ -143,9 +148,18 @@ import {
143
148
  } from "@tellescope/constants"
144
149
  import { response } from "express"
145
150
 
151
+ export type RelationshipConstraintOptions<T> = {
152
+ updates?: Partial<T>
153
+ }
146
154
  export type RelationshipConstraint<T> = {
147
155
  explanation: string; // human readable, for documentation purposes
148
- evaluate: (v: T, dependencies: Indexable<Partial<DatabaseModel>>, session: UserSession | EnduserSession, method: 'create' | 'update') => string | void;
156
+ evaluate: (
157
+ v: T,
158
+ dependencies: Indexable<Partial<DatabaseModel>>,
159
+ session: UserSession | EnduserSession,
160
+ method: 'create' | 'update',
161
+ options: RelationshipConstraintOptions<T>,
162
+ ) => string | void;
149
163
  }
150
164
 
151
165
  export type DependencyAccessConstraint <T> = { type: 'dependency', foreignModel: ModelName, foreignField: string, accessField: keyof T }
@@ -170,7 +184,7 @@ export type Initializer <T, R> = (a: T, s: UserSession | EnduserSession) => R
170
184
 
171
185
  export type EndpointOptions = {
172
186
  // parameters used for endpoint that aren't stored in the model
173
- parameters?: { [index: string]: EscapeBuilder<any> },
187
+ parameters?: { [index: string]: ValidatorDefinition<any> },
174
188
  }
175
189
 
176
190
  export type DependencyDeletionAction = 'delete' | 'unset' | 'setNull' | 'nop'
@@ -193,7 +207,7 @@ export type RedactionReason = (
193
207
  )
194
208
 
195
209
  export type ModelFieldInfo <T, R> = {
196
- validator: EscapeBuilder<R>,
210
+ validator: ValidatorDefinition<R>,
197
211
  readonly?: boolean,
198
212
  required?: boolean,
199
213
  updatesDisabled?: boolean,
@@ -361,7 +375,7 @@ export type CustomActions = {
361
375
  }>,
362
376
  },
363
377
  journeys: {
364
- update_state: CustomAction<{ updates: Partial<JourneyState>, id: string, name: string }, { updated: Journey }>,
378
+ // update_state: CustomAction<{ updates: Partial<JourneyState>, id: string, name: string }, { updated: Journey }>,
365
379
  delete_states: CustomAction<{ id: string, states: string[] }, { updated: Journey }>,
366
380
  },
367
381
  endusers: {
@@ -424,7 +438,17 @@ export type CustomActions = {
424
438
  sync_integrations: CustomAction<{ enduserEmail: string }, { newEmails: Email[] }>,
425
439
  },
426
440
  calendar_events: {
427
- get_external_events_for_user: CustomAction<{ userId: string, from: Date, limit?: number }, { events: CalendarEvent[] }>,
441
+ get_events_for_user: CustomAction<{ userId: string, from: Date, to?: Date, limit?: number }, { events: CalendarEvent[] }>,
442
+ get_appointment_availability: CustomAction<{
443
+ from: Date, calendarEventTemplateId: string, to?: Date, restrictedByState?: boolean, limit?: number,
444
+ }, {
445
+ availabilityBlocks: AvailabilityBlock[],
446
+ }>,
447
+ book_appointment: CustomAction<{
448
+ userId: string, startTime: Date, calendarEventTemplateId: string,
449
+ }, {
450
+ createdEvent: CalendarEvent,
451
+ }>,
428
452
  },
429
453
  }
430
454
 
@@ -475,6 +499,7 @@ export const build_schema = <T extends Schema>(schema: T) => schema
475
499
  export const schema: SchemaV1 = build_schema({
476
500
  endusers: {
477
501
  info: {
502
+ description: "Used to represent patients or other endusers. See Users for managing your team member's accounts.",
478
503
  sideEffects: {
479
504
  create: [sideEffects.handleJourneyStateChange],
480
505
  update: [sideEffects.handleJourneyStateChange],
@@ -529,7 +554,7 @@ export const schema: SchemaV1 = build_schema({
529
554
  redactions: ['enduser'],
530
555
  },
531
556
  phone: {
532
- validator: phoneValidatorEmptyOkay,
557
+ validator: phoneValidatorOptional,
533
558
  examples: ['+14155555555'],
534
559
  redactions: ['enduser'],
535
560
  },
@@ -612,6 +637,7 @@ export const schema: SchemaV1 = build_schema({
612
637
  },
613
638
  ]
614
639
  },
640
+ state: { validator: stateValidator },
615
641
  // recentMessagePreview: {
616
642
  // validator: stringValidator,
617
643
  // },
@@ -966,20 +992,20 @@ export const schema: SchemaV1 = build_schema({
966
992
  },
967
993
  },
968
994
  customActions: {
969
- update_state: {
970
- op: 'custom', access: 'update', method: "patch",
971
- name: 'Update State',
972
- path: '/journey/:id/state/:name',
973
- description: "Updates a state in a journey. Endusers and automations are updated automatically.",
974
- parameters: {
975
- id: { validator: mongoIdStringValidator },
976
- name: { validator: stringValidator100 },
977
- updates: { validator: journeyStateUpdateValidator, required: true },
978
- },
979
- returns: {
980
- updated: { validator: 'journey' as any }
981
- },
982
- },
995
+ // update_state: {
996
+ // op: 'custom', access: 'update', method: "patch",
997
+ // name: 'Update State',
998
+ // path: '/journey/:id/state/:name',
999
+ // description: "Updates a state in a journey. Endusers and automations are updated automatically.",
1000
+ // parameters: {
1001
+ // id: { validator: mongoIdStringValidator },
1002
+ // name: { validator: stringValidator100 },
1003
+ // updates: { validator: journeyStateUpdateValidator, required: true },
1004
+ // },
1005
+ // returns: {
1006
+ // updated: { validator: 'journey' as any }
1007
+ // },
1008
+ // },
983
1009
  delete_states: {
984
1010
  op: 'custom', access: 'update', method: "delete",
985
1011
  name: 'Delete States',
@@ -1461,19 +1487,32 @@ export const schema: SchemaV1 = build_schema({
1461
1487
  },
1462
1488
  },
1463
1489
  users: {
1464
- info: {},
1490
+ info: {
1491
+ description: "Used to represent your team member accounts. See Endusers for representing patients and other types of stakeholders.",
1492
+ },
1465
1493
  constraints: {
1466
1494
  unique: ['username'],
1467
1495
  globalUnique: ['email', 'phone'],
1468
- relationship: [{
1469
- explanation: "Only admin users can update others' profiles",
1470
- evaluate: ({ _id }, _, session) => {
1471
- if (_id && _id.toString() === session.id) return
1472
- if ((session as UserSession)?.roles?.includes('Admin')) return
1496
+ relationship: [
1497
+ {
1498
+ explanation: "Only admin users can update others' profiles",
1499
+ evaluate: ({ _id }, _, session) => {
1500
+ if (_id && _id.toString() === session.id) return
1501
+ if ((session as UserSession)?.roles?.includes('Admin')) return
1473
1502
 
1474
- return "Only admin users can update others' profiles"
1503
+ return "Only admin users can update others' profiles"
1504
+ }
1505
+ }, {
1506
+ explanation: "Only admin users can update user roles",
1507
+ evaluate: ({ roles }, _, session, method, { updates }) => {
1508
+ if ((session as UserSession)?.roles?.includes('Admin')) return // admin can do this
1509
+ if (method === 'create') return // create already admin restricted
1510
+ if (!updates?.roles) return // roles not provided
1511
+
1512
+ return "Only admin users can update others' profiles"
1513
+ }
1475
1514
  }
1476
- }],
1515
+ ],
1477
1516
  },
1478
1517
  defaultActions: {
1479
1518
  create: { adminOnly: true }, createMany: { adminOnly: true }, delete: { adminOnly: true },
@@ -1588,12 +1627,11 @@ export const schema: SchemaV1 = build_schema({
1588
1627
  },
1589
1628
  roles: {
1590
1629
  validator: listOfStringsValidator,
1591
- updatesDisabled: true, // implement with separate endpoint with tight restrictions
1592
1630
  redactions: ['enduser'],
1593
1631
  },
1594
1632
  acknowledgedIntegrations: { validator: dateValidator },
1595
1633
  skills: {
1596
- validator: listOfStringsValidator,
1634
+ validator: listOfStringsValidatorEmptyOk,
1597
1635
  },
1598
1636
  verifiedEmail: {
1599
1637
  updatesDisabled: true, // allow it to be set on creation by admin via API to streamline SSO support
@@ -1619,6 +1657,11 @@ export const schema: SchemaV1 = build_schema({
1619
1657
  },
1620
1658
  ]
1621
1659
  },
1660
+ credentialedStates: {
1661
+ validator: stateCredentialsValidator,
1662
+ },
1663
+ timezone: { validator: timezoneValidator },
1664
+ weeklyAvailabilities: { validator: weeklyAvailabilitiesValidator },
1622
1665
  }
1623
1666
  },
1624
1667
  templates: {
@@ -1681,7 +1724,7 @@ export const schema: SchemaV1 = build_schema({
1681
1724
  validator: fileTypeValidator,
1682
1725
  required: true
1683
1726
  },
1684
- enduserId: {
1727
+ enduserId: { // deleted as side effect of enduser delete
1685
1728
  validator: mongoIdStringValidator,
1686
1729
  },
1687
1730
  secureName: {
@@ -2322,22 +2365,53 @@ export const schema: SchemaV1 = build_schema({
2322
2365
  },
2323
2366
  defaultActions: DEFAULT_OPERATIONS,
2324
2367
  customActions: {
2325
- get_external_events_for_user: {
2368
+ get_events_for_user: {
2326
2369
  op: "custom", access: 'read', method: "get",
2327
- name: 'Get External Events for User',
2328
- path: '/external-events-for-user',
2329
- description: "Gets events from external calendars, formatted as a Tellescope event",
2370
+ name: 'Get Events for User (Including Integrations)',
2371
+ path: '/events-for-user',
2372
+ description: "Combines internal and external events, formatted as a Tellescope events",
2330
2373
  parameters: {
2331
2374
  userId: { validator: mongoIdStringValidator, required: true },
2332
2375
  from: { validator: dateValidator, required: true },
2376
+ to: { validator: dateValidator },
2333
2377
  limit: { validator: nonNegNumberValidator },
2334
2378
  },
2335
2379
  returns: {
2336
2380
  events: { validator: 'calendar_events' as any }
2337
2381
  },
2338
2382
  },
2383
+ get_appointment_availability: {
2384
+ op: "custom", access: 'read', method: "get",
2385
+ name: 'Get Appointment Availability for a Calendar Event Type',
2386
+ path: '/calendar-availability',
2387
+ description: "Gets availability blocks for different users based on their internal and external calendars",
2388
+ parameters: {
2389
+ calendarEventTemplateId: { validator: mongoIdStringValidator, required: true },
2390
+ from: { validator: dateValidator, required: true },
2391
+ restrictedByState: { validator: booleanValidator },
2392
+ to: { validator: dateValidator },
2393
+ limit: { validator: nonNegNumberValidator },
2394
+ },
2395
+ returns: {
2396
+ availabilityBlocks: { validator: availabilityBlocksValidator, required: true }
2397
+ },
2398
+ },
2399
+ book_appointment: {
2400
+ op: "custom", access: 'create', method: "post",
2401
+ name: 'Book Appointment',
2402
+ path: '/book-appointment',
2403
+ description: "Books an appointment with a given user if available",
2404
+ parameters: {
2405
+ calendarEventTemplateId: { validator: mongoIdStringValidator, required: true },
2406
+ userId: { validator: mongoIdStringValidator, required: true },
2407
+ startTime: { validator: dateValidator, required: true },
2408
+ },
2409
+ returns: {
2410
+ createdEvent: { validator: 'calenar_event' as any },
2411
+ },
2412
+ },
2339
2413
  },
2340
- enduserActions: { read: {}, readMany: {} },
2414
+ enduserActions: { read: {}, readMany: {}, get_appointment_availability: {}, book_appointment: {} },
2341
2415
  fields: {
2342
2416
  ...BuiltInFields,
2343
2417
  title: {
@@ -2391,7 +2465,7 @@ export const schema: SchemaV1 = build_schema({
2391
2465
  dependsOn: ['calendar_event_templates'],
2392
2466
  dependencyField: '_id',
2393
2467
  relationship: 'foreignKey',
2394
- onDependencyDelete: 'delete',
2468
+ onDependencyDelete: 'nop',
2395
2469
  }]
2396
2470
  },
2397
2471
  publicRead: { validator: booleanValidator },
@@ -2402,6 +2476,8 @@ export const schema: SchemaV1 = build_schema({
2402
2476
  sharedContentIds: { validator: listOfMongoIdStringValidatorEmptyOk },
2403
2477
  enduserFormResponses: { validator: enduserFormResponsesForEventValidator },
2404
2478
  enduserTasks: { validator: enduserTasksForEventValidator },
2479
+ location: { validator: stringValidator1000 },
2480
+ phone: { validator: stringValidator100 }, // leave more generous than phone validator in favor of lower friction
2405
2481
  }
2406
2482
  },
2407
2483
  calendar_event_templates: {
@@ -3122,7 +3198,7 @@ export const schema: SchemaV1 = build_schema({
3122
3198
  subscriptionPeriod: { validator: numberValidator },
3123
3199
  logoVersion: { validator: numberValidator },
3124
3200
  faviconVersion: { validator: numberValidator },
3125
- roles: { validator: listOfStringsValidator },
3201
+ roles: { validator: listOfStringsValidatorEmptyOk },
3126
3202
  skills: { validator: listOfStringsValidator },
3127
3203
  themeColor: { validator: stringValidator100 },
3128
3204
  customPortalURL: { validator: stringValidator250 },
@@ -3223,6 +3299,7 @@ export const schema: SchemaV1 = build_schema({
3223
3299
  validator: portalBlocksValidator,
3224
3300
  },
3225
3301
  disabled: { validator: booleanValidator },
3302
+ mobileBottomNavigationPosition: { validator: nonNegNumberValidator },
3226
3303
  },
3227
3304
  },
3228
3305
  enduser_tasks: {
@@ -3255,12 +3332,8 @@ export const schema: SchemaV1 = build_schema({
3255
3332
  onDependencyDelete: 'delete',
3256
3333
  }]
3257
3334
  },
3258
- completedAt: {
3259
- validator: dateValidator,
3260
- },
3261
- description: {
3262
- validator: stringValidator1000,
3263
- },
3335
+ completedAt: { validator: dateValidator },
3336
+ description: { validator: stringValidator1000 },
3264
3337
  },
3265
3338
  },
3266
3339
  care_plans: {