@tellescope/sdk 0.0.5 → 0.0.9

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.
Files changed (45) hide show
  1. package/lib/cjs/enduser.d.ts +346 -13
  2. package/lib/cjs/enduser.d.ts.map +1 -1
  3. package/lib/cjs/enduser.js +135 -14
  4. package/lib/cjs/enduser.js.map +1 -1
  5. package/lib/cjs/sdk.d.ts +107 -20
  6. package/lib/cjs/sdk.d.ts.map +1 -1
  7. package/lib/cjs/sdk.js +116 -32
  8. package/lib/cjs/sdk.js.map +1 -1
  9. package/lib/cjs/session.d.ts +37 -176
  10. package/lib/cjs/session.d.ts.map +1 -1
  11. package/lib/cjs/session.js +131 -34
  12. package/lib/cjs/session.js.map +1 -1
  13. package/lib/cjs/tests/public_endpoint_tests.js +3 -3
  14. package/lib/cjs/tests/public_endpoint_tests.js.map +1 -1
  15. package/lib/cjs/tests/socket_tests.js +42 -31
  16. package/lib/cjs/tests/socket_tests.js.map +1 -1
  17. package/lib/cjs/tests/tests.js +232 -63
  18. package/lib/cjs/tests/tests.js.map +1 -1
  19. package/lib/esm/enduser.d.ts +346 -13
  20. package/lib/esm/enduser.d.ts.map +1 -1
  21. package/lib/esm/enduser.js +132 -12
  22. package/lib/esm/enduser.js.map +1 -1
  23. package/lib/esm/sdk.d.ts +107 -20
  24. package/lib/esm/sdk.d.ts.map +1 -1
  25. package/lib/esm/sdk.js +116 -32
  26. package/lib/esm/sdk.js.map +1 -1
  27. package/lib/esm/session.d.ts +37 -176
  28. package/lib/esm/session.d.ts.map +1 -1
  29. package/lib/esm/session.js +130 -32
  30. package/lib/esm/session.js.map +1 -1
  31. package/lib/esm/tests/public_endpoint_tests.js +3 -3
  32. package/lib/esm/tests/public_endpoint_tests.js.map +1 -1
  33. package/lib/esm/tests/socket_tests.js +41 -30
  34. package/lib/esm/tests/socket_tests.js.map +1 -1
  35. package/lib/esm/tests/tests.js +228 -64
  36. package/lib/esm/tests/tests.js.map +1 -1
  37. package/lib/tsconfig.tsbuildinfo +1 -1
  38. package/package.json +11 -9
  39. package/src/enduser.ts +93 -20
  40. package/src/sdk.ts +71 -43
  41. package/src/session.ts +122 -34
  42. package/src/tests/public_endpoint_tests.ts +6 -4
  43. package/src/tests/socket_tests.ts +37 -16
  44. package/src/tests/tests.ts +147 -25
  45. package/tsconfig.json +0 -1
@@ -1,9 +1,18 @@
1
1
  import {
2
2
  assert,
3
+ async_test,
3
4
  log_header,
4
- objects_equivalent,
5
5
  wait,
6
6
  } from "@tellescope/testing"
7
+ import {
8
+ objects_equivalent,
9
+ } from "@tellescope/utilities"
10
+ import {
11
+ ChatMessage,
12
+ } from "@tellescope/types-client"
13
+ import {
14
+ Indexable,
15
+ } from "@tellescope/types-utilities"
7
16
  import { EnduserSession } from "../enduser"
8
17
  import { Session, /* APIQuery */ } from "../sdk"
9
18
 
@@ -23,8 +32,7 @@ if (!(email && password && email2 && password2)) {
23
32
  const basic_tests = async () => {
24
33
  const socket_events: Indexable[] = []
25
34
 
26
- user2.subscribe({ 'endusers': 'endusers' })
27
- user2.handle_events({
35
+ user2.subscribe({ 'endusers': 'endusers' }, {
28
36
  'created-endusers': es => socket_events.push(es),
29
37
  'updated-endusers': es => socket_events.push(es),
30
38
  'deleted-endusers': es => socket_events.push(es),
@@ -116,11 +124,10 @@ const access_tests = async () => {
116
124
  }
117
125
 
118
126
  const enduser_tests = async () => {
119
- const enduser = await user1.api.endusers.createOne({ email: "sockettest@tellescope.com" })
120
- await user1.api.endusers.setPassword(enduser.id, 'enduserpassword')
127
+ const enduser = await user1.api.endusers.createOne({ email: "enduser@tellescope.com" })
128
+ await user1.api.endusers.setPassword({ id: enduser.id, password: 'enduserPassword!' })
121
129
 
122
- await enduserSDK.authenticate(enduser.email as string, 'enduserpassword')
123
- enduserSDK.authenticate_socket()
130
+ await enduserSDK.authenticate(enduser.email as string, 'enduserPassword!')
124
131
  await wait(undefined, 25)
125
132
 
126
133
  const userEvents = [] as ChatMessage[]
@@ -140,18 +147,31 @@ const enduser_tests = async () => {
140
147
 
141
148
  user1.handle_events({
142
149
  'created-chats': rs => userEvents.push(...rs),
143
- 'updated-chats': rs => enduserEvents.push(...rs),
150
+ })
151
+ enduserSDK.handle_events({
152
+ 'created-chats': rs => enduserEvents.push(...rs),
144
153
  })
145
154
 
146
155
  const messageToEnduser = await user1.api.chats.createOne({ roomId: room.id, message: "Hello!" })
147
156
  const messageToUser = await enduserSDK.api.chats.createOne({ roomId: room.id, message: "Hello right back!" })
157
+ await wait(undefined, 25)
148
158
 
149
- console.log(userEvents, enduserEvents)
159
+ assert(objects_equivalent(userEvents[0], messageToUser), 'no message on socket', 'push message to user')
160
+ assert(objects_equivalent(enduserEvents[0], messageToEnduser), 'no message on socket', 'push message to enduser')
161
+
162
+ // test enduser logout
163
+ await enduserSDK.api.endusers.logout()
164
+ await async_test(
165
+ `verify enduser logout works`,
166
+ () => enduserSDK.api.chats.getSome({}),
167
+ { shouldError: true, onError: (e: string) => e === 'Unauthenticated' }
168
+ )
150
169
 
170
+ // keep these models around for front-end testing
151
171
  // cleanup
152
- await user1.api.endusers.deleteOne(enduser.id)
153
- await user1.api.chats.deleteOne(messageToEnduser.id)
154
- await user1.api.chats.deleteOne(messageToUser.id)
172
+ // await user1.api.endusers.deleteOne(enduser.id)
173
+ // await user1.api.chats.deleteOne(messageToEnduser.id)
174
+ // await user1.api.chats.deleteOne(messageToUser.id)
155
175
  }
156
176
 
157
177
  (async () => {
@@ -160,10 +180,11 @@ const enduser_tests = async () => {
160
180
  try {
161
181
  await user1.authenticate(email, password, host)
162
182
  await user1.reset_db()
163
- await user2.authenticate(email2, password2, host) // generate authToken + socket connection for API key
164
-
183
+ await user2.authenticate(email2, password2, host) // generate authToken + socket connection for API keyj
184
+ await wait(undefined, 25)
185
+
165
186
  let loopCount = 0
166
- while (!(user1.socket_is_authenticated() && user2.socket_is_authenticated()) && ++loopCount < 10) {
187
+ while (!(user1.socketAuthenticated && user2.socketAuthenticated) && ++loopCount < 10) {
167
188
  user2.authenticate_socket()
168
189
  await wait(undefined, 100)
169
190
  }
@@ -171,7 +192,7 @@ const enduser_tests = async () => {
171
192
  console.log("Failed to authenticate")
172
193
  process.exit()
173
194
  }
174
-
195
+
175
196
  await enduser_tests()
176
197
  await basic_tests()
177
198
  await access_tests()
@@ -6,34 +6,44 @@ import {
6
6
  ClientModelForName,
7
7
  ClientModelForName_required,
8
8
  } from "@tellescope/types-client"
9
+ import {
10
+ Model as ClientModel,
11
+ ModelName,
12
+ } from "@tellescope/types-models"
9
13
 
10
-
11
- // import v from 'validator'
14
+ import {
15
+ Indexable,
16
+ Operation,
17
+ } from "@tellescope/types-utilities"
12
18
 
13
19
  import {
14
20
  fieldsToValidation,
15
21
  mongoIdValidator,
16
22
 
17
- // InputValidation,
23
+ InputValidation,
18
24
  } from "@tellescope/validation"
19
25
 
20
- import { Session, APIQuery } from "../sdk"
21
- import { url_safe_path } from "@tellescope/utilities"
26
+ import { Session, APIQuery, EnduserSession } from "../sdk"
27
+ import { } from "@tellescope/utilities"
22
28
  import { DEFAULT_OPERATIONS } from "@tellescope/constants"
23
29
  import {
24
30
  schema,
25
- // Model,
26
- // ModelFields
31
+ Model,
32
+ ModelFields,
27
33
  } from "@tellescope/schema"
28
34
 
29
35
  import {
30
36
  assert,
31
37
  async_test,
32
38
  log_header,
33
- objects_equivalent,
34
39
  wait,
35
40
  } from "@tellescope/testing"
36
41
 
42
+ import {
43
+ objects_equivalent,
44
+ url_safe_path,
45
+ } from "@tellescope/utilities"
46
+
37
47
 
38
48
  const host = process.env.TEST_URL || 'http://localhost:8080'
39
49
  const [email, password] = [process.env.TEST_EMAIL, process.env.TEST_PASSWORD]
@@ -41,8 +51,28 @@ const [email2, password2] = [process.env.TEST_EMAIL_2, process.env.TEST_PASSWORD
41
51
 
42
52
  const userId = '60398b0231a295e64f084fd9'
43
53
 
54
+ // const example_SDK_usage = async () => {
55
+ // // initialize SDK and authenticate a user
56
+ // const sdk = new Session()
57
+ // await sdk.authenticate("user-email", 'user-password')
58
+
59
+ // // create a record, using Enduser model as example
60
+ // const enduser = await sdk.api.endusers.createOne({ email: "enduser1@tellescope.com" })
61
+
62
+ // // update an existing record
63
+ // await sdk.api.endusers.updateOne(enduser.id, { phone: "+15555555555" })
64
+
65
+ // // fetch a record by id, or a list of recent records
66
+ // const existingEnduser: Enduser = await sdk.api.endusers.getOne(enduser.id)
67
+ // const existingEndusers: Enduser[] = await sdk.api.endusers.getSome({ limit: 5, lastId: enduser.id })
68
+
69
+ // // delete an individual record
70
+ // await sdk.api.endusers.deleteOne(enduser.id)
71
+ // }
72
+
44
73
  const sdk = new Session()
45
74
  const sdkOther = new Session({ host, apiKey: "ba745e25162bb95a795c5fa1af70df188d93c4d3aac9c48b34a5c8c9dd7b80f7" })
75
+ const enduserSDK = new EnduserSession({ host })
46
76
  // const sdkOtherEmail = "sebass@tellescope.com"
47
77
 
48
78
  if (!(email && password && email2 && password2)) {
@@ -160,6 +190,34 @@ const threadKeyTests = async () => {
160
190
  ])
161
191
  }
162
192
 
193
+ const filterTests = async () => {
194
+ const enduser = await sdk.api.endusers.createOne({ email: 'filtertests@tellescope.com', fname: 'test' })
195
+ const otherEnduser = await sdk.api.endusers.createOne({ email: 'other@tellescope.com' })
196
+ await async_test(
197
+ `find enduser by filter`,
198
+ () => sdk.api.endusers.getSome({ filter: { email: 'filtertests@tellescope.com' }}),
199
+ { onResult: es => es.length === 1 && es[0].id === enduser.id },
200
+ )
201
+ await async_test(
202
+ `find enduser by compound filter`,
203
+ () => sdk.api.endusers.getSome({ filter: { email: 'filtertests@tellescope.com', fname: 'test' }}),
204
+ { onResult: es => es.length === 1 && es[0].id === enduser.id },
205
+ )
206
+ await async_test(
207
+ `nothing found by invalid compound filter`,
208
+ () => sdk.api.endusers.getSome({ filter: { email: 'filtertests@tellescope.com', fname: 'nottest' }}),
209
+ { onResult: es => es.length === 0 },
210
+ )
211
+ await async_test(
212
+ `nothing found for invalid filter`,
213
+ () => sdk.api.endusers.getSome({ filter: { email: 'doesnotexist@tellescope.com' }}),
214
+ { onResult: es => es.length === 0 },
215
+ )
216
+
217
+ await sdk.api.endusers.deleteOne(enduser.id)
218
+ await sdk.api.endusers.deleteOne(otherEnduser.id)
219
+ }
220
+
163
221
  const instanceForModel = <N extends ModelName, T=ClientModelForName[N], REQ=ClientModelForName_required[N]>(model: Model<T, N>, i=0) => {
164
222
  const instance = {} as Indexable
165
223
  const updates = {} as Indexable
@@ -281,7 +339,7 @@ const run_generated_tests = async <N extends ModelName>({ queries, model, name,
281
339
  await async_test(
282
340
  `update-${singularName}`,
283
341
  () => queries.updateOne(_id, updates, { replaceObjectFields: true }),
284
- passOnVoid
342
+ { onResult: u => typeof u === 'object' && u.id === _id }
285
343
  )
286
344
  }
287
345
  await async_test(
@@ -299,7 +357,7 @@ const run_generated_tests = async <N extends ModelName>({ queries, model, name,
299
357
  )
300
358
  await async_test(
301
359
  `get-${safeName}`,
302
- () => queries.getSome({}, filter),
360
+ () => queries.getSome({ filter }),
303
361
  { onResult: ([d, /*...others */]) => {
304
362
  // if (others.length !== 0) return false // some collections are not reset during testing, like API keys
305
363
  if (!d?.id) return false
@@ -527,7 +585,7 @@ const journey_tests = async (queries=sdk.api.journeys) => {
527
585
 
528
586
  await async_test(
529
587
  `journey-updateState`,
530
- () => queries.updateState(journey.id, 'Added', { name: 'Updated', priority: 'N/A' }),
588
+ () => queries.updateState({ id: journey.id, name: 'Added', updates: { name: 'Updated', priority: 'N/A' }}),
531
589
  passOnVoid,
532
590
  )
533
591
  await wait(undefined, 25) // wait for side effects to update endusers
@@ -701,7 +759,7 @@ const chat_tests = async() => {
701
759
  )
702
760
  await async_test(
703
761
  `get-chats (with filter)`,
704
- () => sdk.api.chats.getSome({}, { roomId: room.id }),
762
+ () => sdk.api.chats.getSome({ filter: { roomId: room.id } }),
705
763
  { onResult: c => c?.length === 2 }
706
764
  )
707
765
 
@@ -712,25 +770,27 @@ const chat_tests = async() => {
712
770
  )
713
771
  await async_test(
714
772
  `get-chats not allowed`,
715
- () => sdk2.api.chats.getSome({}, { roomId: room.id }),
716
- { shouldError: true, onError: e => e.message === 'You do not have permission to access this resource' }
717
- )
718
- await async_test(
719
- `update-chat not allowed`,
720
- () => sdk2.api.chats.updateOne(chat.id, { message: 'Hi' }),
773
+ () => sdk2.api.chats.getSome({ filter: { roomId: room.id } }),
721
774
  { shouldError: true, onError: e => e.message === 'You do not have permission to access this resource' }
722
775
  )
776
+ // currently disabled endpoint altogether
777
+ // await async_test(
778
+ // `update-chat not allowed`,
779
+ // () => sdk2.api.chats.updateOne(chat.id, { message: 'Hi' }),
780
+ // { shouldError: true, onError: e => e.message === 'You do not have permission to access this resource' }
781
+ // )
723
782
  await async_test(
724
783
  `delete-chat not allowed`,
725
784
  () => sdk2.api.chats.deleteOne(chat.id),
726
785
  { shouldError: true, onError: e => e.message === 'You do not have permission to access this resource' }
727
786
  )
728
787
 
729
- await async_test(
730
- `update-chat can't update roomId`,
731
- () => sdk.api.chats.updateOne(chat.id, { roomId: room.id } as any), // cast to any to allow calling with bad argument, but typing should catch this too
732
- { shouldError: true, onError: e => e.message === 'Error parsing field updates: roomId is not valid for updates' }
733
- )
788
+ // currently disabled endpoint altogether
789
+ // await async_test(
790
+ // `update-chat can't update roomId`,
791
+ // () => sdk.api.chats.updateOne(chat.id, { roomId: room.id } as any), // cast to any to allow calling with bad argument, but typing should catch this too
792
+ // { shouldError: true, onError: e => e.message === 'Error parsing field updates: roomId is not valid for updates' }
793
+ // )
734
794
 
735
795
  await sdk.api.chat_rooms.deleteOne(room.id)
736
796
  await wait(undefined, 25)
@@ -760,12 +820,12 @@ const chat_tests = async() => {
760
820
  )
761
821
  await async_test(
762
822
  `get-chats (shared, user1)`,
763
- () => sdk.api.chats.getSome({}, { roomId: sharedRoom.id }),
823
+ () => sdk.api.chats.getSome({ filter: { roomId: sharedRoom.id } }, ),
764
824
  { onResult: cs => cs.length === 2 && !!cs.find(c => c.id === sharedChat.id) && !!cs.find(c => c.id === sharedChat2.id) }
765
825
  )
766
826
  await async_test(
767
827
  `get-chats (shared, user2)`,
768
- () => sdk2.api.chats.getSome({}, { roomId: sharedRoom.id }),
828
+ () => sdk2.api.chats.getSome({ filter: { roomId: sharedRoom.id } }),
769
829
  { onResult: cs => cs.length === 2 && !!cs.find(c => c.id === sharedChat.id) && !!cs.find(c => c.id === sharedChat2.id) }
770
830
  )
771
831
 
@@ -783,6 +843,65 @@ const chat_tests = async() => {
783
843
  )
784
844
  }
785
845
 
846
+ const enduserAccessTests = async () => {
847
+ const email = 'enduser@tellescope.com'
848
+ const password = 'testpassword'
849
+
850
+ const enduser = await sdk.api.endusers.createOne({ email })
851
+ await sdk.api.endusers.setPassword({ id: enduser.id, password }).catch(console.error)
852
+ await enduserSDK.authenticate(email, password).catch(console.error)
853
+
854
+ for (const n in schema) {
855
+ const endpoint = url_safe_path(n)
856
+ const model = schema[n as keyof typeof schema]
857
+
858
+ if (!model?.enduserActions?.read && (model.defaultActions.read || model.customActions.read)) {
859
+ await async_test(
860
+ `no-enduser-access getOne (${endpoint})`,
861
+ () => enduserSDK.GET(`/v1/${endpoint.substring(0, endpoint.length - 1)}/:id`),
862
+ { shouldError: true, onError: (e: string) => e === 'Unauthenticated' }
863
+ )
864
+ }
865
+ if (!model.enduserActions?.readMany && (model.defaultActions.readMany || model.customActions.readMany)) {
866
+ await async_test(
867
+ `no-enduser-access getSome (${endpoint})`,
868
+ () => enduserSDK.GET(`/v1/${endpoint}`),
869
+ { shouldError: true, onError: (e: string) => e === 'Unauthenticated' }
870
+ )
871
+ }
872
+ if (!model.enduserActions?.create && (model.defaultActions.create || model.customActions.create)) {
873
+ await async_test(
874
+ `no-enduser-access createOne (${endpoint})`,
875
+ () => enduserSDK.POST(`/v1/${endpoint.substring(0, endpoint.length - 1)}`),
876
+ { shouldError: true, onError: (e: string) => e === 'Unauthenticated' }
877
+ )
878
+ }
879
+ if (!model.enduserActions?.createMany && (model.defaultActions.createMany || model.customActions.createMany)) {
880
+ await async_test(
881
+ `no-enduser-access createMany (${endpoint})`,
882
+ () => enduserSDK.POST(`/v1/${endpoint}`),
883
+ { shouldError: true, onError: (e: string) => e === 'Unauthenticated' }
884
+ )
885
+ }
886
+ if (!model.enduserActions?.update && (model.defaultActions.update || model.customActions.update)) {
887
+ await async_test(
888
+ `no-enduser-access update (${endpoint})`,
889
+ () => enduserSDK.PATCH(`/v1/${endpoint.substring(0, endpoint.length - 1)}/:id`),
890
+ { shouldError: true, onError: (e: string) => e === 'Unauthenticated' }
891
+ )
892
+ }
893
+ if (!model.enduserActions?.delete && (model.defaultActions.delete || model.customActions.delete)) {
894
+ await async_test(
895
+ `no-enduser-access delete (${endpoint})`,
896
+ () => enduserSDK.DELETE(`/v1/${endpoint.substring(0, endpoint.length - 1)}/:id`),
897
+ { shouldError: true, onError: (e: string) => e === 'Unauthenticated' }
898
+ )
899
+ }
900
+ }
901
+
902
+ await sdk.api.endusers.deleteOne(enduser.id)
903
+ }
904
+
786
905
  const tests: { [K in keyof ClientModelForName]: () => void } = {
787
906
  chats: chat_tests,
788
907
  endusers: enduser_tests,
@@ -795,6 +914,7 @@ const tests: { [K in keyof ClientModelForName]: () => void } = {
795
914
  chat_rooms: chat_room_tests,
796
915
  users: () => {},
797
916
  templates: () => {},
917
+ files: () => {},
798
918
  };
799
919
 
800
920
  (async () => {
@@ -803,7 +923,9 @@ const tests: { [K in keyof ClientModelForName]: () => void } = {
803
923
  log_header("API")
804
924
  await setup_tests()
805
925
  await multi_tenant_tests() // should come right after setup tests
926
+ await filterTests()
806
927
  await threadKeyTests()
928
+ await enduserAccessTests()
807
929
 
808
930
  let n: keyof typeof schema;
809
931
  for (n in schema) {
package/tsconfig.json CHANGED
@@ -10,7 +10,6 @@
10
10
  { "path": "../constants" },
11
11
  { "path": "../schema" },
12
12
  { "path": "../testing" },
13
- { "path": "../types" },
14
13
  { "path": "../types-client" },
15
14
  { "path": "../utilities" },
16
15
  { "path": "../validation" }