@webex/internal-plugin-conversation 3.0.0-beta.9 → 3.0.0-bnr.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.
Files changed (57) hide show
  1. package/README.md +1 -3
  2. package/dist/activities.js +8 -69
  3. package/dist/activities.js.map +1 -1
  4. package/dist/activity-thread-ordering.js +19 -79
  5. package/dist/activity-thread-ordering.js.map +1 -1
  6. package/dist/config.js +1 -7
  7. package/dist/config.js.map +1 -1
  8. package/dist/constants.js +4 -5
  9. package/dist/constants.js.map +1 -1
  10. package/dist/conversation.js +790 -1199
  11. package/dist/conversation.js.map +1 -1
  12. package/dist/convo-error.js +0 -23
  13. package/dist/convo-error.js.map +1 -1
  14. package/dist/decryption-transforms.js +35 -98
  15. package/dist/decryption-transforms.js.map +1 -1
  16. package/dist/encryption-transforms.js +11 -48
  17. package/dist/encryption-transforms.js.map +1 -1
  18. package/dist/index.js +7 -50
  19. package/dist/index.js.map +1 -1
  20. package/dist/internal-plugin-conversation.d.ts +21 -0
  21. package/dist/share-activity.js +40 -106
  22. package/dist/share-activity.js.map +1 -1
  23. package/dist/to-array.js +9 -11
  24. package/dist/to-array.js.map +1 -1
  25. package/dist/tsdoc-metadata.json +11 -0
  26. package/dist/types/activities.d.ts +32 -0
  27. package/dist/types/activity-thread-ordering.d.ts +18 -0
  28. package/dist/types/config.d.ts +19 -0
  29. package/dist/types/constants.d.ts +5 -0
  30. package/dist/types/conversation.d.ts +2 -0
  31. package/dist/types/convo-error.d.ts +10 -0
  32. package/dist/types/decryption-transforms.d.ts +1 -0
  33. package/dist/types/encryption-transforms.d.ts +1 -0
  34. package/dist/types/index.d.ts +3 -0
  35. package/dist/types/share-activity.d.ts +7 -0
  36. package/dist/types/to-array.d.ts +9 -0
  37. package/package.json +15 -15
  38. package/src/activities.js +10 -7
  39. package/src/activity-thread-ordering.js +27 -30
  40. package/src/activity-threading.md +68 -49
  41. package/src/config.js +5 -5
  42. package/src/conversation.js +621 -589
  43. package/src/decryption-transforms.js +103 -62
  44. package/src/encryption-transforms.js +103 -83
  45. package/src/index.js +82 -66
  46. package/src/share-activity.js +64 -55
  47. package/src/to-array.js +2 -2
  48. package/test/integration/spec/create.js +184 -118
  49. package/test/integration/spec/encryption.js +250 -186
  50. package/test/integration/spec/get.js +761 -513
  51. package/test/integration/spec/mercury.js +37 -27
  52. package/test/integration/spec/share.js +292 -229
  53. package/test/integration/spec/verbs.js +628 -441
  54. package/test/unit/spec/conversation.js +265 -163
  55. package/test/unit/spec/decrypt-transforms.js +112 -131
  56. package/test/unit/spec/encryption-transforms.js +24 -18
  57. package/test/unit/spec/share-activity.js +37 -40
@@ -0,0 +1,19 @@
1
+ declare namespace _default {
2
+ namespace conversation {
3
+ const allowedInboundTags: {
4
+ 'webex-mention': string[];
5
+ };
6
+ const allowedOutboundTags: {
7
+ 'webex-mention': string[];
8
+ };
9
+ function inboundProcessFunc(): void;
10
+ function outboundProcessFunc(): void;
11
+ const allowedInboundStyles: any[];
12
+ const allowedOutboundStyles: any[];
13
+ const thumbnailMaxHeight: number;
14
+ const thumbnailMaxWidth: number;
15
+ const keepEncryptedProperties: boolean;
16
+ const decryptionFailureMessage: string;
17
+ }
18
+ }
19
+ export default _default;
@@ -0,0 +1,5 @@
1
+ export const KEY_ROTATION_REQUIRED: 1400087;
2
+ export const KEY_ALREADY_ROTATED: 1409004;
3
+ export const ENCRYPTION_KEY_URL_MISMATCH: 1400049;
4
+ export const DEFAULT_CLUSTER: "urn:TEAM:us-east-2_a";
5
+ export const DEFAULT_CLUSTER_SERVICE: "identityLookup";
@@ -0,0 +1,2 @@
1
+ export default Conversation;
2
+ declare const Conversation: any;
@@ -0,0 +1,10 @@
1
+ /**
2
+ * General conversation error
3
+ */
4
+ export class ConversationError {
5
+ }
6
+ /**
7
+ * InvalidUserCreation thrown when failed to create conversation with invalid user
8
+ */
9
+ export class InvalidUserCreation extends ConversationError {
10
+ }
@@ -0,0 +1 @@
1
+ export const transforms: any[];
@@ -0,0 +1 @@
1
+ export const transforms: any[];
@@ -0,0 +1,3 @@
1
+ export { default } from "./conversation";
2
+ export { default as ShareActivity } from "./share-activity";
3
+ export { ConversationError, InvalidUserCreation } from "./convo-error";
@@ -0,0 +1,7 @@
1
+ export const EMITTER_SYMBOL: unique symbol;
2
+ export const FILE_SYMBOL: unique symbol;
3
+ export default ShareActivity;
4
+ /**
5
+ * @class
6
+ */
7
+ declare const ShareActivity: any;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Helper to convert objects into arrays of transforms. probably belongs in
3
+ * webex-core
4
+ * @param {string} direction "inbound"|"outbound"
5
+ * @param {Object} obj
6
+ * @private
7
+ * @returns {Array}
8
+ */
9
+ export default function toArray(direction: string, obj: any): any[];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webex/internal-plugin-conversation",
3
- "version": "3.0.0-beta.9",
3
+ "version": "3.0.0-bnr.0",
4
4
  "description": "",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",
@@ -20,26 +20,26 @@
20
20
  ]
21
21
  },
22
22
  "dependencies": {
23
- "@webex/common": "3.0.0-beta.9",
24
- "@webex/helper-html": "3.0.0-beta.9",
25
- "@webex/helper-image": "3.0.0-beta.9",
26
- "@webex/internal-plugin-conversation": "3.0.0-beta.9",
27
- "@webex/internal-plugin-encryption": "3.0.0-beta.9",
28
- "@webex/internal-plugin-user": "3.0.0-beta.9",
29
- "@webex/webex-core": "3.0.0-beta.9",
23
+ "@webex/common": "3.0.0-bnr.0",
24
+ "@webex/helper-html": "3.0.0-bnr.0",
25
+ "@webex/helper-image": "3.0.0-bnr.0",
26
+ "@webex/internal-plugin-conversation": "3.0.0-bnr.0",
27
+ "@webex/internal-plugin-encryption": "3.0.0-bnr.0",
28
+ "@webex/internal-plugin-user": "3.0.0-bnr.0",
29
+ "@webex/webex-core": "3.0.0-bnr.0",
30
30
  "crypto-js": "^4.1.1",
31
31
  "lodash": "^4.17.21",
32
32
  "node-scr": "^0.3.0",
33
33
  "uuid": "^3.3.2"
34
34
  },
35
35
  "devDependencies": {
36
- "@webex/test-helper-chai": "3.0.0-beta.9",
37
- "@webex/test-helper-file": "3.0.0-beta.9",
38
- "@webex/test-helper-make-local-url": "3.0.0-beta.9",
39
- "@webex/test-helper-mocha": "3.0.0-beta.9",
40
- "@webex/test-helper-mock-webex": "3.0.0-beta.9",
41
- "@webex/test-helper-retry": "3.0.0-beta.9",
42
- "@webex/test-helper-test-users": "3.0.0-beta.9",
36
+ "@webex/test-helper-chai": "3.0.0-bnr.0",
37
+ "@webex/test-helper-file": "3.0.0-bnr.0",
38
+ "@webex/test-helper-make-local-url": "3.0.0-bnr.0",
39
+ "@webex/test-helper-mocha": "3.0.0-bnr.0",
40
+ "@webex/test-helper-mock-webex": "3.0.0-bnr.0",
41
+ "@webex/test-helper-retry": "3.0.0-bnr.0",
42
+ "@webex/test-helper-test-users": "3.0.0-bnr.0",
43
43
  "sinon": "^9.2.4"
44
44
  }
45
45
  }
package/src/activities.js CHANGED
@@ -14,7 +14,7 @@ export const ACTIVITY_TYPES = {
14
14
  CREATE: 'CREATE',
15
15
  TOMBSTONE: 'TOMBSTONE',
16
16
  DELETE: 'DELETE',
17
- REPLY_EDIT: 'REPLY_EDIT'
17
+ REPLY_EDIT: 'REPLY_EDIT',
18
18
  };
19
19
 
20
20
  const REPLY = 'reply';
@@ -59,9 +59,11 @@ export const getPublishedDate = (activity = {}) => new Date(activity.published).
59
59
  * @param {Object} activity2
60
60
  * @returns {boolean} true if first activity is newer than second
61
61
  */
62
- export const isNewer = (activity1, activity2) => getPublishedDate(activity1) > getPublishedDate(activity2);
62
+ export const isNewer = (activity1, activity2) =>
63
+ getPublishedDate(activity1) > getPublishedDate(activity2);
63
64
 
64
- export const sortActivitiesByPublishedDate = (activities) => sortBy(activities, (activity) => getPublishedDate(activity));
65
+ export const sortActivitiesByPublishedDate = (activities) =>
66
+ sortBy(activities, (activity) => getPublishedDate(activity));
65
67
 
66
68
  export const getParentId = (activity) => activity?.parent?.id;
67
69
 
@@ -83,7 +85,8 @@ export const sanitizeActivity = (activity) => {
83
85
  return final;
84
86
  };
85
87
 
86
- export const getIsActivityOrphaned = (activity, activities) => activity.parent && activity.parent.id && !activities[activity.parent.id];
88
+ export const getIsActivityOrphaned = (activity, activities) =>
89
+ activity.parent && activity.parent.id && !activities[activity.parent.id];
87
90
 
88
91
  const getIsReplyEditActivity = (activity, activities) => {
89
92
  const parentId = activity.parent.id;
@@ -111,7 +114,7 @@ export const createRootActivity = (activity) => activity;
111
114
  export const createReplyActivity = (activity) => {
112
115
  const replyAct = {
113
116
  ...activity,
114
- replyParent: activity.parent
117
+ replyParent: activity.parent,
115
118
  };
116
119
 
117
120
  return replyAct;
@@ -128,7 +131,7 @@ export const createEditActivity = (editActivity, activities) => {
128
131
  parent: editActParentObj,
129
132
  editParent: editActParentObj,
130
133
  object: editActivity.object,
131
- published: editActivity.published
134
+ published: editActivity.published,
132
135
  };
133
136
 
134
137
  return joinedEditAct;
@@ -147,7 +150,7 @@ export const createReplyEditActivity = (editActivity, activities) => {
147
150
  editParent: editActParentObj,
148
151
  replyParent: parentReplyAct.parent,
149
152
  object: editActivity.object,
150
- published: editActivity.published
153
+ published: editActivity.published,
151
154
  };
152
155
 
153
156
  return joinedReplyEditActivity;
@@ -9,7 +9,7 @@ import {
9
9
  NEWER,
10
10
  OLDER,
11
11
  INITIAL,
12
- MID
12
+ MID,
13
13
  } from './activities';
14
14
 
15
15
  export const defaultMinDisplayableActivities = 20;
@@ -32,7 +32,8 @@ export const setValue = (destination, key, value) => destination.set(key, value)
32
32
  */
33
33
  export const getValue = (source, key) => source.get(key);
34
34
 
35
- export const getActivityObjectsFromMap = (hashMap) => Array.from(hashMap).map(([, activity]) => activity);
35
+ export const getActivityObjectsFromMap = (hashMap) =>
36
+ Array.from(hashMap).map(([, activity]) => activity);
36
37
  /**
37
38
  * creates maps for various activity types and defines handlers for working with stored activities
38
39
  * utilizes revealing module pattern to close over state and only expose certain necessary functions for altering state
@@ -53,8 +54,7 @@ export const activityManager = () => {
53
54
 
54
55
  if (existingReplyHash) {
55
56
  setValue(existingReplyHash, replyAct.id, replyAct);
56
- }
57
- else {
57
+ } else {
58
58
  const replyHash = new Map();
59
59
 
60
60
  setValue(replyHash, replyAct.id, replyAct);
@@ -98,23 +98,25 @@ export const activityManager = () => {
98
98
  reactionHelper(reactionSelfAct, reactionSelfActivityHash);
99
99
  };
100
100
 
101
- const getActivityHandlerByKey = (key) => ({
102
- [ACTIVITY_TYPES.REACTION]: handleNewReaction,
103
- [ACTIVITY_TYPES.REACTION_SELF]: handleNewReactionSelf,
104
- [ACTIVITY_TYPES.EDIT]: handleNewEdit,
105
- [ACTIVITY_TYPES.REPLY]: handleNewReply
106
- }[key]);
107
-
108
- const getActivityByTypeAndParentId = (type, id) => ({
109
- [ACTIVITY_TYPES.EDIT]: getValue(editActivityHash, id),
110
- [ACTIVITY_TYPES.REPLY]: getValue(replyActivityHash, id),
111
- [ACTIVITY_TYPES.REACTION]: getValue(reactionActivityHash, id),
112
- [ACTIVITY_TYPES.REACTION_SELF]: getValue(reactionSelfActivityHash, id)
113
- }[type]);
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]);
114
116
 
115
117
  return {
116
118
  getActivityHandlerByKey,
117
- getActivityByTypeAndParentId
119
+ getActivityByTypeAndParentId,
118
120
  };
119
121
  };
120
122
 
@@ -133,8 +135,7 @@ export const bookendManager = () => {
133
135
  const setOldestAct = (act) => {
134
136
  if (!oldestAct) {
135
137
  oldestAct = act;
136
- }
137
- else if (isNewer(oldestAct, act)) {
138
+ } else if (isNewer(oldestAct, act)) {
138
139
  oldestAct = act;
139
140
  }
140
141
  };
@@ -142,8 +143,7 @@ export const bookendManager = () => {
142
143
  const setNewestAct = (act) => {
143
144
  if (!newestAct) {
144
145
  newestAct = act;
145
- }
146
- else if (isNewer(act, newestAct)) {
146
+ } else if (isNewer(act, newestAct)) {
147
147
  newestAct = act;
148
148
  }
149
149
  };
@@ -161,7 +161,7 @@ export const bookendManager = () => {
161
161
  return {
162
162
  setBookends,
163
163
  getNewestAct,
164
- getOldestAct
164
+ getOldestAct,
165
165
  };
166
166
  };
167
167
 
@@ -204,7 +204,7 @@ export const noMoreActivitiesManager = () => {
204
204
  getNoMoreActs,
205
205
  checkAndSetNoMoreActs,
206
206
  checkAndSetNoNewerActs,
207
- checkAndSetNoOlderActs
207
+ checkAndSetNoOlderActs,
208
208
  };
209
209
  };
210
210
 
@@ -223,7 +223,7 @@ export const rootActivityManager = () => {
223
223
 
224
224
  return {
225
225
  addNewRoot,
226
- getRootActivityHash
226
+ getRootActivityHash,
227
227
  };
228
228
  };
229
229
 
@@ -249,9 +249,7 @@ export const getLoopCounterFailsafe = () => {
249
249
  * @returns {object}
250
250
  */
251
251
  export const getQuery = (type, queryOptions) => {
252
- const {
253
- newestPublishedDate, oldestPublishedDate, batchSize, activityToSearch = {}
254
- } = queryOptions;
252
+ const {newestPublishedDate, oldestPublishedDate, batchSize, activityToSearch = {}} = queryOptions;
255
253
 
256
254
  switch (type) {
257
255
  case NEWER: {
@@ -266,8 +264,7 @@ export const getQuery = (type, queryOptions) => {
266
264
 
267
265
  if (searchType === ACTIVITY_TYPES.REPLY || searchType === ACTIVITY_TYPES.EDIT) {
268
266
  midDate = activityToSearch.parent.published;
269
- }
270
- else {
267
+ } else {
271
268
  midDate = activityToSearch.published;
272
269
  }
273
270
 
@@ -3,22 +3,24 @@
3
3
  Activity thread ordering (or "threading") is the act of flattening the hierarchical relationship of thread parents and thread replies.
4
4
 
5
5
  ## Why Thread Order?
6
+
6
7
  When a client fetches activities from conversation service, convo returns chronologically ordered activities (by published date). If you are a client that attempts to display activities to a user, this is mostly useless. An example:
7
8
 
8
9
  Client: hey convo, give me 10 activities
9
10
 
10
11
  Convo: here.
11
- 1. reaction
12
- 2. root
13
- 3. reaction
14
- 4. reply
15
- 5. edit
16
- 6. edit
17
- 7. reply
18
- 8. reaction
19
- 9. meeting
20
- 10. reply
21
-
12
+
13
+ 1. reaction
14
+ 2. root
15
+ 3. reaction
16
+ 4. reply
17
+ 5. edit
18
+ 6. edit
19
+ 7. reply
20
+ 8. reaction
21
+ 9. meeting
22
+ 10. reply
23
+
22
24
  Client: ...
23
25
 
24
26
  Convo: ...
@@ -28,17 +30,18 @@ By contrast, thread ordering returns activities in _thread order_, otherwise kno
28
30
  Client: hey convo, give me 10 activities in thread order
29
31
 
30
32
  Convo: here.
31
- 1. root 4
32
- 2. reply to root 4
33
- 3. reply to root 4
34
- 4. root 3
35
- 5. reply to root 3
36
- 6. reply to root 3
37
- 7. root 2
38
- 8. reply to root 2
39
- 9. reply to root 2
40
- 10. root 1 (newest root activity)
41
-
33
+
34
+ 1. root 4
35
+ 2. reply to root 4
36
+ 3. reply to root 4
37
+ 4. root 3
38
+ 5. reply to root 3
39
+ 6. reply to root 3
40
+ 7. root 2
41
+ 8. reply to root 2
42
+ 9. reply to root 2
43
+ 10. root 1 (newest root activity)
44
+
42
45
  Client: 👍
43
46
 
44
47
  Convo: 👍
@@ -57,6 +60,7 @@ As you can see, thread ordering is useful, and as you may _not_ see, it is diffi
57
60
  # The Code
58
61
 
59
62
  Thread ordering methods live in the internal converation plugin
63
+
60
64
  ```
61
65
  webex.internal.conversation[*]
62
66
  ```
@@ -64,36 +68,39 @@ webex.internal.conversation[*]
64
68
  There are two methods that compose thread ordering, a public and private method. The public method is simply a facade of the private method, abstracting the complex away from the caller.
65
69
 
66
70
  ### `_listActivitiesThreadOrdered(options)` (private)
71
+
67
72
  The `_listActivitiesThreadOrdered` method is a stateful async generator function that fetches thread ordered activities.
68
73
 
69
74
  #### Description
70
- The `_listActivitiesThreadOrdered` method instantiates a generator function that yields a promise. It yields results in an infinite loop for the life of the generator (until the instance is no longer referenced and JS garbage collects). This means when the method yields a result it pauses execution until its next invocation, freezing its current state to be used by the next invocation. The generator instance internally tracks the oldest and newest activities it has fetched, using them as the timestamps to query the next set of results in either direction, thus the caller is not required to maintain any state to fetch older and newer activities. This method does not cache all fetched activities, therefore the caller is still required to store their fetched activities or be forced to refetch them.
75
+
76
+ The `_listActivitiesThreadOrdered` method instantiates a generator function that yields a promise. It yields results in an infinite loop for the life of the generator (until the instance is no longer referenced and JS garbage collects). This means when the method yields a result it pauses execution until its next invocation, freezing its current state to be used by the next invocation. The generator instance internally tracks the oldest and newest activities it has fetched, using them as the timestamps to query the next set of results in either direction, thus the caller is not required to maintain any state to fetch older and newer activities. This method does not cache all fetched activities, therefore the caller is still required to store their fetched activities or be forced to refetch them.
71
77
 
72
78
  The generator's returned `next` method accepts arguments as well, which allows the caller to change the direction of their querying from newer messages to older ones without creating a new generator instance. `next`
73
79
 
74
80
  #### Parameters
81
+
75
82
  _generator initialization options_
76
83
 
77
84
  options
78
85
 
79
- options.url: the conversation's convo URL
86
+ options.url: the conversation's convo URL
80
87
 
81
- options.minActivities: the minimum number of activities you would like in your batch
88
+ options.minActivities: the minimum number of activities you would like in your batch
82
89
 
83
- options.queryType: the direction to fetch activities. One of 'newer', 'older', 'mid'
90
+ options.queryType: the direction to fetch activities. One of 'newer', 'older', 'mid'
84
91
 
85
- options.search: a server activity object to return as the middle point of the batch, along with its surrounding activities
92
+ options.search: a server activity object to return as the middle point of the batch, along with its surrounding activities
86
93
 
87
94
  _parameters accepted by the generator's `next` method_
88
95
 
89
96
  options
90
97
 
91
- options.queryType: see above
92
-
93
- options.search: see above
98
+ options.queryType: see above
94
99
 
100
+ options.search: see above
95
101
 
96
102
  #### Return value
103
+
97
104
  Calling `_listActivitiesThreadOrdered` returns the generator instance, and does not execute any work. The generator returned has a `next` method that begins the first round of work and returns a `done` boolean and a `value`, the asked-for thread ordered activities.
98
105
 
99
106
  ```
@@ -109,6 +116,7 @@ value: IActivity[]
109
116
  ```
110
117
 
111
118
  #### Examples
119
+
112
120
  ```
113
121
  const options = {
114
122
  url: 'myconvourl.com',
@@ -123,31 +131,35 @@ await threadOrderedFetcher.next() // => { done: boolean, value: IActivity[] }
123
131
  #### The nitty gritty: design
124
132
 
125
133
  There are 3 main phases of the method, with one major subphase:
134
+
126
135
  1. initialization: up to the ` while (true)` loop
127
136
  2. execution: the ` while (true)` loop
128
137
  3. (subphase of execution) fetching: the ` while (!getNoMoreActs())` loop
129
138
  4. re-calculation: after the ` yield`
130
139
 
131
140
  ##### initialization
141
+
132
142
  Parsing the arguments and initializing state is done in this first phase, before the generator's first execution. State that must be retained independent of each execution loop (the code run by the generator's `next` method) is instantiated here. The following variables (or grouped of variables) are created and maintained for the life of the generator:
133
143
 
134
- * oldestAct - the oldest activity (by published date) that has been fetched by the gen. instance
135
- * newestAct - the newest activity that has been fetched by the gen. instance
136
- * batchSize - the number of activities to fetch to achieve minActivities. This value is set lower in cases where we fetch children, because adding the children to their parents may help us reach minActivities count
137
- * query - initialize fetching query. The first query will be forced to fetch newest activities in a space to initialize the activity states, unless a search is requested
138
- * ***ActivityHash(es): cache objects for children activities. These caches store all child activity types returned from convo fetches in order to keep track of "orphans", or child activities that come in before their parent activity
144
+ - oldestAct - the oldest activity (by published date) that has been fetched by the gen. instance
145
+ - newestAct - the newest activity that has been fetched by the gen. instance
146
+ - batchSize - the number of activities to fetch to achieve minActivities. This value is set lower in cases where we fetch children, because adding the children to their parents may help us reach minActivities count
147
+ - query - initialize fetching query. The first query will be forced to fetch newest activities in a space to initialize the activity states, unless a search is requested
148
+ - \*\*\*ActivityHash(es): cache objects for children activities. These caches store all child activity types returned from convo fetches in order to keep track of "orphans", or child activities that come in before their parent activity
139
149
 
140
150
  ##### execution
151
+
141
152
  The execution phase will be run for every call to `next` method. Its job is to fetch activities until the minimum activity limit is reached, then it will build the ordered list of activities and yield them to the caller. Similar to init phase, execution phase has variables declared outside the fetching loop in order to keep track of what we have fetched so far, and whether continuing to fetch is necessary. The execuction phase runs the fetching subphase. The following state variables are tracked by this outer loop, before the fetching phase:
142
153
 
143
- * rootActivityHash - the data structure used to track root activities we have fetched in a given batch
144
- * [* helpers] - many helper functions are declared. They close over state variables and are used to group functionality used by the fetching loop, and for self-documenting purposes
145
- * fetchLoopCount - track count of fetch loops run. Used to break out of loop in unlikely case that we fetch the same query over and over.
154
+ - rootActivityHash - the data structure used to track root activities we have fetched in a given batch
155
+ - [* helpers] - many helper functions are declared. They close over state variables and are used to group functionality used by the fetching loop, and for self-documenting purposes
156
+ - fetchLoopCount - track count of fetch loops run. Used to break out of loop in unlikely case that we fetch the same query over and over.
146
157
 
147
158
  ##### fetching
148
- The fetching phase is contained within the execution phase, and is a loop that will run until we run out of activities to fetch, or explicitly break the loop when we reach the minActivities count with what we've fetched so far. Each fetch loop begins by setting up the query and passing options to `#listActivities` method. All query types depend on a first query to activities to get N root activities. midDate queries (aliased MID) and sinceDate queries (aliased NEWER) also must recursively fetch children to ensure we don't return to caller a root activity that is missing children.*
149
159
 
150
- *NOTE: These sometimes-necessary children queries depend on the addition of a new method, `#listAllChildActivitiesByParentId`. This method is similar to `listChildActivitiesByParentId`, but this method recursively fetches all the chilren of a certain type, rather than forcing the calling method to fetch 10 children at a time (as is the current child limit set by underlying convo API).
160
+ The fetching phase is contained within the execution phase, and is a loop that will run until we run out of activities to fetch, or explicitly break the loop when we reach the minActivities count with what we've fetched so far. Each fetch loop begins by setting up the query and passing options to `#listActivities` method. All query types depend on a first query to activities to get N root activities. midDate queries (aliased MID) and sinceDate queries (aliased NEWER) also must recursively fetch children to ensure we don't return to caller a root activity that is missing children.\*
161
+
162
+ \*NOTE: These sometimes-necessary children queries depend on the addition of a new method, `#listAllChildActivitiesByParentId`. This method is similar to `listChildActivitiesByParentId`, but this method recursively fetches all the chilren of a certain type, rather than forcing the calling method to fetch 10 children at a time (as is the current child limit set by underlying convo API).
151
163
 
152
164
  Activities returned to us by convo fetches are sorted and placed into maps based off their activity type. Root activities are stored on a per-batch basis, whereas children are stored globally (prevents orphans). Root activities are keyed by their ID, where children are keyed by their parent's ID (`activity.parent.id`).
153
165
 
@@ -156,24 +168,29 @@ When reactions are fetched, however, we call a _different_ convo API that helps
156
168
  Fetching loop can be explicitly broken out of when we have decided we have the necessary activities for the current batch. If we _don't_ have enough activities, we initialize a new query derived from the former query and return to the top of the fetching loop to continue building our list.
157
169
 
158
170
  ##### execution (revisited)
159
- After a successful series of fetches have given us the activities necessary for the current batch, we initialize an empty array that acts as our ordered list. To begin, the current batch's root activities are sorted by their published date, and using the ordered list of IDs, we begin to loop over the rootActivityHash.
171
+
172
+ After a successful series of fetches have given us the activities necessary for the current batch, we initialize an empty array that acts as our ordered list. To begin, the current batch's root activities are sorted by their published date, and using the ordered list of IDs, we begin to loop over the rootActivityHash.
160
173
 
161
174
  For every root activity, the ID of the root is used to check all the child hashes (keyed by _parent ID_, recall), and implement IActivity. When a root activity has replies, a similar process is undergone for the reply activity: sorting it by published date, checking its ID against the edits and reactions hash, and sanitizing to implement IActivity. Replies are then looped over and added to the ordered list before moving on to the next root.
162
175
 
163
176
  We have successfully finished a batch, and will now yield the ordered list to the caller.
164
177
 
165
178
  ##### recalculation
179
+
166
180
  The generator's `next` method may accepts arguments in order to alter the behavior of the existing generator. Assigning `yield` to a variable captures the arguments passed into `next` method. The `next` method accepts a new value for minActivities, as well as an override for `queryType`. This allows the same generator (and its state) to be used for multiple queries that build one upon another.
167
181
 
168
182
  The first call to `next` (the first call) is initialized automatically as an INITIAL fetch, to populate the generator state, but subsequent calls to `next` method without a passed-in `queryType` will close the generator.
169
183
 
170
184
  ### `listActivitiesThreadOrdered(options)` (public)
185
+
171
186
  The public facade exposes wrappers for ease of managing an instance of the generator. All methods implement the iterator protocol The following methods are exposed:
172
187
 
173
188
  #### `getOlder()`
189
+
174
190
  Implements iterator protocol. Returns oldest activities, then returns any older activities than the oldest fetched.
175
191
 
176
192
  example:
193
+
177
194
  ```
178
195
  const myGen = webex.internal.conversation.listActivitiesThreadOrdered(opts);
179
196
  const firstBatch = await myGen.getOlder();
@@ -195,9 +212,11 @@ console.log(secondBatch)
195
212
  ```
196
213
 
197
214
  #### jumpToActivity(searchActivity)
198
- Implements iterator protocol. Returns searched activity as the middle activity in a batch, with older and newer activities surrounding.
199
215
 
200
- example:
216
+ Implements iterator protocol. Returns searched activity as the middle activity in a batch, with older and newer activities surrounding.
217
+
218
+ example:
219
+
201
220
  ```
202
221
  const activitySearchResult = IServerActivity // actual activity object returned by server, most commonly returned by activity search
203
222
  const myGen = webex.internal.conversation.listActivitiesThreadOrdered(opts);
@@ -210,10 +229,13 @@ console.log(results)
210
229
  }
211
230
  */
212
231
  ```
213
- #### `getNewer()`
232
+
233
+ #### `getNewer()`
234
+
214
235
  Implements iterator protocol. Returns most recent activities, then returns any newer activities than the newest fetched.
215
236
 
216
237
  example:
238
+
217
239
  ```
218
240
  const myGen = webex.internal.conversation.listActivitiesThreadOrdered(opts);
219
241
  const firstBatch = await myGen.getNewer();
@@ -234,7 +256,9 @@ console.log(secondBatch)
234
256
  }
235
257
  */
236
258
  ```
259
+
237
260
  `getNewer()` is of limited use at first, but consider the following example, when used in conjunction with `jumpToActivity`:
261
+
238
262
  ```
239
263
  const activitySearchResult = IServerActivity // actual activity object returned by server, most commonly returned by activity search
240
264
  const myGen = webex.internal.conversation.listActivitiesThreadOrdered(opts);
@@ -256,8 +280,3 @@ console.log(secondBatch);
256
280
  }
257
281
  */
258
282
  ```
259
-
260
-
261
-
262
-
263
-
package/src/config.js CHANGED
@@ -5,10 +5,10 @@
5
5
  export default {
6
6
  conversation: {
7
7
  allowedInboundTags: {
8
- 'webex-mention': ['data-object-type', 'data-object-id', 'data-object-url']
8
+ 'webex-mention': ['data-object-type', 'data-object-id', 'data-object-url'],
9
9
  },
10
10
  allowedOutboundTags: {
11
- 'webex-mention': ['data-object-type', 'data-object-id', 'data-object-url']
11
+ 'webex-mention': ['data-object-type', 'data-object-id', 'data-object-url'],
12
12
  },
13
13
  // eslint-disable-next-line no-empty-function
14
14
  inboundProcessFunc: () => {},
@@ -27,11 +27,11 @@ export default {
27
27
  */
28
28
  thumbnailMaxWidth: 640,
29
29
  /**
30
- * Primarily for testing. When true, decrypting an activity will create a
30
+ * Primarily for testing. When true, decrypting an activity will create a
31
31
  * sister property with the original encrypted string
32
32
  * @type {Boolean}
33
33
  */
34
34
  keepEncryptedProperties: false,
35
- decryptionFailureMessage: 'This message cannot be decrypted'
36
- }
35
+ decryptionFailureMessage: 'This message cannot be decrypted',
36
+ },
37
37
  };