@nlabs/reaktor 0.1.0 → 0.1.2

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 (112) hide show
  1. package/package.json +13 -13
  2. package/src/config.ts +8 -2
  3. package/src/data/conversations.ts +2 -4
  4. package/src/data/email.ts +3 -4
  5. package/src/data/files.ts +2 -2
  6. package/src/data/images.ts +5 -5
  7. package/src/data/posts.ts +239 -167
  8. package/src/data/users.ts +0 -2
  9. package/src/types/apps.ts +0 -1
  10. package/src/types/auth.ts +1 -0
  11. package/src/types/files.ts +0 -2
  12. package/src/types/groups.ts +0 -1
  13. package/src/types/images.ts +0 -1
  14. package/src/types/locations.ts +0 -1
  15. package/src/types/payments.ts +0 -5
  16. package/src/types/posts.ts +13 -4
  17. package/src/types/tags.ts +0 -1
  18. package/src/utils/auth.ts +35 -2
  19. package/src/utils/graphql.ts +7 -0
  20. package/src/utils/index.ts +1 -0
  21. package/lib/config.d.ts +0 -21
  22. package/lib/config.js +0 -127
  23. package/lib/data/conversations.d.ts +0 -6
  24. package/lib/data/conversations.js +0 -201
  25. package/lib/data/dynamodb.d.ts +0 -8
  26. package/lib/data/dynamodb.js +0 -139
  27. package/lib/data/email.d.ts +0 -7
  28. package/lib/data/email.js +0 -164
  29. package/lib/data/files.d.ts +0 -16
  30. package/lib/data/files.js +0 -407
  31. package/lib/data/groups.d.ts +0 -13
  32. package/lib/data/groups.js +0 -354
  33. package/lib/data/images.d.ts +0 -12
  34. package/lib/data/images.js +0 -668
  35. package/lib/data/index.d.ts +0 -19
  36. package/lib/data/index.js +0 -24
  37. package/lib/data/ios.d.ts +0 -6
  38. package/lib/data/ios.js +0 -302
  39. package/lib/data/locations.d.ts +0 -3
  40. package/lib/data/locations.js +0 -132
  41. package/lib/data/messages.d.ts +0 -9
  42. package/lib/data/messages.js +0 -248
  43. package/lib/data/notifications.d.ts +0 -5
  44. package/lib/data/notifications.js +0 -42
  45. package/lib/data/payments.d.ts +0 -11
  46. package/lib/data/payments.js +0 -748
  47. package/lib/data/posts.d.ts +0 -14
  48. package/lib/data/posts.js +0 -458
  49. package/lib/data/reactions.d.ts +0 -6
  50. package/lib/data/reactions.js +0 -218
  51. package/lib/data/s3.d.ts +0 -6
  52. package/lib/data/s3.js +0 -103
  53. package/lib/data/search.d.ts +0 -3
  54. package/lib/data/search.js +0 -98
  55. package/lib/data/sms.d.ts +0 -3
  56. package/lib/data/sms.js +0 -59
  57. package/lib/data/subscription.d.ts +0 -7
  58. package/lib/data/subscription.js +0 -284
  59. package/lib/data/tags.d.ts +0 -14
  60. package/lib/data/tags.js +0 -304
  61. package/lib/data/users.d.ts +0 -12
  62. package/lib/data/users.js +0 -312
  63. package/lib/index.d.ts +0 -3
  64. package/lib/index.js +0 -8
  65. package/lib/types/apps.d.ts +0 -44
  66. package/lib/types/apps.js +0 -2
  67. package/lib/types/arangodb.d.ts +0 -17
  68. package/lib/types/arangodb.js +0 -2
  69. package/lib/types/auth.d.ts +0 -9
  70. package/lib/types/auth.js +0 -2
  71. package/lib/types/conversations.d.ts +0 -6
  72. package/lib/types/conversations.js +0 -2
  73. package/lib/types/email.d.ts +0 -12
  74. package/lib/types/email.js +0 -2
  75. package/lib/types/files.d.ts +0 -28
  76. package/lib/types/files.js +0 -2
  77. package/lib/types/google.d.ts +0 -27
  78. package/lib/types/google.js +0 -2
  79. package/lib/types/groups.d.ts +0 -22
  80. package/lib/types/groups.js +0 -2
  81. package/lib/types/images.d.ts +0 -25
  82. package/lib/types/images.js +0 -2
  83. package/lib/types/index.d.ts +0 -17
  84. package/lib/types/index.js +0 -22
  85. package/lib/types/locations.d.ts +0 -21
  86. package/lib/types/locations.js +0 -2
  87. package/lib/types/messages.d.ts +0 -12
  88. package/lib/types/messages.js +0 -2
  89. package/lib/types/notifications.d.ts +0 -19
  90. package/lib/types/notifications.js +0 -2
  91. package/lib/types/payments.d.ts +0 -119
  92. package/lib/types/payments.js +0 -2
  93. package/lib/types/posts.d.ts +0 -20
  94. package/lib/types/posts.js +0 -2
  95. package/lib/types/reactions.d.ts +0 -4
  96. package/lib/types/reactions.js +0 -2
  97. package/lib/types/tags.d.ts +0 -10
  98. package/lib/types/tags.js +0 -2
  99. package/lib/types/users.d.ts +0 -78
  100. package/lib/types/users.js +0 -2
  101. package/lib/utils/analytics.d.ts +0 -3
  102. package/lib/utils/analytics.js +0 -47
  103. package/lib/utils/arangodb.d.ts +0 -9
  104. package/lib/utils/arangodb.js +0 -98
  105. package/lib/utils/auth.d.ts +0 -2
  106. package/lib/utils/auth.js +0 -43
  107. package/lib/utils/index.d.ts +0 -5
  108. package/lib/utils/index.js +0 -10
  109. package/lib/utils/objects.d.ts +0 -3
  110. package/lib/utils/objects.js +0 -34
  111. package/lib/utils/redis.d.ts +0 -1
  112. package/lib/utils/redis.js +0 -15
package/src/data/posts.ts CHANGED
@@ -2,36 +2,86 @@
2
2
  * Copyright (c) 2019-Present, Nitrogen Labs, Inc.
3
3
  * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms.
4
4
  */
5
- import {createHash, parseChar, parseId, parseString, parseVarChar} from '@nlabs/utils';
5
+ import {createHash, parseChar, parseId, parseNum, parseString, parseVarChar} from '@nlabs/utils';
6
6
  import {aql, Database} from 'arangojs';
7
7
  import {AqlQuery} from 'arangojs/lib/cjs/aql-query';
8
8
  import {ArrayCursor} from 'arangojs/lib/cjs/cursor';
9
9
  import flatten from 'lodash/flatten';
10
10
  import uniqBy from 'lodash/uniqBy';
11
11
 
12
- import {ApiContext, ArangoDBLimit, FileType, GroupType, PostType, TagType} from '../types';
12
+ import {ApiContext, FileType, GroupType, PostOptions, PostType, TagType} from '../types';
13
13
  import {getLimit, useDb} from '../utils';
14
14
  import {updateFiles} from './files';
15
15
  import {extractTags} from './tags';
16
16
 
17
17
  // const eventCategory: string = 'posts';
18
+ const MAX_CONTENT_LENGTH: number = 100000;
18
19
 
19
- export const getPostList = (context: ApiContext, from: number, to: number): Promise<PostType[]> => {
20
+ export const parsePostOptions = (options: PostOptions = {}) => {
21
+ const {
22
+ from = 0,
23
+ latitude,
24
+ longitude,
25
+ to = 30,
26
+ type = 'default'
27
+ } = options;
28
+
29
+
30
+ return {
31
+ latitude: parseNum(latitude, 32),
32
+ longitude: parseNum(longitude, 32),
33
+ limit: getLimit(from, to),
34
+ type: parseChar(type, 32)
35
+ };
36
+ };
37
+
38
+ export const getPostOptional = (fields: string[]) =>
39
+ fields.reduce((selects: any, field: string) => {
40
+ switch(field) {
41
+ case 'reactions': {
42
+ selects.queries.push(`LET reactions = (
43
+ FOR post, r IN INBOUND p._id reactions
44
+ COLLECT reactionName = r.value INTO reactionItems
45
+ RETURN {name: reactionName, count: LENGTH(reactionItems[*].r.value)}
46
+ )`);
47
+ selects.objects.push('reactions:reactions');
48
+ return selects;
49
+ }
50
+ case 'tags': {
51
+ selects.queries.push(`LET tags = (
52
+ FOR t, pl IN INBOUND p._id isTagged
53
+ RETURN t
54
+ )`);
55
+ selects.objects.push('tags:tags');
56
+ return selects;
57
+ }
58
+ case 'user': {
59
+ selects.queries.push(`LET user = FIRST(
60
+ FOR u IN users
61
+ FILTER p.userId == u._key
62
+ LIMIT 1
63
+ RETURN u
64
+ )`);
65
+ selects.objects.push('user:user');
66
+ return selects;
67
+ }
68
+ default: {
69
+ return selects;
70
+ }
71
+ }
72
+ }, {objects: [], queries: []});
73
+
74
+ export const getPostList = (context: ApiContext, options?: PostOptions): Promise<PostType[]> => {
20
75
  // const action: string = 'getListByApp';
21
- const {database} = context;
22
- const limit: ArangoDBLimit = getLimit(from, to);
76
+ const {database, fields} = context;
77
+ const {limit, type} = parsePostOptions(options);
78
+ const {objects: selectObjects, queries: selectQueries} = getPostOptional(fields);
23
79
  const aqlQry: string = `FOR p IN posts
24
- FILTER !!p.parent == false
25
- LET reactions = (
26
- FOR post, r IN INBOUND p._id reactions
27
- COLLECT reactionName = r.value INTO reactionItems
28
- RETURN {name: reactionName, count: LENGTH(reactionItems[*].r.value)}
29
- )
30
- FOR u IN users
31
- FILTER p.userId == u._key
32
- ${limit.aql}
33
- SORT p.added
34
- RETURN DISTINCT MERGE(p, {user:u, reactions:reactions})`;
80
+ FILTER p.type == "${type}" && p.privacy == "public" && p.parent == null
81
+ ${selectQueries.join('\n')}
82
+ ${limit.aql}
83
+ SORT p.added
84
+ RETURN DISTINCT MERGE(p, {${selectObjects.join(', ')}})`;
35
85
 
36
86
  return useDb(database).query(aqlQry)
37
87
  .then((cursor: ArrayCursor) => cursor.all())
@@ -40,9 +90,10 @@ export const getPostList = (context: ApiContext, from: number, to: number): Prom
40
90
  });
41
91
  };
42
92
 
43
- export const getPostListByGroup = (context: ApiContext, groupId: string, from: number, to: number): Promise<PostType[]> => {
93
+ export const getPostListByGroup = (context: ApiContext, groupId: string, options?: PostOptions): Promise<PostType[]> => {
44
94
  // const action: string = 'getListByGroup';
45
- const {database, userId: sessionId} = context;
95
+ const {database, fields, userId: sessionId} = context;
96
+ const {objects: selectObjects, queries: selectQueries} = getPostOptional(fields);
46
97
 
47
98
  // Group id
48
99
  const formatGroupId: string = parseId(groupId);
@@ -55,19 +106,13 @@ export const getPostListByGroup = (context: ApiContext, groupId: string, from: n
55
106
  .then((cursor: ArrayCursor) => cursor.all())
56
107
  .then((groups: GroupType[] = []) => {
57
108
  if(groups.length) {
58
- const limit: ArangoDBLimit = getLimit(from, to);
109
+ const {limit, type} = parsePostOptions(options);
59
110
  const postAqlQry: string = `FOR p IN posts
60
- FILTER p.groupId == "${formatGroupId}" && !!p.parent == false
61
- LET reactions = (
62
- FOR post, r IN INBOUND p._id reactions
63
- COLLECT reactionName = r.value INTO reactionItems
64
- RETURN {name: reactionName, count: LENGTH(reactionItems[*].r.value)}
65
- )
66
- FOR u IN users
67
- FILTER p.userId == u._key
68
- ${limit.aql}
69
- SORT p.added
70
- RETURN DISTINCT MERGE(p, {user:u, reactions:reactions})`;
111
+ FILTER p.type == "${type}" && p.groupId == "${formatGroupId}" && p.parent == null
112
+ ${selectQueries.join('\n')}
113
+ ${limit.aql}
114
+ SORT p.added
115
+ RETURN DISTINCT MERGE(p, {${selectObjects.join(', ')}})`;
71
116
 
72
117
  return db.query(postAqlQry)
73
118
  .then((cursor: ArrayCursor) => cursor.all())
@@ -83,22 +128,17 @@ export const getPostListByGroup = (context: ApiContext, groupId: string, from: n
83
128
  });
84
129
  };
85
130
 
86
- export const getPostListByLatest = (context: ApiContext, from: number, to: number): Promise<PostType[]> => {
131
+ export const getPostListByLatest = (context: ApiContext, options?: PostOptions): Promise<PostType[]> => {
87
132
  // const action: string = 'getListByLatest';
88
- const {database} = context;
89
- const limit: ArangoDBLimit = getLimit(from, to);
133
+ const {database, fields} = context;
134
+ const {limit, type} = parsePostOptions(options);
135
+ const {objects: selectObjects, queries: selectQueries} = getPostOptional(fields);
90
136
  const aqlQry: string = `FOR p IN posts
91
- FILTER p.privacy == "public" && !!p.parent == false
92
- LET reactions = (
93
- FOR post, r IN INBOUND p._id reactions
94
- COLLECT reactionName = r.value INTO reactionItems
95
- RETURN {name: reactionName, count: LENGTH(reactionItems[*].r.value)}
96
- )
97
- FOR u IN users
98
- FILTER p.userId == u._key
99
- ${limit.aql}
100
- SORT p.added
101
- RETURN DISTINCT MERGE(p, {user:u, reactions:reactions})`;
137
+ FILTER p.type == "${type}" && p.privacy == "public" && p.parent == null
138
+ ${selectQueries.join('\n')}
139
+ ${limit.aql}
140
+ SORT p.added
141
+ RETURN DISTINCT MERGE(p, {${selectObjects.join(', ')}})`;
102
142
 
103
143
  return useDb(database).query(aqlQry)
104
144
  .then((cursor: ArrayCursor) => cursor.all())
@@ -107,31 +147,47 @@ export const getPostListByLatest = (context: ApiContext, from: number, to: numbe
107
147
  });
108
148
  };
109
149
 
110
- export const getPostListByTags = (context: ApiContext, tagNames: string[], from?: number, to?: number): Promise<PostType[]> => {
150
+ export const getPostListByTags = (
151
+ context: ApiContext,
152
+ tagNames: string[],
153
+ options?: PostOptions
154
+ ): Promise<PostType[]> => {
111
155
  // const action: string = 'getListByTags';
112
- const {database} = context;
156
+ const {database, fields} = context;
157
+ const {latitude, longitude, limit, type} = parsePostOptions(options);
158
+ const {objects: selectObjects, queries: selectQueries} = getPostOptional(fields);
159
+ const sortBy: string[] = [];
160
+
161
+ if(latitude !== undefined && longitude !== undefined) {
162
+ const formatLatitude: number = parseNum(latitude);
163
+ const formatLongitude: number = parseNum(longitude);
164
+ selectQueries.push(`LET distance = DISTANCE(
165
+ ${formatLatitude},
166
+ ${formatLongitude},
167
+ NOT_NULL(p.latitude, 0),
168
+ NOT_NULL(p.longitude, 0))
169
+ `);
170
+ selectObjects.push('distance:distance');
171
+ sortBy.push('distance');
172
+ }
173
+
174
+ sortBy.push('p.added');
113
175
 
114
176
  return Promise.all(
115
177
  tagNames.map((tagName: string) => {
116
- const formatTagId: string = createHash(`tag-${tagName}`, null);
117
- const limit: ArangoDBLimit = getLimit(from, to);
118
- const aqlQry: string = `FOR p, e IN OUTBOUND "${`tags/${formatTagId}`}" isTagged
119
- FOR u IN users
120
- LET reactions = (
121
- FOR post, r IN INBOUND p._id reactions
122
- COLLECT reactionName = r.value INTO reactionItems
123
- RETURN {name: reactionName, count: LENGTH(reactionItems[*].r.value)}
124
- )
125
- FILTER e.type == 'posts' && p.userId == u._key
126
- ${limit.aql}
127
- SORT p.added
128
- RETURN DISTINCT MERGE(p, {user:u, reactions:reactions})`;
129
-
178
+ const aqlQry: string = `FOR targetTag IN tags
179
+ FILTER targetTag.name == "${tagName}"
180
+ FOR p, e IN OUTBOUND targetTag._id isTagged
181
+ ${selectQueries.join('\n')}
182
+ FILTER p.type = "${type}" && p.privacy == "public" && e.type == 'posts'
183
+ ${limit.aql}
184
+ SORT ${sortBy.join(', ')}
185
+ RETURN DISTINCT MERGE(p, {${selectObjects.join(', ')}})`;
186
+
187
+ console.log(aqlQry);
130
188
  return useDb(database).query(aqlQry)
131
189
  .then((cursor: ArrayCursor) => cursor.all())
132
- .catch((error: Error) => {
133
- throw error;
134
- });
190
+ .catch(() => []);
135
191
  }))
136
192
  .then((results) => uniqBy(flatten(results), '_key'))
137
193
  .catch((error: Error) => {
@@ -139,23 +195,52 @@ export const getPostListByTags = (context: ApiContext, tagNames: string[], from?
139
195
  });
140
196
  };
141
197
 
142
- export const getPostListByUser = (context: ApiContext, userId: string, from: number, to: number): Promise<PostType[]> => {
198
+ export const getPostListByUser = (context: ApiContext, userId: string, options?: PostOptions): Promise<PostType[]> => {
143
199
  // const action: string = 'getListByUser';
144
- const {database} = context;
200
+ const {database, fields} = context;
201
+ const {limit, type} = parsePostOptions(options);
145
202
  const formatUserId: string = parseId(userId);
146
- const limit: ArangoDBLimit = getLimit(from, to);
203
+ const {objects: selectObjects, queries: selectQueries} = getPostOptional(fields);
204
+ const aqlQry: string = `FOR p IN posts
205
+ FILTER p.userId == "${formatUserId}" && p.type == "${type}" && p.privacy == "public" && p.parent == null
206
+ ${selectQueries.join('\n')}
207
+ ${limit.aql}
208
+ SORT p.added
209
+ RETURN DISTINCT MERGE(p, {${selectObjects.join(', ')}})`;
210
+
211
+ return useDb(database).query(aqlQry)
212
+ .then((cursor: ArrayCursor) => cursor.all())
213
+ .catch((error: Error) => {
214
+ throw error;
215
+ });
216
+ };
217
+
218
+ export const getPostListByArea = (
219
+ context: ApiContext,
220
+ latitude: number,
221
+ longitude: number,
222
+ options?: PostOptions
223
+ ): Promise<PostType[]> => {
224
+ // const action: string = 'getListByUser';
225
+ const {database, fields} = context;
226
+ const {limit, type} = parsePostOptions(options);
227
+ const formatLatitude: number = parseNum(latitude);
228
+ const formatLongitude: number = parseNum(longitude);
229
+ const {objects: selectObjects, queries: selectQueries} = getPostOptional(fields);
230
+ selectQueries.push(`LET distance = DISTANCE(
231
+ ${formatLatitude},
232
+ ${formatLongitude},
233
+ NOT_NULL(p.latitude, 0),
234
+ NOT_NULL(p.longitude, 0))
235
+ `);
236
+ selectObjects.push('distance:distance');
237
+
147
238
  const aqlQry: string = `FOR p IN posts
148
- FILTER p.userId == "${formatUserId}" && !!p.parent == false
149
- LET reactions = (
150
- FOR post, r IN INBOUND p._id reactions
151
- COLLECT reactionName = r.value INTO reactionItems
152
- RETURN {name: reactionName, count: LENGTH(reactionItems[*].r.value)}
153
- )
154
- FOR u IN users
155
- FILTER p.userId == u._key
156
- ${limit.aql}
157
- SORT p.added
158
- RETURN DISTINCT MERGE(p, {user:u, reactions:reactions})`;
239
+ ${selectQueries.join('\n')}
240
+ FILTER p.type == "${type}" && p.privacy == "public" && p.parentId == null
241
+ ${limit.aql}
242
+ SORT distance, p.added
243
+ RETURN DISTINCT MERGE(p, {${selectObjects.join(', ')}})`;
159
244
 
160
245
  return useDb(database).query(aqlQry)
161
246
  .then((cursor: ArrayCursor) => cursor.all())
@@ -166,13 +251,14 @@ export const getPostListByUser = (context: ApiContext, userId: string, from: num
166
251
 
167
252
  export const getPost = (context: ApiContext, itemId: string): Promise<PostType> => {
168
253
  // const action: string = 'getItem';
169
- const {database, userId: sessionId} = context;
254
+ const {database, fields, userId: sessionId} = context;
170
255
  const formatItemId: string = parseId(itemId);
171
256
  const db = useDb(database);
257
+ const {objects: selectObjects, queries: selectQueries} = getPostOptional(fields);
172
258
  const aqlQry: AqlQuery = aql`FOR p IN posts
173
- FILTER p._key == ${formatItemId}
174
- LIMIT 1
175
- RETURN p`;
259
+ FILTER p._key == ${formatItemId}
260
+ LIMIT 1
261
+ RETURN p`;
176
262
 
177
263
  return db.query(aqlQry)
178
264
  .then((cursor: ArrayCursor) => cursor.next())
@@ -184,34 +270,24 @@ export const getPost = (context: ApiContext, itemId: string): Promise<PostType>
184
270
  }: PostType = post;
185
271
 
186
272
  // Query based on privacy level
187
- let privacyAqlQry: AqlQuery;
273
+ let privacyAqlQry: string;
188
274
 
189
275
  if(groupId && privacy === 'group') {
190
- privacyAqlQry = aql`FOR p IN posts
191
- FOR user IN users
192
- FILTER p._key == ${_key} && user._key == p.userId
193
- LET reactions = (
194
- FOR post, r IN INBOUND p._id reactions
195
- COLLECT reactionName = r.value INTO reactionItems
196
- RETURN {name: reactionName, count: LENGTH(reactionItems[*].r.value)}
197
- )
276
+ privacyAqlQry = `FOR p IN posts
277
+ FILTER p._key == "${_key}"
278
+ ${selectQueries.join('\n')}
198
279
  FOR group IN groups
199
280
  FILTER group._key == p.groupId
200
281
  FOR u, e IN OUTBOUND group._id isGrouped
201
282
  FILTER u._key == ${sessionId}
202
283
  LIMIT 1
203
- RETURN MERGE(p, {user: user, reactions: reactions})`;
284
+ RETURN MERGE(p, {${selectObjects.join(', ')}})`;
204
285
  } else if(privacy === 'public') {
205
- privacyAqlQry = aql`FOR p IN posts
206
- FOR user IN users
207
- FILTER p._key == ${_key} && user._key == p.userId
208
- LET reactions = (
209
- FOR post, r IN INBOUND p._id reactions
210
- COLLECT reactionName = r.value INTO reactionItems
211
- RETURN {name: reactionName, count: LENGTH(reactionItems[*].r.value)}
212
- )
286
+ privacyAqlQry = `FOR p IN posts
287
+ FILTER p._key == "${_key}"
288
+ ${selectQueries.join('\n')}
213
289
  LIMIT 1
214
- RETURN MERGE(p, {user: user, reactions: reactions})`;
290
+ RETURN MERGE(p, {${selectObjects.join(', ')}})`;
215
291
  }
216
292
 
217
293
  if(privacyAqlQry) {
@@ -230,17 +306,18 @@ export const getPost = (context: ApiContext, itemId: string): Promise<PostType>
230
306
  });
231
307
  };
232
308
 
233
- export const getPostComments = (context: ApiContext, itemId: string, from: number, to: number): Promise<PostType[]> => {
309
+ export const getPostComments = (context: ApiContext, itemId: string, options?: PostOptions): Promise<PostType[]> => {
234
310
  // const action: string = 'getComments';
235
311
  const {database, userId: sessionId} = context;
312
+ const {limit, type} = parsePostOptions(options);
236
313
  const formatItemId: string = parseId(itemId);
237
314
 
238
315
  // Get the parent post to get restrictions
239
316
  const db = useDb(database);
240
317
  const aqlQry: AqlQuery = aql`FOR p IN posts
241
- FILTER p._key == ${formatItemId}
242
- LIMIT 1
243
- RETURN p`;
318
+ FILTER p.type == ${type} && p._key == ${formatItemId}
319
+ LIMIT 1
320
+ RETURN p`;
244
321
 
245
322
  return db.query(aqlQry)
246
323
  .then((cursor: ArrayCursor) => cursor.next())
@@ -253,36 +330,35 @@ export const getPostComments = (context: ApiContext, itemId: string, from: numbe
253
330
 
254
331
  // Query based on privacy level
255
332
  let privacyAqlQry: string;
256
- const limit = getLimit(from, to);
257
333
 
258
334
  if(groupId && privacy === 'group') {
259
335
  privacyAqlQry = `FOR p IN posts
260
- FOR user IN users
261
- FILTER p.parent == "${_key}" && user._key == p.userId
262
- LET reactions = (
263
- FOR post, r IN INBOUND p._id reactions
264
- COLLECT reactionName = r.value INTO reactionItems
265
- RETURN {name: reactionName, count: LENGTH(reactionItems[*].r.value)}
266
- )
267
- FOR group IN groups
268
- FILTER group._key == p.groupId
269
- FOR u, e IN OUTBOUND group._id isGrouped
270
- FILTER u._key == "${sessionId}"
271
- SORT p.added
272
- ${limit.aql}
273
- RETURN MERGE(p, {user: user, reactions: reactions})`;
336
+ FOR user IN users
337
+ FILTER p.parent == "${_key}" && user._key == p.userId
338
+ LET reactions = (
339
+ FOR post, r IN INBOUND p._id reactions
340
+ COLLECT reactionName = r.value INTO reactionItems
341
+ RETURN {name: reactionName, count: LENGTH(reactionItems[*].r.value)}
342
+ )
343
+ FOR group IN groups
344
+ FILTER group._key == p.groupId
345
+ FOR u, e IN OUTBOUND group._id isGrouped
346
+ FILTER u._key == "${sessionId}"
347
+ SORT p.added
348
+ ${limit.aql}
349
+ RETURN MERGE(p, {user: user, reactions: reactions})`;
274
350
  } else if(privacy === 'public') {
275
351
  privacyAqlQry = `FOR p IN posts
276
- FOR user IN users
277
- FILTER p.parent == "${_key}" && user._key == p.userId
278
- LET reactions = (
279
- FOR post, r IN INBOUND p._id reactions
280
- COLLECT reactionName = r.value INTO reactionItems
281
- RETURN {name: reactionName, count: LENGTH(reactionItems[*].r.value)}
282
- )
283
- SORT p.added
284
- ${limit.aql}
285
- RETURN MERGE(p, {user: user, reactions: reactions})`;
352
+ FOR user IN users
353
+ FILTER p.parent == "${_key}" && user._key == p.userId
354
+ LET reactions = (
355
+ FOR post, r IN INBOUND p._id reactions
356
+ COLLECT reactionName = r.value INTO reactionItems
357
+ RETURN {name: reactionName, count: LENGTH(reactionItems[*].r.value)}
358
+ )
359
+ SORT p.added
360
+ ${limit.aql}
361
+ RETURN MERGE(p, {user: user, reactions: reactions})`;
286
362
  }
287
363
 
288
364
  if(privacyAqlQry) {
@@ -305,12 +381,15 @@ export const addPost = (context: ApiContext, item: PostType): Promise<PostType>
305
381
  const {database, userId: sessionId} = context;
306
382
 
307
383
  const {
384
+ content = '',
308
385
  groupId = '',
386
+ location,
387
+ latitude,
388
+ longitude,
309
389
  name = '',
310
- parentId = '',
390
+ parentId = null,
311
391
  privacy = 'public',
312
- text = '',
313
- title = ''
392
+ type = 'default'
314
393
  }: PostType = item;
315
394
 
316
395
  const now: number = Date.now();
@@ -318,15 +397,19 @@ export const addPost = (context: ApiContext, item: PostType): Promise<PostType>
318
397
  const insert: PostType = {
319
398
  _key: createHash(`post-${sessionId}`),
320
399
  added: now,
321
- groupId: parseId(groupId),
400
+ content: parseString(content, MAX_CONTENT_LENGTH),
401
+ groupId: groupId ? parseId(groupId) : undefined,
402
+ latitude: latitude !== undefined ? parseNum(latitude) : undefined,
403
+ location: location ? parseString(location, 160) : undefined,
404
+ longitude: longitude !== undefined ? parseNum(longitude) : undefined,
322
405
  modified: now,
323
406
  name: parseString(name, 160),
324
- parentId: parseId(parentId),
325
- privacy: parseVarChar(privacy, 16),
326
- text: parseString(text, 20000),
327
- title: parseString(title, 160),
407
+ parentId: parentId ? parseId(parentId) : undefined,
408
+ privacy: privacy ? parseVarChar(privacy, 16) : undefined,
409
+ type: parseChar(type, 32),
328
410
  userId: sessionId
329
411
  };
412
+
330
413
  const db: Database = useDb(database);
331
414
  const aqlQry: AqlQuery = aql`INSERT ${insert} IN posts RETURN NEW`;
332
415
 
@@ -336,7 +419,7 @@ export const addPost = (context: ApiContext, item: PostType): Promise<PostType>
336
419
  const {_key: postKey} = post;
337
420
 
338
421
  // Update linked tags within posts
339
- return extractTags(db, 'posts', postKey, insert.text)
422
+ return extractTags(db, 'posts', postKey, insert.content)
340
423
  .then((tagList: TagType[]) => {
341
424
  post.tags = tagList;
342
425
  return post;
@@ -352,36 +435,25 @@ export const updatePost = (context: ApiContext, item: PostType): Promise<PostTyp
352
435
  const {database, userId: sessionId} = context;
353
436
  const now: number = Date.now();
354
437
  const {
438
+ content,
355
439
  groupId,
356
- id,
357
440
  name,
358
441
  parentId,
442
+ postId,
359
443
  privacy,
360
- text
444
+ type
361
445
  }: PostType = item;
362
446
 
363
- const updatedPost: PostType = {
364
- modified: now
447
+ const update: PostType = {
448
+ content: content ? parseString(content, MAX_CONTENT_LENGTH) : undefined,
449
+ modified: now,
450
+ name: name ? parseString(name, 160) : undefined,
451
+ parentId: parentId ? parseString(parentId, 160) : undefined,
452
+ privacy: privacy ? parseVarChar(privacy, 16) : undefined,
453
+ type: type !== undefined ? parseChar(type, 16) : undefined
365
454
  };
366
455
 
367
- if(name) {
368
- updatedPost.name = parseString(name, 160);
369
- }
370
-
371
- if(text) {
372
- updatedPost.text = parseString(text, 640);
373
- }
374
-
375
- if(privacy) {
376
- updatedPost.privacy = parseVarChar(privacy, 16);
377
- }
378
-
379
- if(parent) {
380
- updatedPost.parentId = parseId(parentId);
381
- }
382
- const update: any = updatedPost;
383
-
384
- let formatId: string = parseId(id);
456
+ let formatId: string = parseId(postId);
385
457
  formatId = formatId === '' ? createHash(`post-${sessionId}`) : formatId;
386
458
  const formatGroupId: string = parseId(groupId);
387
459
  const insert: any = {
@@ -393,10 +465,10 @@ export const updatePost = (context: ApiContext, item: PostType): Promise<PostTyp
393
465
  userId: sessionId
394
466
  };
395
467
  const db: Database = useDb(database);
396
- const aqlQry: AqlQuery = aql`UPSERT {_key: ${id}, userId: ${sessionId}}
397
- INSERT ${insert}
398
- UPDATE ${update}
399
- IN posts RETURN NEW`;
468
+ const aqlQry: AqlQuery = aql`UPSERT {_key: ${formatId}, userId: ${sessionId}}
469
+ INSERT ${insert}
470
+ UPDATE ${update}
471
+ IN posts RETURN NEW`;
400
472
 
401
473
  return db.query(aqlQry)
402
474
  .then((cursor: ArrayCursor) => cursor.next())
@@ -404,7 +476,7 @@ export const updatePost = (context: ApiContext, item: PostType): Promise<PostTyp
404
476
  const {_key: updatedPostKey} = updatedPost;
405
477
 
406
478
  // Update linked tags
407
- return extractTags(db, 'posts', updatedPostKey, update.text || '')
479
+ return extractTags(db, 'posts', updatedPostKey, update.content || '')
408
480
  .then((tagList = []) => {
409
481
  updatedPost.tags = tagList;
410
482
 
@@ -412,7 +484,7 @@ export const updatePost = (context: ApiContext, item: PostType): Promise<PostTyp
412
484
  const files: FileType[] = updatedPost.files || [];
413
485
 
414
486
  if(files.length) {
415
- return updateFiles(db, id, files)
487
+ return updateFiles(db, formatId, files)
416
488
  .then((fileList = []) => {
417
489
  updatedPost.files = fileList;
418
490
  return updatedPost;
@@ -475,7 +547,7 @@ export const deletePost = (context: ApiContext, itemId: string): Promise<PostTyp
475
547
  export const cleanPosts = (database: string): Promise<number> => {
476
548
  // Remove all messages that are over 60 days and not saved
477
549
  const aqlQry: AqlQuery = aql`FOR p IN posts
478
- FILTER p.added < DATE_TIMESTAMP(DATE_SUBTRACT(DATE_NOW(), 60, 'day')) && p.type == 1
550
+ FILTER p.added < DATE_TIMESTAMP(DATE_SUBTRACT(DATE_NOW(), 60, 'day')) && p.type == "default"
479
551
  REMOVE p IN posts
480
552
  RETURN OLD`;
481
553
 
package/src/data/users.ts CHANGED
@@ -207,13 +207,11 @@ export const getUsersByRelations = (
207
207
  const formatUserId: string = parseId(userId);
208
208
  const formatType: string = parseChar(type, 32);
209
209
  const limit = getLimit(from, to);
210
- console.log('context', context);
211
210
  const aqlQry: string = `FOR u, r IN INBOUND "${`users/${formatUserId}`}" hasRelation
212
211
  FILTER r.type == "${formatType}"
213
212
  ${limit.aql}
214
213
  RETURN u`;
215
214
 
216
- console.log('getUsersByRelations::aqlQry', aqlQry);
217
215
  return useDb(database).query(aqlQry)
218
216
  .then((cursor: ArrayCursor) => cursor.all())
219
217
  .catch((error: Error) => logError({
package/src/types/apps.ts CHANGED
@@ -11,7 +11,6 @@ export interface TestType {
11
11
  export interface AppSessionType {
12
12
  readonly active?: boolean;
13
13
  readonly added?: number;
14
- readonly appId?: string;
15
14
  readonly exp?: number;
16
15
  readonly modified?: number;
17
16
  readonly name?: string;
package/src/types/auth.ts CHANGED
@@ -6,6 +6,7 @@ export interface ApiContext {
6
6
  readonly appId: string;
7
7
  readonly database: string;
8
8
  readonly email: string;
9
+ readonly fields?: string[];
9
10
  readonly ipAddress: string;
10
11
  readonly userId: string;
11
12
  readonly username: string;
@@ -5,7 +5,6 @@
5
5
  export interface FileType {
6
6
  readonly _key?: string;
7
7
  readonly added?: number;
8
- readonly appId?: string;
9
8
  readonly base64?: string;
10
9
  readonly buffer?: Buffer;
11
10
  readonly description?: string;
@@ -26,7 +25,6 @@ export interface FileDecodedType {
26
25
  }
27
26
 
28
27
  export interface FileEdgeType {
29
- readonly appId?: string;
30
28
  readonly imgId?: string;
31
29
  readonly itemId?: string;
32
30
  readonly itemType?: string;
@@ -5,7 +5,6 @@
5
5
  export interface GroupType {
6
6
  readonly _key?: string;
7
7
  readonly added?: number;
8
- readonly appId?: string;
9
8
  readonly description?: string;
10
9
  readonly groupId?: string;
11
10
  readonly id?: string;
@@ -23,7 +23,6 @@ export interface ImageIdentifyType {
23
23
  export type ImageUrlTypes = 'app' | 'events' | 'groups' | 'users';
24
24
 
25
25
  export interface ImageUrlData {
26
- readonly appId?: string;
27
26
  readonly directory?: string;
28
27
  readonly imgId?: string;
29
28
  readonly imgType?: string;
@@ -6,7 +6,6 @@ export interface LocationType {
6
6
  readonly _key?: string;
7
7
  readonly address?: string;
8
8
  readonly added?: number;
9
- readonly appId?: string;
10
9
  readonly city?: string;
11
10
  readonly country?: string;
12
11
  readonly description?: string;