@amityco/ts-sdk 0.0.1-beta.21 → 0.0.1-beta.24

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 (53) hide show
  1. package/dist/@types/domains/channel.d.ts +1 -2
  2. package/dist/@types/domains/channel.d.ts.map +1 -1
  3. package/dist/@types/domains/content.d.ts +5 -2
  4. package/dist/@types/domains/content.d.ts.map +1 -1
  5. package/dist/@types/domains/message.d.ts +2 -2
  6. package/dist/@types/domains/message.d.ts.map +1 -1
  7. package/dist/@types/domains/reaction.d.ts +1 -1
  8. package/dist/@types/domains/reaction.d.ts.map +1 -1
  9. package/dist/channel/api/queryChannelMembers.d.ts +2 -1
  10. package/dist/channel/api/queryChannelMembers.d.ts.map +1 -1
  11. package/dist/channel/api/queryChannels.d.ts +1 -0
  12. package/dist/channel/api/queryChannels.d.ts.map +1 -1
  13. package/dist/channel/api/updateChannel.d.ts +1 -1
  14. package/dist/channel/api/updateChannel.d.ts.map +1 -1
  15. package/dist/client/api/connectClient.d.ts +3 -1
  16. package/dist/client/api/connectClient.d.ts.map +1 -1
  17. package/dist/comment/api/queryComments.d.ts +1 -0
  18. package/dist/comment/api/queryComments.d.ts.map +1 -1
  19. package/dist/core/model/identifyModel.d.ts +1 -0
  20. package/dist/core/model/identifyModel.d.ts.map +1 -1
  21. package/dist/core/query/query.d.ts.map +1 -1
  22. package/dist/index.cjs.js +204 -68
  23. package/dist/index.esm.js +203 -68
  24. package/dist/index.umd.js +5 -5
  25. package/dist/message/api/createMessage.d.ts +2 -2
  26. package/dist/message/api/createMessage.d.ts.map +1 -1
  27. package/dist/message/api/updateMessage.d.ts +2 -2
  28. package/dist/message/api/updateMessage.d.ts.map +1 -1
  29. package/dist/message/events/onMessageUpdated.d.ts.map +1 -1
  30. package/dist/reaction/events/onReactionAdded.d.ts.map +1 -1
  31. package/dist/reaction/utils/index.d.ts +1 -0
  32. package/dist/reaction/utils/index.d.ts.map +1 -1
  33. package/dist/reaction/utils/prepareMessagePayloadForCache.d.ts +3 -0
  34. package/dist/reaction/utils/prepareMessagePayloadForCache.d.ts.map +1 -0
  35. package/package.json +1 -1
  36. package/src/@types/domains/channel.ts +1 -2
  37. package/src/@types/domains/content.ts +7 -1
  38. package/src/@types/domains/message.ts +2 -1
  39. package/src/@types/domains/reaction.ts +1 -1
  40. package/src/channel/api/queryChannelMembers.ts +4 -4
  41. package/src/channel/api/queryChannels.ts +1 -0
  42. package/src/channel/api/updateChannel.ts +1 -1
  43. package/src/client/api/connectClient.ts +12 -7
  44. package/src/comment/api/queryComments.ts +6 -3
  45. package/src/core/model/identifyModel.ts +18 -0
  46. package/src/core/query/paging.ts +3 -3
  47. package/src/core/query/query.ts +19 -1
  48. package/src/message/api/createMessage.ts +24 -8
  49. package/src/message/api/updateMessage.ts +2 -2
  50. package/src/message/events/onMessageUpdated.ts +9 -1
  51. package/src/reaction/events/onReactionAdded.ts +4 -0
  52. package/src/reaction/utils/index.ts +1 -0
  53. package/src/reaction/utils/prepareMessagePayloadForCache.ts +40 -0
package/dist/index.esm.js CHANGED
@@ -5,6 +5,7 @@ import debug from 'debug';
5
5
  import axios from 'axios';
6
6
  import HttpAgent, { HttpsAgent } from 'agentkeepalive';
7
7
  import io from 'socket.io-client';
8
+ import nativeIdGenerator from 'react-native-uuid';
8
9
 
9
10
  var _a$1;
10
11
  /* eslint-disable no-undef */
@@ -85,19 +86,19 @@ const toToken = (paging, style) => {
85
86
  "before" or "after" value. if that would change,
86
87
  we'd need to move toward a more simple: `!paging.before`
87
88
  */
88
- if (!Number.isNaN(paging === null || paging === void 0 ? void 0 : paging.before)) {
89
+ if (!Number.isNaN(Number(paging === null || paging === void 0 ? void 0 : paging.before))) {
89
90
  payload = {
90
91
  before: paging.before,
91
92
  last: paging.limit,
92
93
  };
93
94
  }
94
- else if (!Number.isNaN(paging === null || paging === void 0 ? void 0 : paging.after)) {
95
+ else if (!Number.isNaN(Number(paging === null || paging === void 0 ? void 0 : paging.after))) {
95
96
  payload = {
96
97
  after: paging.after,
97
98
  first: paging.limit,
98
99
  };
99
100
  }
100
- else if (!Number.isNaN(paging === null || paging === void 0 ? void 0 : paging.limit)) {
101
+ else if (!Number.isNaN(Number(paging === null || paging === void 0 ? void 0 : paging.limit))) {
101
102
  payload = {
102
103
  last: paging.limit,
103
104
  };
@@ -166,6 +167,121 @@ const toPageRaw = (token) => {
166
167
  return undefined;
167
168
  };
168
169
 
170
+ /** @hidden */
171
+ const idResolvers = {
172
+ user: ({ userId }) => userId,
173
+ file: ({ fileId }) => fileId,
174
+ role: ({ roleId }) => roleId,
175
+ channel: ({ channelId }) => channelId,
176
+ channelUsers: ({ channelId, userId }) => `${channelId}#${userId}`,
177
+ message: ({ messageId }) => messageId,
178
+ community: ({ communityId }) => communityId,
179
+ category: ({ categoryId }) => categoryId,
180
+ communityUsers: ({ communityId, userId }) => `${communityId}#${userId}`,
181
+ post: ({ postId }) => postId,
182
+ comment: ({ commentId }) => commentId,
183
+ poll: ({ pollId }) => pollId,
184
+ reaction: ({ reactionId }) => reactionId,
185
+ stream: ({ streamId }) => streamId,
186
+ follow: ({ from, to }) => `${from}#${to}`,
187
+ followCount: ({ userId }) => userId,
188
+ };
189
+ /**
190
+ * Retrieve the id resolver matching a domain name
191
+ *
192
+ * @param name the domain name for the resolve
193
+ * @returns an idResolver function for the given domain name
194
+ */
195
+ const getResolver = (name) => idResolvers[name];
196
+
197
+ /**
198
+ * Identification criterias
199
+ *
200
+ * As key, the name of the identified model ;
201
+ * As value, the list of properties to consider a given model as of type
202
+ *
203
+ * Used as source of truth for {@link identifyModel}
204
+ *
205
+ * @hidden
206
+ */
207
+ const CRITERIAS = {
208
+ file: ['fileId', 'attributes'],
209
+ user: ['userId', 'avatarFileId'],
210
+ role: ['roleId'],
211
+ channel: ['channelId', 'rateLimit'],
212
+ channelUsers: ['channelId', 'userId', 'membership'],
213
+ message: ['messageId'],
214
+ community: ['communityId', 'onlyAdminCanPost'],
215
+ category: ['categoryId'],
216
+ communityUsers: ['userId', 'communityId', 'communityMembership'],
217
+ post: ['postId', 'feedId'],
218
+ comment: ['commentId', 'referenceId'],
219
+ poll: ['pollId'],
220
+ reaction: ['reactionId'],
221
+ stream: ['streamId'],
222
+ follow: ['from', 'to'],
223
+ followCount: ['userId', 'followerCount'],
224
+ };
225
+ /** @hidden */
226
+ const hasKeys = (object, needles) => {
227
+ const haystack = Object.keys(object);
228
+ return needles.every(needle => haystack.includes(needle));
229
+ };
230
+ /**
231
+ * Finds the name of the store for a given unknown model
232
+ *
233
+ * @param model one of the {@link Amity.Model} to identify
234
+ * @returns the name of the corresponding store
235
+ */
236
+ const identifyModel = (model) => {
237
+ var _a;
238
+ // we cannot avoid "as" in here because Object.entries does not
239
+ // allow anything else than "string" as key in the iterator type
240
+ const criterias = Object.entries(CRITERIAS);
241
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
242
+ return (_a = criterias.find(([_, keys]) => hasKeys(model, keys))) === null || _a === void 0 ? void 0 : _a[0];
243
+ };
244
+ /*
245
+ * Identify the modal key for a model
246
+ * Used to get args for optimistic updates
247
+ * Example: createMessage: get messageId on optimistic message creation
248
+ *
249
+ * @param model to be recognized
250
+ * @returns model key array if one if found or undefined
251
+ */
252
+ const identifyModelKey = (model) => {
253
+ var _a;
254
+ const modalKey = identifyModel(model);
255
+ if (!modalKey) {
256
+ return undefined;
257
+ }
258
+ return (_a = CRITERIAS[modalKey]) === null || _a === void 0 ? void 0 : _a[0];
259
+ };
260
+
261
+ /**
262
+ * A map of v3 response keys to a store name.
263
+ * @hidden
264
+ */
265
+ const PAYLOAD2MODEL = {
266
+ users: 'user',
267
+ files: 'file',
268
+ roles: 'role',
269
+ channels: 'channel',
270
+ channelUsers: 'channelUsers',
271
+ messages: 'message',
272
+ communities: 'community',
273
+ categories: 'category',
274
+ communityUsers: 'communityUsers',
275
+ posts: 'post',
276
+ postChildren: 'post',
277
+ comments: 'comment',
278
+ polls: 'poll',
279
+ reactions: 'reaction',
280
+ videoStreamings: 'stream',
281
+ follows: 'follow',
282
+ followCounts: 'followCount',
283
+ };
284
+
169
285
  /* eslint-disable no-use-before-define */
170
286
  /**
171
287
  * Type guard to check and cast that a given async function is has the ".locally" property
@@ -310,7 +426,23 @@ const runQuery = ({ func, args }, callback, options = queryOptions('cache_then_s
310
426
  loading: true,
311
427
  }));
312
428
  }
313
- func(...args)
429
+ let optimisticArgs = args;
430
+ /* get args for optimistic method calls
431
+ *
432
+ * On optimistic updates, the modal key for the update needs to be passed to
433
+ * the server so as to avoid duplicate modal creation
434
+ *
435
+ * ex: on creating a new message pass the modalKey is messageId, pass this
436
+ * id onto the server so that a duplicate with seperate messageId is not
437
+ * created.
438
+ */
439
+ if (isMutator(func)) {
440
+ // @ts-ignore
441
+ const modelKey = local && local.data && identifyModelKey(local.data);
442
+ // @ts-ignore
443
+ optimisticArgs = modelKey ? [Object.assign(Object.assign({}, args[0]), { [modelKey]: local.data[modelKey] })] : args;
444
+ }
445
+ func(...optimisticArgs)
314
446
  .then(fresh => {
315
447
  // @ts-ignore i know.
316
448
  // isLocal(local) && syncInCache(local, fresh)
@@ -20203,57 +20335,6 @@ const onClientBanned = (callback) => {
20203
20335
  });
20204
20336
  };
20205
20337
 
20206
- /** @hidden */
20207
- const idResolvers = {
20208
- user: ({ userId }) => userId,
20209
- file: ({ fileId }) => fileId,
20210
- role: ({ roleId }) => roleId,
20211
- channel: ({ channelId }) => channelId,
20212
- channelUsers: ({ channelId, userId }) => `${channelId}#${userId}`,
20213
- message: ({ messageId }) => messageId,
20214
- community: ({ communityId }) => communityId,
20215
- category: ({ categoryId }) => categoryId,
20216
- communityUsers: ({ communityId, userId }) => `${communityId}#${userId}`,
20217
- post: ({ postId }) => postId,
20218
- comment: ({ commentId }) => commentId,
20219
- poll: ({ pollId }) => pollId,
20220
- reaction: ({ reactionId }) => reactionId,
20221
- stream: ({ streamId }) => streamId,
20222
- follow: ({ from, to }) => `${from}#${to}`,
20223
- followCount: ({ userId }) => userId,
20224
- };
20225
- /**
20226
- * Retrieve the id resolver matching a domain name
20227
- *
20228
- * @param name the domain name for the resolve
20229
- * @returns an idResolver function for the given domain name
20230
- */
20231
- const getResolver = (name) => idResolvers[name];
20232
-
20233
- /**
20234
- * A map of v3 response keys to a store name.
20235
- * @hidden
20236
- */
20237
- const PAYLOAD2MODEL = {
20238
- users: 'user',
20239
- files: 'file',
20240
- roles: 'role',
20241
- channels: 'channel',
20242
- channelUsers: 'channelUsers',
20243
- messages: 'message',
20244
- communities: 'community',
20245
- categories: 'category',
20246
- communityUsers: 'communityUsers',
20247
- posts: 'post',
20248
- postChildren: 'post',
20249
- comments: 'comment',
20250
- polls: 'poll',
20251
- reactions: 'reaction',
20252
- videoStreamings: 'stream',
20253
- follows: 'follow',
20254
- followCounts: 'followCount',
20255
- };
20256
-
20257
20338
  /**
20258
20339
  * Ingest a payload (v3) into the cache
20259
20340
  *
@@ -20327,7 +20408,7 @@ const onUserDeleted = (callback) => createUserEventSubscriber('user.deleted', ca
20327
20408
  * @category Client API
20328
20409
  * @async
20329
20410
  */
20330
- const connectClient = async (params) => {
20411
+ const connectClient = async (params, config) => {
20331
20412
  var _a;
20332
20413
  const client = getActiveClient();
20333
20414
  client.log('client/api/connectClient', Object.assign({ apiKey: client.apiKey }, params));
@@ -20352,7 +20433,9 @@ const connectClient = async (params) => {
20352
20433
  client.userId = params.userId;
20353
20434
  client.accessToken = accessToken;
20354
20435
  setActiveUser(users[0]);
20355
- subscribeTopic(getNetworkTopic());
20436
+ if ((config === null || config === void 0 ? void 0 : config.disableRTE) !== true) {
20437
+ subscribeTopic(getNetworkTopic());
20438
+ }
20356
20439
  const subscriptions = [
20357
20440
  onClientBanned(() => {
20358
20441
  disconnectClient();
@@ -21298,6 +21381,8 @@ queryMessages.locally = (query) => {
21298
21381
  : undefined;
21299
21382
  };
21300
21383
 
21384
+ const uuid = () => nativeIdGenerator.v4().toString();
21385
+
21301
21386
  /**
21302
21387
  * ```js
21303
21388
  * import { createMessage } from '@amityco/ts-sdk'
@@ -21348,12 +21433,23 @@ const createMessage = async (bundle) => {
21348
21433
  createMessage.optimistically = (bundle) => {
21349
21434
  var _a, _b;
21350
21435
  const client = getActiveClient();
21351
- client.log('user/createMessage.locally', bundle);
21352
21436
  if (!client.cache)
21353
21437
  return;
21354
- const channel = pullFromCache(['channel', 'get', bundle.channelId]);
21355
- upsertInCache(['channel', 'get', bundle.channelId], Object.assign(Object.assign({}, channel === null || channel === void 0 ? void 0 : channel.data), { messageCount: ((_a = channel === null || channel === void 0 ? void 0 : channel.data.messageCount) !== null && _a !== void 0 ? _a : 0) + 1 }));
21356
- const message = Object.assign({ messageId: Math.random().toString(16), userId: client.userId, channelSegment: ((_b = channel === null || channel === void 0 ? void 0 : channel.data.messageCount) !== null && _b !== void 0 ? _b : 0) + 1, createdAt: new Date().toISOString() }, bundle);
21438
+ /*
21439
+ * when creating messages optimistically a messageId needs to be added by the
21440
+ * client, created a new variable so as to allow backward compatibility of API
21441
+ *
21442
+ * Updated to handle client requirement to add messageId while uploading
21443
+ * message with image. Temporary!
21444
+ */
21445
+ const bundleWithMessageId = Object.assign({ messageId: uuid() }, bundle);
21446
+ // only log if cache is enabled
21447
+ client.log('user/createMessage.locally', bundleWithMessageId);
21448
+ const channel = pullFromCache(['channel', 'get', bundleWithMessageId.channelId]);
21449
+ upsertInCache(['channel', 'get', bundleWithMessageId.channelId], Object.assign(Object.assign({}, channel === null || channel === void 0 ? void 0 : channel.data), { messageCount: ((_a = channel === null || channel === void 0 ? void 0 : channel.data.messageCount) !== null && _a !== void 0 ? _a : 0) + 1 }));
21450
+ // as reused to update created and updated time, which should be the same
21451
+ const createdTime = new Date().toISOString();
21452
+ const message = Object.assign({ userId: client.userId, channelSegment: ((_b = channel === null || channel === void 0 ? void 0 : channel.data.messageCount) !== null && _b !== void 0 ? _b : 0) + 1, createdAt: createdTime, updatedAt: createdTime }, bundleWithMessageId);
21357
21453
  pushToCache(['message', 'get', message.messageId], message, { cachedAt: -1 });
21358
21454
  fireEvent('v3.message.didCreate', { messages: [message] });
21359
21455
  return {
@@ -22414,6 +22510,10 @@ const queryComments = async (query) => {
22414
22510
  const client = getActiveClient();
22415
22511
  client.log('comment/queryComments', query);
22416
22512
  const { page = { limit: 10 } } = query, params = __rest(query, ["page"]);
22513
+ const options = {
22514
+ type: params.sortBy ? 'pagination' : undefined,
22515
+ token: toToken(page, params.sortBy ? 'skiplimit' : 'afterbefore'),
22516
+ };
22417
22517
  // const filterByParentId = query.parentId !== undefined
22418
22518
  // API-FIX: parameters should be querystring. (1)
22419
22519
  // API-FIX: backend should answer Amity.Response (2)
@@ -22421,9 +22521,7 @@ const queryComments = async (query) => {
22421
22521
  const { data } = await client.http.get(`/api/v3/comments`, {
22422
22522
  params: Object.assign(Object.assign({}, params), {
22423
22523
  // filterByParentId, API-FIX: backend does not support this boolean LOL. what the hell seriously.
22424
- options: {
22425
- token: toToken(page, 'afterbefore'),
22426
- } }),
22524
+ options }),
22427
22525
  });
22428
22526
  // API-FIX: backend should answer Amity.Response (2)
22429
22527
  // const { paging, comments } = unwrapPayload(data)
@@ -22758,6 +22856,38 @@ const preparePayloadForCache = (event, payload) => {
22758
22856
  }
22759
22857
  };
22760
22858
 
22859
+ /** @hidden */
22860
+ /*
22861
+ * @param message payload from http request without myReactions
22862
+ * add myReactions to http response if the event was a reaction event
22863
+ */
22864
+ const prepareMessagePayloadForCache = (payload) => {
22865
+ const client = getActiveClient();
22866
+ const cached = pullFromCache(['message', 'get', payload.messageId]);
22867
+ // '[]' in cases where the new reaction is the first one
22868
+ const myReactions = (cached === null || cached === void 0 ? void 0 : cached.data.myReactions) || [];
22869
+ // add myReactions to the payload
22870
+ Object.assign(payload, { myReactions });
22871
+ // check if there are any updates to the reactions
22872
+ const latestReaction = payload === null || payload === void 0 ? void 0 : payload.latestReaction;
22873
+ const isLatestReactionMine = latestReaction && latestReaction.userId === client.userId;
22874
+ if (!isLatestReactionMine) {
22875
+ return;
22876
+ }
22877
+ // new reaction added
22878
+ if (latestReaction.eventName === 'add' && !myReactions.includes(latestReaction.reactionName)) {
22879
+ Object.assign(payload, {
22880
+ myReactions: [...myReactions, latestReaction.reactionName],
22881
+ });
22882
+ }
22883
+ // existing reaction removed
22884
+ if (latestReaction.eventName === 'remove' && myReactions.includes(latestReaction.reactionName)) {
22885
+ Object.assign(payload, {
22886
+ myReactions: myReactions.filter(x => x !== latestReaction.reactionName),
22887
+ });
22888
+ }
22889
+ };
22890
+
22761
22891
  /**
22762
22892
  * ```js
22763
22893
  * import { addReaction } from '@amityco/ts-sdk'
@@ -23806,9 +23936,9 @@ const leaveChannel = async (channelId) => {
23806
23936
  const queryChannelMembers = async (query) => {
23807
23937
  const client = getActiveClient();
23808
23938
  client.log('channel/queryChannelMembers', query);
23809
- const _a = query !== null && query !== void 0 ? query : {}, { page, channelId, membership } = _a, params = __rest(_a, ["page", "channelId", "membership"]);
23810
- const { data } = await client.http.get(`/api/v3/channels/${encodeURIComponent(channelId)}/users`, {
23811
- params: Object.assign(Object.assign({}, params), { filter: membership, options: {
23939
+ const _a = query !== null && query !== void 0 ? query : {}, { page, channelId } = _a, params = __rest(_a, ["page", "channelId"]);
23940
+ const { data } = await client.http.get(`/api/v4/channels/${encodeURIComponent(channelId)}/users`, {
23941
+ params: Object.assign(Object.assign({}, params), { options: {
23812
23942
  token: toToken(page, 'skiplimit'),
23813
23943
  } }),
23814
23944
  });
@@ -24179,7 +24309,12 @@ const onMessageUpdated = (callback) => {
24179
24309
  const client = getActiveClient();
24180
24310
  const filter = (payload) => {
24181
24311
  ingestInCache(payload);
24182
- callback(payload.messages[0]);
24312
+ const message = payload.messages[0];
24313
+ // if payload does not have myReactions
24314
+ if (!(message === null || message === void 0 ? void 0 : message.myReactions)) {
24315
+ prepareMessagePayloadForCache(message);
24316
+ }
24317
+ callback(message);
24183
24318
  };
24184
24319
  return createEventSubscriber(client, 'message/onMessageUpdated', 'v3.message.didUpdate', filter);
24185
24320
  };