@tellescope/sdk 0.0.11 → 0.0.15

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/sdk.ts CHANGED
@@ -12,6 +12,7 @@ import {
12
12
  ClientModelForName_readonly,
13
13
  ClientModelForName_required,
14
14
  ClientModelForName_updatesDisabled,
15
+ ChatRoom,
15
16
  Enduser,
16
17
  File,
17
18
  } from "@tellescope/types-client"
@@ -23,6 +24,8 @@ import { Session as SessionManager, SessionOptions, Filter } from "./session"
23
24
  export * from "./public"
24
25
  export * from "./enduser"
25
26
 
27
+ export type LoadFunction<T> = (o?: { lastId?: string, limit?: number, sort?: SortOption, threadKey?: string, filter?: Filter<Partial<T>> }) => Promise<T[]>
28
+
26
29
  export interface APIQuery<
27
30
  N extends keyof ClientModelForName,
28
31
  T=ClientModelForName[N],
@@ -34,7 +37,7 @@ export interface APIQuery<
34
37
  createOne: (t: CREATE) => Promise<T>;
35
38
  createSome: (ts: CREATE[]) => Promise<{ created: T[], errors: object[] }>;
36
39
  getOne: (id: string, filter?: Filter<Partial<T>>) => Promise<T>;
37
- getSome: (o?: { lastId?: string, limit?: number, sort?: SortOption, threadKey?: string, filter?: Filter<Partial<T>> }) => Promise<T[]>
40
+ getSome: LoadFunction<T>;
38
41
  updateOne: (id: string, updates: UPDATE, options?: CustomUpdateOptions) => Promise<T>;
39
42
  deleteOne: (id: string) => Promise<void>;
40
43
  }
@@ -71,6 +74,7 @@ const loadDefaultQueries = (s: Session): { [K in keyof ClientModelForName] : API
71
74
  files: defaultQueries(s, 'files'),
72
75
  tickets: defaultQueries(s, 'tickets'),
73
76
  meetings: defaultQueries(s, 'meetings'),
77
+ notes: defaultQueries(s, 'notes'),
74
78
  })
75
79
 
76
80
  type Queries = { [K in keyof ClientModelForName]: APIQuery<K> } & {
@@ -80,6 +84,7 @@ type Queries = { [K in keyof ClientModelForName]: APIQuery<K> } & {
80
84
  endusers: {
81
85
  setPassword: (args: { id: string, password: string }) => Promise<void>,
82
86
  isAuthenticated: (args: { id: string, authToken: string }) => Promise<{ isAuthenticated: boolean, enduser: Enduser }>
87
+ generateAuthToken: (args: { id: string }) => Promise<{ authToken: string }>
83
88
  },
84
89
  users: {
85
90
  display_names: () => Promise<{ fname: string, lname: string, id: string }[]>,
@@ -89,12 +94,15 @@ type Queries = { [K in keyof ClientModelForName]: APIQuery<K> } & {
89
94
  file_download_URL: (args: { secureName: string }) => Promise<{ downloadURL: string }>,
90
95
  },
91
96
  meetings: {
92
- start_meeting: () => Promise<{ id: string, meeting: { Meeting: MeetingInfo }, host: AttendeeInfo }>,
97
+ start_meeting: () => Promise<{ id: string, meeting: { Meeting: MeetingInfo }, host: { Attendee: AttendeeInfo } }>,
93
98
  end_meeting: (args: { id: string }) => Promise<void>,
94
99
  add_attendees_to_meeting: (args: { id: string, attendees: UserIdentity[] }) => Promise<void>,
95
100
  my_meetings: () => Promise<Meeting[]>,
96
101
  attendee_info: (args: { id: string }) => Promise<{ attendee: AttendeeInfo, others: UserIdentity[] }>,
97
102
  },
103
+ chat_rooms: {
104
+ join_room: (args: { id: string }) => Promise<{ room: ChatRoom }>,
105
+ },
98
106
  }
99
107
 
100
108
  export class Session extends SessionManager {
@@ -108,9 +116,11 @@ export class Session extends SessionManager {
108
116
  queries.journeys.updateState = ({id, name, updates}) => this._PATCH(`/v1/journey/${id}/state/${name}`, { updates })
109
117
  queries.endusers.setPassword = ({id, password}) => this._POST(`/v1/set-enduser-password`, { id, password })
110
118
  queries.endusers.isAuthenticated = ({id, authToken}) => this._GET(`/v1/enduser-is-authenticated`, { id, authToken })
119
+ queries.endusers.generateAuthToken = args => this._GET(`/v1/generate-enduser-auth-token`, args)
111
120
  queries.users.display_names = () => this._GET<{}, { fname: string, lname: string, id: string }[]>(`/v1/user-display-names`),
112
121
  queries.files.prepare_file_upload = (args) => this._POST(`/v1/prepare-file-upload`, args),
113
122
  queries.files.file_download_URL = a => this._GET('/v1/file-download-URL', a),
123
+ queries.chat_rooms.join_room = a => this._POST('/v1/join-chat-room', a),
114
124
 
115
125
  queries.meetings.start_meeting = () => this._POST('/v1/start-meeting')
116
126
  queries.meetings.end_meeting = a => this._POST('/v1/end-meeting', a)
package/src/session.ts CHANGED
@@ -195,6 +195,11 @@ export class Session {
195
195
  catch(err) { console.error(err); throw err }
196
196
  }
197
197
 
198
+ DOWNLOAD = async (downloadURL: string) => {
199
+ const content = await axios.get(downloadURL)
200
+ return content.data
201
+ }
202
+
198
203
  EMIT = async (route: string, args: object, authenticated=true, options={} as RequestOptions) => {
199
204
  this.socket?.emit(route, { ...args, ...authenticated ? { authToken: this.authToken } : {} } )
200
205
  }
@@ -1,8 +1,9 @@
1
1
  require('source-map-support').install();
2
+ import * as fs from "fs"
3
+ import * as buffer from "buffer" // only node >=15.7.0
2
4
 
3
5
  import {
4
6
  Enduser,
5
- ChatRoom,
6
7
  ClientModelForName,
7
8
  ClientModelForName_required,
8
9
  } from "@tellescope/types-client"
@@ -191,7 +192,7 @@ const threadKeyTests = async () => {
191
192
  }
192
193
 
193
194
  const filterTests = async () => {
194
- const enduser = await sdk.api.endusers.createOne({ email: 'filtertests@tellescope.com', fname: 'test' })
195
+ const enduser = await sdk.api.endusers.createOne({ email: 'filtertests@tellescope.com', fname: 'test', fields: { field1: 'value1', field2: 'value2' } })
195
196
  const otherEnduser = await sdk.api.endusers.createOne({ email: 'other@tellescope.com' })
196
197
  await async_test(
197
198
  `find enduser by filter`,
@@ -213,6 +214,36 @@ const filterTests = async () => {
213
214
  () => sdk.api.endusers.getSome({ filter: { email: 'doesnotexist@tellescope.com' }}),
214
215
  { onResult: es => es.length === 0 },
215
216
  )
217
+ await async_test(
218
+ `find enduser by nested filter`,
219
+ () => sdk.api.endusers.getSome({ filter: { fields: { field1: 'value1' } } }),
220
+ { onResult: es => es.length === 1 && es[0].id === enduser.id },
221
+ )
222
+ await async_test(
223
+ `nothing found by invalid nested filter`,
224
+ () => sdk.api.endusers.getSome({ filter: { fields: { field1: 'not a nested field value' } }}),
225
+ { onResult: es => es.length === 0 },
226
+ )
227
+ await async_test(
228
+ `find enduser by compound nested filter`,
229
+ () => sdk.api.endusers.getSome({ filter: { fields: { field1: 'value1', field2: 'value2' } } }),
230
+ { onResult: es => es.length === 1 && es[0].id === enduser.id },
231
+ )
232
+ await async_test(
233
+ `nothing found by compound invalid nested filter`,
234
+ () => sdk.api.endusers.getSome({ filter: { fields: { field1: 'not a nested field value', field2: 'value2' } }}),
235
+ { onResult: es => es.length === 0 },
236
+ )
237
+ await async_test(
238
+ `find enduser by compound nested filter with non-nested field as well`,
239
+ () => sdk.api.endusers.getSome({ filter: {email: 'filtertests@tellescope.com', fields: { field1: 'value1', field2: 'value2' } } }),
240
+ { onResult: es => es.length === 1 && es[0].id === enduser.id },
241
+ )
242
+ await async_test(
243
+ `nothing found for compound nested filter with non-nested field as well`,
244
+ () => sdk.api.endusers.getSome({ filter: {email: 'doesnotexist@tellescope.com', fields: { field1: 'value1', field2: 'value2' } } }),
245
+ { onResult: es => es.length === 0 },
246
+ )
216
247
 
217
248
  await sdk.api.endusers.deleteOne(enduser.id)
218
249
  await sdk.api.endusers.deleteOne(otherEnduser.id)
@@ -232,6 +263,16 @@ const updatesTests = async () => {
232
263
  await sdk.api.endusers.deleteOne(enduser.id)
233
264
  }
234
265
 
266
+ const generateEnduserAuthTests = async () => {
267
+ log_header("Generated Enduser authToken Tests")
268
+ const enduser = await sdk.api.endusers.createOne({ email: 'generated@tellescope.com'})
269
+ const { authToken } = await sdk.api.endusers.generateAuthToken({ id: enduser.id })
270
+ const { isAuthenticated } = await sdk.api.endusers.isAuthenticated({ id: enduser.id, authToken })
271
+ assert(isAuthenticated, 'invalid authToken generated for enduser', 'Generate authToken for enduser is valid')
272
+
273
+ await sdk.api.endusers.deleteOne(enduser.id)
274
+ }
275
+
235
276
  const instanceForModel = <N extends ModelName, T=ClientModelForName[N], REQ=ClientModelForName_required[N]>(model: Model<T, N>, i=0) => {
236
277
  const instance = {} as Indexable
237
278
  const updates = {} as Indexable
@@ -744,8 +785,31 @@ const chat_room_tests = async () => {
744
785
  () => sdk2.api.chat_rooms.getOne(room.id),
745
786
  { shouldError: true, onError: e => e.message === "Could not find a record for the given id" }
746
787
  )
788
+ await sdk.api.chat_rooms.deleteOne(room.id)
747
789
 
748
- sdk.api.chat_rooms.deleteOne(room.id)
790
+
791
+ const emptyRoom = await sdk.api.chat_rooms.createOne({ })
792
+ await async_test(
793
+ `get-chat-room (creator can access, even when not in userIds)`,
794
+ () => sdk.api.chat_rooms.getOne(emptyRoom.id),
795
+ { onResult: r => r.id === emptyRoom.id }
796
+ )
797
+ await async_test(
798
+ `get-chat-room (not in empty room)`,
799
+ () => sdk2.api.chat_rooms.getOne(emptyRoom.id),
800
+ { shouldError: true, onError: e => e.message === "Could not find a record for the given id" }
801
+ )
802
+ await async_test(
803
+ `join-room`,
804
+ () => sdk2.api.chat_rooms.join_room({ id: emptyRoom.id }),
805
+ { onResult: ({ room }) => room.id === emptyRoom.id }
806
+ )
807
+ await async_test(
808
+ `get-chat-room (join successful)`,
809
+ () => sdk2.api.chat_rooms.getOne(emptyRoom.id),
810
+ { onResult: r => r.id === emptyRoom.id }
811
+ )
812
+ await sdk.api.chat_rooms.deleteOne(emptyRoom.id)
749
813
  }
750
814
 
751
815
  const chat_tests = async() => {
@@ -941,6 +1005,20 @@ const enduserAccessTests = async () => {
941
1005
  await sdk.api.endusers.deleteOne(enduser.id)
942
1006
  }
943
1007
 
1008
+ const files_tests = async () => {
1009
+ const buff = buffer.Buffer.from('test file data')
1010
+
1011
+ const { presignedUpload, file } = await sdk.api.files.prepare_file_upload({
1012
+ name: 'Test File', size: buff.byteLength, type: 'text/plain'
1013
+ })
1014
+ await sdk.UPLOAD(presignedUpload, undefined, buff as any)
1015
+
1016
+ const { downloadURL } = await sdk.api.files.file_download_URL({ secureName: file.secureName })
1017
+ const downloaded: string = await sdk.DOWNLOAD(downloadURL)
1018
+
1019
+ assert(downloaded === buff.toString(), 'downloaded file does not match uploaded file', 'upload, download comparison')
1020
+ }
1021
+
944
1022
  const tests: { [K in keyof ClientModelForName]: () => void } = {
945
1023
  chats: chat_tests,
946
1024
  endusers: enduser_tests,
@@ -953,9 +1031,10 @@ const tests: { [K in keyof ClientModelForName]: () => void } = {
953
1031
  chat_rooms: chat_room_tests,
954
1032
  users: () => {},
955
1033
  templates: () => {},
956
- files: () => {},
1034
+ files: files_tests,
957
1035
  tickets: () => {},
958
1036
  meetings: () => {},
1037
+ notes: () => {},
959
1038
  };
960
1039
 
961
1040
  (async () => {
@@ -970,6 +1049,7 @@ const tests: { [K in keyof ClientModelForName]: () => void } = {
970
1049
  await updatesTests()
971
1050
  await threadKeyTests()
972
1051
  await enduserAccessTests()
1052
+ await generateEnduserAuthTests()
973
1053
  } catch(err) {
974
1054
  console.error("Failed during custom test")
975
1055
  console.error(err)