@tellescope/schema 1.246.2 → 1.248.0

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
@@ -275,6 +275,7 @@ import {
275
275
  listValidator,
276
276
  userCallRoutingBehaviorValidator,
277
277
  userUIRestrictionsValidator,
278
+ userFieldRedactionsValidator,
278
279
  externalChatGPTMessagesValidator,
279
280
  enduserProfileViewBlocksValidator,
280
281
  customDashboardBlocksValidator,
@@ -384,6 +385,7 @@ export const get_next_reminder_timestamp_for_ticket = ({ dueDateInMS, reminders,
384
385
  export type RelationshipConstraintOptions<T> = {
385
386
  updates?: Partial<T>
386
387
  original?: T,
388
+ replaceObjectFields?: boolean,
387
389
  }
388
390
  export type RelationshipConstraint<T> = {
389
391
  explanation: string; // human readable, for documentation purposes
@@ -994,6 +996,8 @@ export type CustomActions = {
994
996
  update_zoom: CustomAction<{ clientId?: string, clientSecret?: string }, { }>,
995
997
  proxy_read: CustomAction<{ integration: string, type: string, id?: string, query?: string }, { data: any }>,
996
998
  proxy_write: CustomAction<{ integration: string, type: string, id?: string, query?: Record<string, any> }, { data: any }>,
999
+ load_redacted: CustomAction<{}, { integrations: Integration[] }>,
1000
+ update_settings: CustomAction<{ id: string, updates: Partial<Integration> }, { integration: Integration }>,
997
1001
  },
998
1002
  emails: {
999
1003
  sync_integrations: CustomAction<{ enduserEmail: string, allUsers?: boolean }, { newEmails: Email[] }>,
@@ -1052,11 +1056,12 @@ export type CustomActions = {
1052
1056
  get_enduser_report: CustomAction<{ range?: DateRange, groupBy?: string, countDuplicates?: boolean, templateIds?: string[], enduserGroupBy?: string, enduserFields: Record<string, any> }, { report: Report }>,
1053
1057
  // for getting statuses of events (cancelled, rescheduled, etc.)
1054
1058
  get_status_report: CustomAction<{ range?: DateRange, groupBy?: string }, { report: Report }>,
1055
- // bulk operations on recurring event series (cancel for attendee, remove attendee, cancel, delete)
1059
+ // bulk operations on recurring event series or a set of specific events
1056
1060
  bulk_update: CustomAction<
1057
1061
  {
1058
- recurringEventId: string,
1059
- action: 'cancel_for_attendee' | 'remove_attendee' | 'cancel' | 'delete' | 'uncancel_for_attendee' | 'uncancel',
1062
+ recurringEventId?: string,
1063
+ ids?: string[],
1064
+ action: 'cancel_for_attendee' | 'remove_attendee' | 'cancel' | 'delete' | 'uncancel_for_attendee' | 'uncancel' | 'confirm' | 'no_show' | 'un_no_show',
1060
1065
  scope?: 'this_and_future' | 'all',
1061
1066
  enduserId?: string,
1062
1067
  cancelReason?: string,
@@ -1441,6 +1446,17 @@ export const schema: SchemaV1 = build_schema({
1441
1446
 
1442
1447
  return "Enduser organizationIds can only be updated by users"
1443
1448
  }
1449
+ }, {
1450
+ explanation: 'invalidateSessionsBefore can only be set forward in time, never backwards',
1451
+ evaluate: (_v, _deps, _session, method, { updates, original }) => {
1452
+ if (method === 'create') return
1453
+ if (!updates?.invalidateSessionsBefore) return
1454
+ const orig = original as any
1455
+ if (!orig?.invalidateSessionsBefore) return
1456
+ if (new Date(updates.invalidateSessionsBefore) < new Date(orig.invalidateSessionsBefore)) {
1457
+ return "invalidateSessionsBefore can only be set forward in time"
1458
+ }
1459
+ }
1444
1460
  }
1445
1461
  ],
1446
1462
  access: [ // for non-admins, limit access to endusers the user is assigned to, by default
@@ -1571,6 +1587,7 @@ export const schema: SchemaV1 = build_schema({
1571
1587
  validator: dateValidator,
1572
1588
  },
1573
1589
  lastLogout: { validator: dateValidator },
1590
+ invalidateSessionsBefore: { validator: dateValidator },
1574
1591
  termsSigned: { validator: dateValidator },
1575
1592
  termsVersion: { validator: stringValidator100 },
1576
1593
  lastCommunication: {
@@ -2506,6 +2523,32 @@ export const schema: SchemaV1 = build_schema({
2506
2523
  next_page_token: { validator: stringValidator }
2507
2524
  },
2508
2525
  },
2526
+ load_redacted: {
2527
+ op: 'custom', access: 'read', method: 'get',
2528
+ path: '/integrations/load-redacted',
2529
+ name: 'Load Redacted Integrations',
2530
+ description: "Loads all integrations for the organization with sensitive fields removed",
2531
+ parameters: {},
2532
+ returns: {
2533
+ integrations: {
2534
+ validator: listValidatorEmptyOk(optionalAnyObjectValidator as any),
2535
+ required: true,
2536
+ },
2537
+ },
2538
+ },
2539
+ update_settings: {
2540
+ op: 'custom', access: 'update', method: 'post',
2541
+ path: '/integrations/update-settings',
2542
+ name: 'Update Integration Settings',
2543
+ description: "Updates non-sensitive integration settings",
2544
+ parameters: {
2545
+ id: { validator: mongoIdStringRequired, required: true },
2546
+ updates: { validator: objectAnyFieldsAnyValuesValidator, required: true },
2547
+ },
2548
+ returns: {
2549
+ integration: { validator: optionalAnyObjectValidator as any, required: true },
2550
+ },
2551
+ },
2509
2552
  }
2510
2553
  },
2511
2554
  engagement_events: {
@@ -4614,6 +4657,7 @@ export const schema: SchemaV1 = build_schema({
4614
4657
  belugaVerificationId: { validator: stringValidator },
4615
4658
  belugaPharmacyMappings: {
4616
4659
  validator: listValidatorOptionalOrEmptyOk(objectValidator<BelugaPharmacyMapping>({
4660
+ title: stringValidatorOptionalEmptyOkay,
4617
4661
  pharmacyId: stringValidator100,
4618
4662
  patientPreference: stringValidator5000,
4619
4663
  conditions: compoundFilterValidator,
@@ -4973,14 +5017,15 @@ export const schema: SchemaV1 = build_schema({
4973
5017
  path: '/form-responses/create-canvasnote',
4974
5018
  description: "Compiles FormResponses and creates a Note in Canvas",
4975
5019
  warnings: ['This returns early as the sync process can take a while for many form responses'],
4976
- parameters: {
5020
+ parameters: {
4977
5021
  enduserId: { validator: mongoIdStringValidator, required: true },
4978
5022
  formIds: { validator: listOfMongoIdStringValidator, required: true },
4979
5023
  noteCoding: { validator: canvasCodingValidator, required: true },
4980
- matchCareTeamTagsForCanvasPractitionerResolution: {
5024
+ matchCareTeamTagsForCanvasPractitionerResolution: {
4981
5025
  validator: listOfStringsWithQualifierValidator,
4982
5026
  required: true,
4983
5027
  },
5028
+ syncAllFormResponses: { validator: booleanValidatorOptional },
4984
5029
  },
4985
5030
  returns: { },
4986
5031
  },
@@ -5577,10 +5622,11 @@ export const schema: SchemaV1 = build_schema({
5577
5622
  op: "custom", access: 'update', method: "patch",
5578
5623
  name: 'Bulk Update Recurring Events',
5579
5624
  path: '/calendar-events/bulk-update',
5580
- description: "Performs bulk operations on a recurring event series starting from the given event",
5625
+ description: "Performs bulk operations on a recurring event series starting from the given event, or a set of specific events",
5581
5626
  parameters: {
5582
- recurringEventId: { validator: mongoIdStringValidator, required: true },
5583
- action: { validator: exactMatchValidator(['cancel_for_attendee', 'remove_attendee', 'cancel', 'delete', 'uncancel_for_attendee', 'uncancel']), required: true },
5627
+ recurringEventId: { validator: mongoIdStringValidator },
5628
+ ids: { validator: listOfMongoIdStringValidator },
5629
+ action: { validator: exactMatchValidator(['cancel_for_attendee', 'remove_attendee', 'cancel', 'delete', 'uncancel_for_attendee', 'uncancel', 'confirm', 'no_show', 'un_no_show']), required: true },
5584
5630
  scope: { validator: exactMatchValidatorOptional<"this_and_future" | "all">(['this_and_future', 'all']) },
5585
5631
  enduserId: { validator: mongoIdStringValidator },
5586
5632
  cancelReason: { validator: stringValidator5000 },
@@ -6794,6 +6840,58 @@ export const schema: SchemaV1 = build_schema({
6794
6840
  if (!session.isa) return "Not allowed"
6795
6841
  }
6796
6842
  },
6843
+ {
6844
+ explanation: 'Nested list fields in settings must not contain duplicates',
6845
+ evaluate: (updated, lookup, session, type, options) => {
6846
+ if (type !== 'update') return
6847
+ if (!options.updates?.settings) return
6848
+
6849
+ const updateSettings = (options.updates as Partial<Organization>).settings
6850
+ const originalSettings = (options.original as Organization | undefined)?.settings
6851
+ if (!updateSettings) return
6852
+
6853
+ const isReplace = !!options.replaceObjectFields
6854
+
6855
+ const checkStringArray = (newArr: string[] | undefined, oldArr: string[] | undefined, label: string) => {
6856
+ if (!newArr) return
6857
+ const hasDupesWithin = newArr.length !== new Set(newArr).size
6858
+ if (isReplace) {
6859
+ // Only reject if replacement has internal dupes AND grows the array
6860
+ if (hasDupesWithin && newArr.length > (oldArr || []).length) return `Duplicate value in ${label}`
6861
+ } else {
6862
+ // Merge: reject if new values have internal dupes or overlap with existing
6863
+ if (hasDupesWithin) return `Duplicate value in ${label}`
6864
+ if (oldArr) {
6865
+ const oldSet = new Set(oldArr)
6866
+ if (newArr.some(v => oldSet.has(v))) return `Duplicate value in ${label}`
6867
+ }
6868
+ }
6869
+ }
6870
+
6871
+ const checkObjectArray = (newArr: { [k: string]: any }[] | undefined, oldArr: { [k: string]: any }[] | undefined, key: string, label: string) => {
6872
+ if (!newArr) return
6873
+ const newValues = newArr.map(item => item[key])
6874
+ const hasDupesWithin = newValues.length !== new Set(newValues).size
6875
+ if (isReplace) {
6876
+ if (hasDupesWithin && newArr.length > (oldArr || []).length) return `Duplicate ${key} in ${label}`
6877
+ } else {
6878
+ if (hasDupesWithin) return `Duplicate ${key} in ${label}`
6879
+ if (oldArr) {
6880
+ const oldKeys = new Set(oldArr.map(item => item[key]))
6881
+ if (newValues.some(v => oldKeys.has(v))) return `Duplicate ${key} in ${label}`
6882
+ }
6883
+ }
6884
+ }
6885
+
6886
+ return (
6887
+ checkObjectArray(updateSettings.endusers?.customFields, originalSettings?.endusers?.customFields, 'field', 'settings.endusers.customFields')
6888
+ || checkObjectArray(updateSettings.endusers?.builtinFields, originalSettings?.endusers?.builtinFields, 'field', 'settings.endusers.builtinFields')
6889
+ || checkStringArray(updateSettings.endusers?.tags, originalSettings?.endusers?.tags, 'settings.endusers.tags')
6890
+ || checkStringArray(updateSettings.endusers?.dontRecordCallsToPhone, originalSettings?.endusers?.dontRecordCallsToPhone, 'settings.endusers.dontRecordCallsToPhone')
6891
+ || checkStringArray(updateSettings.calendar?.cancelReasons, originalSettings?.calendar?.cancelReasons, 'settings.calendar.cancelReasons')
6892
+ )
6893
+ }
6894
+ },
6797
6895
  ],
6798
6896
  },
6799
6897
  defaultActions: { read: { }, readMany: { }, update: { },
@@ -7009,6 +7107,8 @@ export const schema: SchemaV1 = build_schema({
7009
7107
  number: stringValidator100,
7010
7108
  }))
7011
7109
  },
7110
+ faxCoverPageEnabled: { validator: booleanValidator },
7111
+ faxCoverPageId: { validator: stringValidator250 },
7012
7112
  athenaFieldsSync: { validator: fieldsSyncValidator },
7013
7113
  athenaDepartments: {
7014
7114
  validator: listValidatorOptionalOrEmptyOk(objectValidator<{ id: string, timezone: Timezone }>({
@@ -7307,6 +7407,7 @@ export const schema: SchemaV1 = build_schema({
7307
7407
  ]
7308
7408
  },
7309
7409
  uiRestrictions: { validator: userUIRestrictionsValidator },
7410
+ fieldRedactions: { validator: userFieldRedactionsValidator },
7310
7411
  }
7311
7412
  },
7312
7413
  appointment_booking_pages: {
@@ -7375,8 +7476,9 @@ export const schema: SchemaV1 = build_schema({
7375
7476
  backgroundColor: { validator: stringValidator100 },
7376
7477
  primaryColor: { validator: stringValidator100 },
7377
7478
  secondaryColor: { validator: stringValidator100 },
7378
- intakeTitle: { validator: stringValidator1000 },
7379
- intakeDescription: { validator: stringValidator1000 },
7479
+ intakeTitle: { validator: stringValidator1000 },
7480
+ intakeDescription: { validator: stringValidator1000 },
7481
+ portalDescription: { validator: stringValidator1000 },
7380
7482
  thankYouRedirectURL: { validator: stringValidator1000 },
7381
7483
  thankYouTitle: { validator: stringValidator1000 },
7382
7484
  thankYouDescription: { validator: stringValidator1000 },
@@ -8509,6 +8611,9 @@ If a voicemail is left, it is indicated by recordingURI, transcription, or recor
8509
8611
  },
8510
8612
  customFields: {
8511
8613
  validator: customEnduserFieldsValidatorOptionalOrEmpty,
8614
+ },
8615
+ createEnduserForms: {
8616
+ validator: listOfMongoIdStringValidatorOptionalOrEmptyOk,
8512
8617
  }
8513
8618
  }
8514
8619
  },
@@ -9103,6 +9208,7 @@ If a voicemail is left, it is indicated by recordingURI, transcription, or recor
9103
9208
  cancellationReason: { validator: stringValidatorOptional },
9104
9209
  medication: { validator: stringValidatorOptional },
9105
9210
  medicationSku: { validator: stringValidatorOptional },
9211
+ protocol: { validator: stringValidator1000 },
9106
9212
  }
9107
9213
  },
9108
9214
  vital_configurations: {