@webex/internal-plugin-conversation 2.59.2 → 2.59.3-next.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.
Files changed (48) hide show
  1. package/.eslintrc.js +6 -6
  2. package/README.md +47 -47
  3. package/babel.config.js +3 -3
  4. package/dist/activities.js +4 -4
  5. package/dist/activities.js.map +1 -1
  6. package/dist/activity-thread-ordering.js +34 -34
  7. package/dist/activity-thread-ordering.js.map +1 -1
  8. package/dist/config.js +12 -12
  9. package/dist/config.js.map +1 -1
  10. package/dist/constants.js.map +1 -1
  11. package/dist/conversation.js +474 -474
  12. package/dist/conversation.js.map +1 -1
  13. package/dist/convo-error.js +4 -4
  14. package/dist/convo-error.js.map +1 -1
  15. package/dist/decryption-transforms.js +155 -155
  16. package/dist/decryption-transforms.js.map +1 -1
  17. package/dist/encryption-transforms.js.map +1 -1
  18. package/dist/index.js +2 -2
  19. package/dist/index.js.map +1 -1
  20. package/dist/share-activity.js +57 -57
  21. package/dist/share-activity.js.map +1 -1
  22. package/dist/to-array.js +7 -7
  23. package/dist/to-array.js.map +1 -1
  24. package/jest.config.js +3 -3
  25. package/package.json +21 -20
  26. package/process +1 -1
  27. package/src/activities.js +157 -157
  28. package/src/activity-thread-ordering.js +283 -283
  29. package/src/activity-threading.md +282 -282
  30. package/src/config.js +37 -37
  31. package/src/constants.js +3 -3
  32. package/src/conversation.js +2535 -2535
  33. package/src/convo-error.js +15 -15
  34. package/src/decryption-transforms.js +541 -541
  35. package/src/encryption-transforms.js +345 -345
  36. package/src/index.js +327 -327
  37. package/src/share-activity.js +436 -436
  38. package/src/to-array.js +29 -29
  39. package/test/integration/spec/create.js +290 -290
  40. package/test/integration/spec/encryption.js +333 -333
  41. package/test/integration/spec/get.js +1255 -1255
  42. package/test/integration/spec/mercury.js +94 -94
  43. package/test/integration/spec/share.js +537 -537
  44. package/test/integration/spec/verbs.js +1041 -1041
  45. package/test/unit/spec/conversation.js +823 -823
  46. package/test/unit/spec/decrypt-transforms.js +460 -460
  47. package/test/unit/spec/encryption-transforms.js +93 -93
  48. package/test/unit/spec/share-activity.js +178 -178
@@ -1,283 +1,283 @@
1
- import {last} from 'lodash';
2
-
3
- import {
4
- ACTIVITY_TYPES,
5
- getParentId,
6
- isNewer,
7
- getActivityType,
8
- sortActivitiesByPublishedDate,
9
- NEWER,
10
- OLDER,
11
- INITIAL,
12
- MID,
13
- } from './activities';
14
-
15
- export const defaultMinDisplayableActivities = 20;
16
- export const minBatchSize = 10;
17
- export const fetchLoopCountMax = 100;
18
- export const batchSizeIncrementCount = 10;
19
-
20
- // use accessors for ease of refactoring underlying implementation
21
- /**
22
- * @param {Map} destination destination map object for data. Currently a Map, but could be refactored to use any type.
23
- * @param {string} key
24
- * @param {any} value
25
- * @returns {Map}
26
- */
27
- export const setValue = (destination, key, value) => destination.set(key, value);
28
- /**
29
- * @param {Map} source source map object to access. Currently expects a Map, but could be refactored to use any type
30
- * @param {string} key
31
- * @returns {Map}
32
- */
33
- export const getValue = (source, key) => source.get(key);
34
-
35
- export const getActivityObjectsFromMap = (hashMap) =>
36
- Array.from(hashMap).map(([, activity]) => activity);
37
- /**
38
- * creates maps for various activity types and defines handlers for working with stored activities
39
- * utilizes revealing module pattern to close over state and only expose certain necessary functions for altering state
40
- * @function
41
- * @returns {object}
42
- * getActivityHandlerByKey(activityType) - accepts a key to map to a defined activity handler
43
- * getActivityByTypeAndParentId(activityType, parentId) accepts a key and a parent ID to return an activity of that type whose parent is the parentId
44
- */
45
- export const activityManager = () => {
46
- const replyActivityHash = new Map();
47
- const editActivityHash = new Map();
48
- const reactionActivityHash = new Map();
49
- const reactionSelfActivityHash = new Map();
50
-
51
- const handleNewReply = (replyAct) => {
52
- const replyParentId = getParentId(replyAct);
53
- const existingReplyHash = getValue(replyActivityHash, replyParentId);
54
-
55
- if (existingReplyHash) {
56
- setValue(existingReplyHash, replyAct.id, replyAct);
57
- } else {
58
- const replyHash = new Map();
59
-
60
- setValue(replyHash, replyAct.id, replyAct);
61
- setValue(replyActivityHash, replyParentId, replyHash);
62
- }
63
- };
64
-
65
- const handleNewEdit = (editAct) => {
66
- const isTombstone = editAct.verb === ACTIVITY_TYPES.TOMBSTONE;
67
-
68
- // we can ignore tombstone edits in favor of the newer one
69
- if (isTombstone) {
70
- return;
71
- }
72
-
73
- const editParentId = getParentId(editAct);
74
- const existingEdit = getValue(editActivityHash, editParentId);
75
-
76
- // edited activity must be newer than what we already have
77
- if (!existingEdit || isNewer(editAct, existingEdit)) {
78
- setValue(editActivityHash, editParentId, editAct);
79
- }
80
- };
81
-
82
- // logic is identical between reactions and reaction selfs, so handler simply passes the activity and the correct hash
83
- const reactionHelper = (reactionAct, hash) => {
84
- const reactionParentId = getParentId(reactionAct);
85
- const existingReaction = getValue(hash, reactionParentId);
86
-
87
- // reaction activity must be newer than what we already have
88
- if (!existingReaction || isNewer(reactionAct, existingReaction)) {
89
- setValue(hash, reactionParentId, reactionAct);
90
- }
91
- };
92
-
93
- const handleNewReaction = (reactionAct) => {
94
- reactionHelper(reactionAct, reactionActivityHash);
95
- };
96
-
97
- const handleNewReactionSelf = (reactionSelfAct) => {
98
- reactionHelper(reactionSelfAct, reactionSelfActivityHash);
99
- };
100
-
101
- const getActivityHandlerByKey = (key) =>
102
- ({
103
- [ACTIVITY_TYPES.REACTION]: handleNewReaction,
104
- [ACTIVITY_TYPES.REACTION_SELF]: handleNewReactionSelf,
105
- [ACTIVITY_TYPES.EDIT]: handleNewEdit,
106
- [ACTIVITY_TYPES.REPLY]: handleNewReply,
107
- }[key]);
108
-
109
- const getActivityByTypeAndParentId = (type, id) =>
110
- ({
111
- [ACTIVITY_TYPES.EDIT]: getValue(editActivityHash, id),
112
- [ACTIVITY_TYPES.REPLY]: getValue(replyActivityHash, id),
113
- [ACTIVITY_TYPES.REACTION]: getValue(reactionActivityHash, id),
114
- [ACTIVITY_TYPES.REACTION_SELF]: getValue(reactionSelfActivityHash, id),
115
- }[type]);
116
-
117
- return {
118
- getActivityHandlerByKey,
119
- getActivityByTypeAndParentId,
120
- };
121
- };
122
-
123
- /**
124
- * encapsulates state and logic for managing oldest and newest activities
125
- * @returns {object} setters and getters for activity state management
126
- */
127
- export const bookendManager = () => {
128
- // keep track of generator state, like what our current oldest & newest activities are
129
- let oldestAct;
130
- let newestAct;
131
-
132
- const getOldestAct = () => oldestAct;
133
- const getNewestAct = () => newestAct;
134
-
135
- const setOldestAct = (act) => {
136
- if (!oldestAct) {
137
- oldestAct = act;
138
- } else if (isNewer(oldestAct, act)) {
139
- oldestAct = act;
140
- }
141
- };
142
-
143
- const setNewestAct = (act) => {
144
- if (!newestAct) {
145
- newestAct = act;
146
- } else if (isNewer(act, newestAct)) {
147
- newestAct = act;
148
- }
149
- };
150
-
151
- const setBookends = (activities) => {
152
- const oldestActsFirst = sortActivitiesByPublishedDate(activities);
153
-
154
- const newestInBatch = last(oldestActsFirst);
155
- const oldestInBatch = oldestActsFirst[0];
156
-
157
- setOldestAct(oldestInBatch);
158
- setNewestAct(newestInBatch);
159
- };
160
-
161
- return {
162
- setBookends,
163
- getNewestAct,
164
- getOldestAct,
165
- };
166
- };
167
-
168
- /**
169
- * encapsulates state and logic for when there are no more fetchable activities from convo
170
- * @returns {object} setters and getters for no more activities logic
171
- */
172
- export const noMoreActivitiesManager = () => {
173
- // used to determine if we should continue to fetch older activities
174
- // must be set per iteration, as querying newer activities is still valid when all end of convo has been reached
175
- let noMoreActs = false;
176
- let noOlderActs = false;
177
- let noNewerActs = false;
178
-
179
- const getNoMoreActs = () => noMoreActs;
180
-
181
- const checkAndSetNoOlderActs = (act) => {
182
- if (!noOlderActs && getActivityType(act) === ACTIVITY_TYPES.CREATE) {
183
- noOlderActs = true;
184
- }
185
- };
186
-
187
- const checkAndSetNoNewerActs = (activities) => {
188
- if (!activities || !activities.length) {
189
- noNewerActs = true;
190
- }
191
- };
192
-
193
- const checkAndSetNoMoreActs = (queryType, visibleActs, currentBatchSize) => {
194
- if (
195
- (queryType === NEWER && noNewerActs) ||
196
- ((queryType === OLDER || queryType === INITIAL) && noOlderActs) ||
197
- (queryType === MID && visibleActs < currentBatchSize && noOlderActs)
198
- ) {
199
- noMoreActs = true;
200
- }
201
- };
202
-
203
- return {
204
- getNoMoreActs,
205
- checkAndSetNoMoreActs,
206
- checkAndSetNoNewerActs,
207
- checkAndSetNoOlderActs,
208
- };
209
- };
210
-
211
- /**
212
- * encapsulates state and logic for managing root activities
213
- * @returns {object} setters and getters for activity state management
214
- */
215
- export const rootActivityManager = () => {
216
- const rootActivityHash = new Map();
217
-
218
- const addNewRoot = (rootAct) => {
219
- setValue(rootActivityHash, rootAct.id, rootAct);
220
- };
221
-
222
- const getRootActivityHash = () => rootActivityHash;
223
-
224
- return {
225
- addNewRoot,
226
- getRootActivityHash,
227
- };
228
- };
229
-
230
- export const getLoopCounterFailsafe = () => {
231
- let fetchLoopCount = 0;
232
-
233
- return () => {
234
- fetchLoopCount += 1;
235
- if (fetchLoopCount > fetchLoopCountMax) {
236
- throw new Error('max fetches reached');
237
- }
238
- };
239
- };
240
-
241
- /**
242
- * creates activity query object
243
- * @param {string} type type of query to create
244
- * @param {object} queryOptions options to define query
245
- * @param {string} [queryOptions.newestPublishedDate] the date of the newest fetched activity
246
- * @param {string} [queryOptions.oldestPublishedDate] the date of the oldest fetched activity
247
- * @param {number} [queryOptions.batchSize] the number of activities to query
248
- * @param {object} [queryOptions.activityToSearch] a server activity to use to build middate query
249
- * @returns {object}
250
- */
251
- export const getQuery = (type, queryOptions) => {
252
- const {newestPublishedDate, oldestPublishedDate, batchSize, activityToSearch = {}} = queryOptions;
253
-
254
- switch (type) {
255
- case NEWER: {
256
- const sinceDate = newestPublishedDate + 1;
257
- const lastActivityFirst = false;
258
-
259
- return {sinceDate, lastActivityFirst};
260
- }
261
- case MID: {
262
- const searchType = getActivityType(activityToSearch);
263
- let midDate;
264
-
265
- if (searchType === ACTIVITY_TYPES.REPLY || searchType === ACTIVITY_TYPES.EDIT) {
266
- midDate = activityToSearch.parent.published;
267
- } else {
268
- midDate = activityToSearch.published;
269
- }
270
-
271
- return {midDate, limit: batchSize};
272
- }
273
- case OLDER: {
274
- const maxDate = oldestPublishedDate - 1;
275
-
276
- return {maxDate};
277
- }
278
- case INITIAL:
279
- default: {
280
- return {};
281
- }
282
- }
283
- };
1
+ import {last} from 'lodash';
2
+
3
+ import {
4
+ ACTIVITY_TYPES,
5
+ getParentId,
6
+ isNewer,
7
+ getActivityType,
8
+ sortActivitiesByPublishedDate,
9
+ NEWER,
10
+ OLDER,
11
+ INITIAL,
12
+ MID,
13
+ } from './activities';
14
+
15
+ export const defaultMinDisplayableActivities = 20;
16
+ export const minBatchSize = 10;
17
+ export const fetchLoopCountMax = 100;
18
+ export const batchSizeIncrementCount = 10;
19
+
20
+ // use accessors for ease of refactoring underlying implementation
21
+ /**
22
+ * @param {Map} destination destination map object for data. Currently a Map, but could be refactored to use any type.
23
+ * @param {string} key
24
+ * @param {any} value
25
+ * @returns {Map}
26
+ */
27
+ export const setValue = (destination, key, value) => destination.set(key, value);
28
+ /**
29
+ * @param {Map} source source map object to access. Currently expects a Map, but could be refactored to use any type
30
+ * @param {string} key
31
+ * @returns {Map}
32
+ */
33
+ export const getValue = (source, key) => source.get(key);
34
+
35
+ export const getActivityObjectsFromMap = (hashMap) =>
36
+ Array.from(hashMap).map(([, activity]) => activity);
37
+ /**
38
+ * creates maps for various activity types and defines handlers for working with stored activities
39
+ * utilizes revealing module pattern to close over state and only expose certain necessary functions for altering state
40
+ * @function
41
+ * @returns {object}
42
+ * getActivityHandlerByKey(activityType) - accepts a key to map to a defined activity handler
43
+ * getActivityByTypeAndParentId(activityType, parentId) accepts a key and a parent ID to return an activity of that type whose parent is the parentId
44
+ */
45
+ export const activityManager = () => {
46
+ const replyActivityHash = new Map();
47
+ const editActivityHash = new Map();
48
+ const reactionActivityHash = new Map();
49
+ const reactionSelfActivityHash = new Map();
50
+
51
+ const handleNewReply = (replyAct) => {
52
+ const replyParentId = getParentId(replyAct);
53
+ const existingReplyHash = getValue(replyActivityHash, replyParentId);
54
+
55
+ if (existingReplyHash) {
56
+ setValue(existingReplyHash, replyAct.id, replyAct);
57
+ } else {
58
+ const replyHash = new Map();
59
+
60
+ setValue(replyHash, replyAct.id, replyAct);
61
+ setValue(replyActivityHash, replyParentId, replyHash);
62
+ }
63
+ };
64
+
65
+ const handleNewEdit = (editAct) => {
66
+ const isTombstone = editAct.verb === ACTIVITY_TYPES.TOMBSTONE;
67
+
68
+ // we can ignore tombstone edits in favor of the newer one
69
+ if (isTombstone) {
70
+ return;
71
+ }
72
+
73
+ const editParentId = getParentId(editAct);
74
+ const existingEdit = getValue(editActivityHash, editParentId);
75
+
76
+ // edited activity must be newer than what we already have
77
+ if (!existingEdit || isNewer(editAct, existingEdit)) {
78
+ setValue(editActivityHash, editParentId, editAct);
79
+ }
80
+ };
81
+
82
+ // logic is identical between reactions and reaction selfs, so handler simply passes the activity and the correct hash
83
+ const reactionHelper = (reactionAct, hash) => {
84
+ const reactionParentId = getParentId(reactionAct);
85
+ const existingReaction = getValue(hash, reactionParentId);
86
+
87
+ // reaction activity must be newer than what we already have
88
+ if (!existingReaction || isNewer(reactionAct, existingReaction)) {
89
+ setValue(hash, reactionParentId, reactionAct);
90
+ }
91
+ };
92
+
93
+ const handleNewReaction = (reactionAct) => {
94
+ reactionHelper(reactionAct, reactionActivityHash);
95
+ };
96
+
97
+ const handleNewReactionSelf = (reactionSelfAct) => {
98
+ reactionHelper(reactionSelfAct, reactionSelfActivityHash);
99
+ };
100
+
101
+ const getActivityHandlerByKey = (key) =>
102
+ ({
103
+ [ACTIVITY_TYPES.REACTION]: handleNewReaction,
104
+ [ACTIVITY_TYPES.REACTION_SELF]: handleNewReactionSelf,
105
+ [ACTIVITY_TYPES.EDIT]: handleNewEdit,
106
+ [ACTIVITY_TYPES.REPLY]: handleNewReply,
107
+ }[key]);
108
+
109
+ const getActivityByTypeAndParentId = (type, id) =>
110
+ ({
111
+ [ACTIVITY_TYPES.EDIT]: getValue(editActivityHash, id),
112
+ [ACTIVITY_TYPES.REPLY]: getValue(replyActivityHash, id),
113
+ [ACTIVITY_TYPES.REACTION]: getValue(reactionActivityHash, id),
114
+ [ACTIVITY_TYPES.REACTION_SELF]: getValue(reactionSelfActivityHash, id),
115
+ }[type]);
116
+
117
+ return {
118
+ getActivityHandlerByKey,
119
+ getActivityByTypeAndParentId,
120
+ };
121
+ };
122
+
123
+ /**
124
+ * encapsulates state and logic for managing oldest and newest activities
125
+ * @returns {object} setters and getters for activity state management
126
+ */
127
+ export const bookendManager = () => {
128
+ // keep track of generator state, like what our current oldest & newest activities are
129
+ let oldestAct;
130
+ let newestAct;
131
+
132
+ const getOldestAct = () => oldestAct;
133
+ const getNewestAct = () => newestAct;
134
+
135
+ const setOldestAct = (act) => {
136
+ if (!oldestAct) {
137
+ oldestAct = act;
138
+ } else if (isNewer(oldestAct, act)) {
139
+ oldestAct = act;
140
+ }
141
+ };
142
+
143
+ const setNewestAct = (act) => {
144
+ if (!newestAct) {
145
+ newestAct = act;
146
+ } else if (isNewer(act, newestAct)) {
147
+ newestAct = act;
148
+ }
149
+ };
150
+
151
+ const setBookends = (activities) => {
152
+ const oldestActsFirst = sortActivitiesByPublishedDate(activities);
153
+
154
+ const newestInBatch = last(oldestActsFirst);
155
+ const oldestInBatch = oldestActsFirst[0];
156
+
157
+ setOldestAct(oldestInBatch);
158
+ setNewestAct(newestInBatch);
159
+ };
160
+
161
+ return {
162
+ setBookends,
163
+ getNewestAct,
164
+ getOldestAct,
165
+ };
166
+ };
167
+
168
+ /**
169
+ * encapsulates state and logic for when there are no more fetchable activities from convo
170
+ * @returns {object} setters and getters for no more activities logic
171
+ */
172
+ export const noMoreActivitiesManager = () => {
173
+ // used to determine if we should continue to fetch older activities
174
+ // must be set per iteration, as querying newer activities is still valid when all end of convo has been reached
175
+ let noMoreActs = false;
176
+ let noOlderActs = false;
177
+ let noNewerActs = false;
178
+
179
+ const getNoMoreActs = () => noMoreActs;
180
+
181
+ const checkAndSetNoOlderActs = (act) => {
182
+ if (!noOlderActs && getActivityType(act) === ACTIVITY_TYPES.CREATE) {
183
+ noOlderActs = true;
184
+ }
185
+ };
186
+
187
+ const checkAndSetNoNewerActs = (activities) => {
188
+ if (!activities || !activities.length) {
189
+ noNewerActs = true;
190
+ }
191
+ };
192
+
193
+ const checkAndSetNoMoreActs = (queryType, visibleActs, currentBatchSize) => {
194
+ if (
195
+ (queryType === NEWER && noNewerActs) ||
196
+ ((queryType === OLDER || queryType === INITIAL) && noOlderActs) ||
197
+ (queryType === MID && visibleActs < currentBatchSize && noOlderActs)
198
+ ) {
199
+ noMoreActs = true;
200
+ }
201
+ };
202
+
203
+ return {
204
+ getNoMoreActs,
205
+ checkAndSetNoMoreActs,
206
+ checkAndSetNoNewerActs,
207
+ checkAndSetNoOlderActs,
208
+ };
209
+ };
210
+
211
+ /**
212
+ * encapsulates state and logic for managing root activities
213
+ * @returns {object} setters and getters for activity state management
214
+ */
215
+ export const rootActivityManager = () => {
216
+ const rootActivityHash = new Map();
217
+
218
+ const addNewRoot = (rootAct) => {
219
+ setValue(rootActivityHash, rootAct.id, rootAct);
220
+ };
221
+
222
+ const getRootActivityHash = () => rootActivityHash;
223
+
224
+ return {
225
+ addNewRoot,
226
+ getRootActivityHash,
227
+ };
228
+ };
229
+
230
+ export const getLoopCounterFailsafe = () => {
231
+ let fetchLoopCount = 0;
232
+
233
+ return () => {
234
+ fetchLoopCount += 1;
235
+ if (fetchLoopCount > fetchLoopCountMax) {
236
+ throw new Error('max fetches reached');
237
+ }
238
+ };
239
+ };
240
+
241
+ /**
242
+ * creates activity query object
243
+ * @param {string} type type of query to create
244
+ * @param {object} queryOptions options to define query
245
+ * @param {string} [queryOptions.newestPublishedDate] the date of the newest fetched activity
246
+ * @param {string} [queryOptions.oldestPublishedDate] the date of the oldest fetched activity
247
+ * @param {number} [queryOptions.batchSize] the number of activities to query
248
+ * @param {object} [queryOptions.activityToSearch] a server activity to use to build middate query
249
+ * @returns {object}
250
+ */
251
+ export const getQuery = (type, queryOptions) => {
252
+ const {newestPublishedDate, oldestPublishedDate, batchSize, activityToSearch = {}} = queryOptions;
253
+
254
+ switch (type) {
255
+ case NEWER: {
256
+ const sinceDate = newestPublishedDate + 1;
257
+ const lastActivityFirst = false;
258
+
259
+ return {sinceDate, lastActivityFirst};
260
+ }
261
+ case MID: {
262
+ const searchType = getActivityType(activityToSearch);
263
+ let midDate;
264
+
265
+ if (searchType === ACTIVITY_TYPES.REPLY || searchType === ACTIVITY_TYPES.EDIT) {
266
+ midDate = activityToSearch.parent.published;
267
+ } else {
268
+ midDate = activityToSearch.published;
269
+ }
270
+
271
+ return {midDate, limit: batchSize};
272
+ }
273
+ case OLDER: {
274
+ const maxDate = oldestPublishedDate - 1;
275
+
276
+ return {maxDate};
277
+ }
278
+ case INITIAL:
279
+ default: {
280
+ return {};
281
+ }
282
+ }
283
+ };