@nlabs/reaktor 0.1.2 → 0.1.3

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 (144) hide show
  1. package/.DS_Store +0 -0
  2. package/lib/config.d.ts +21 -0
  3. package/lib/config.js +130 -0
  4. package/lib/data/conversations.d.ts +6 -0
  5. package/lib/data/conversations.js +197 -0
  6. package/lib/data/dynamodb.d.ts +8 -0
  7. package/lib/data/dynamodb.js +139 -0
  8. package/lib/data/email.d.ts +7 -0
  9. package/lib/data/email.js +163 -0
  10. package/lib/data/files.d.ts +16 -0
  11. package/lib/data/files.js +406 -0
  12. package/lib/data/groups.d.ts +13 -0
  13. package/lib/data/groups.js +354 -0
  14. package/lib/data/images.d.ts +12 -0
  15. package/lib/data/images.js +667 -0
  16. package/{src/data/index.ts → lib/data/index.d.ts} +1 -5
  17. package/lib/data/index.js +24 -0
  18. package/lib/data/ios.d.ts +6 -0
  19. package/lib/data/ios.js +302 -0
  20. package/lib/data/locations.d.ts +3 -0
  21. package/lib/data/locations.js +132 -0
  22. package/lib/data/messages.d.ts +9 -0
  23. package/lib/data/messages.js +248 -0
  24. package/lib/data/notifications.d.ts +5 -0
  25. package/lib/data/notifications.js +42 -0
  26. package/lib/data/payments.d.ts +11 -0
  27. package/lib/data/payments.js +748 -0
  28. package/lib/data/posts.d.ts +22 -0
  29. package/lib/data/posts.js +578 -0
  30. package/lib/data/reactions.d.ts +6 -0
  31. package/lib/data/reactions.js +218 -0
  32. package/lib/data/s3.d.ts +6 -0
  33. package/lib/data/s3.js +103 -0
  34. package/lib/data/search.d.ts +3 -0
  35. package/lib/data/search.js +98 -0
  36. package/lib/data/sms.d.ts +3 -0
  37. package/lib/data/sms.js +59 -0
  38. package/lib/data/subscription.d.ts +7 -0
  39. package/lib/data/subscription.js +284 -0
  40. package/lib/data/tags.d.ts +14 -0
  41. package/lib/data/tags.js +304 -0
  42. package/lib/data/users.d.ts +12 -0
  43. package/lib/data/users.js +310 -0
  44. package/lib/index.d.ts +3 -0
  45. package/lib/index.js +8 -0
  46. package/lib/types/apps.d.ts +43 -0
  47. package/lib/types/apps.js +2 -0
  48. package/lib/types/arangodb.d.ts +17 -0
  49. package/lib/types/arangodb.js +2 -0
  50. package/lib/types/auth.d.ts +10 -0
  51. package/lib/types/auth.js +2 -0
  52. package/lib/types/conversations.d.ts +6 -0
  53. package/lib/types/conversations.js +2 -0
  54. package/lib/types/email.d.ts +12 -0
  55. package/lib/types/email.js +2 -0
  56. package/lib/types/files.d.ts +26 -0
  57. package/lib/types/files.js +2 -0
  58. package/lib/types/google.d.ts +27 -0
  59. package/lib/types/google.js +2 -0
  60. package/lib/types/groups.d.ts +21 -0
  61. package/lib/types/groups.js +2 -0
  62. package/lib/types/images.d.ts +24 -0
  63. package/lib/types/images.js +2 -0
  64. package/{src/types/index.ts → lib/types/index.d.ts} +0 -4
  65. package/lib/types/index.js +22 -0
  66. package/lib/types/locations.d.ts +20 -0
  67. package/lib/types/locations.js +2 -0
  68. package/lib/types/messages.d.ts +12 -0
  69. package/lib/types/messages.js +2 -0
  70. package/lib/types/notifications.d.ts +19 -0
  71. package/lib/types/notifications.js +2 -0
  72. package/lib/types/payments.d.ts +114 -0
  73. package/lib/types/payments.js +2 -0
  74. package/lib/types/posts.d.ts +28 -0
  75. package/lib/types/posts.js +2 -0
  76. package/lib/types/reactions.d.ts +4 -0
  77. package/lib/types/reactions.js +2 -0
  78. package/lib/types/tags.d.ts +9 -0
  79. package/lib/types/tags.js +2 -0
  80. package/lib/types/users.d.ts +78 -0
  81. package/lib/types/users.js +2 -0
  82. package/lib/utils/analytics.d.ts +3 -0
  83. package/lib/utils/analytics.js +47 -0
  84. package/lib/utils/arangodb.d.ts +9 -0
  85. package/lib/utils/arangodb.js +98 -0
  86. package/lib/utils/auth.d.ts +7 -0
  87. package/lib/utils/auth.js +80 -0
  88. package/lib/utils/graphql.d.ts +1 -0
  89. package/lib/utils/graphql.js +7 -0
  90. package/{src/utils/index.ts → lib/utils/index.d.ts} +0 -4
  91. package/lib/utils/index.js +11 -0
  92. package/lib/utils/objects.d.ts +3 -0
  93. package/lib/utils/objects.js +34 -0
  94. package/lib/utils/redis.d.ts +1 -0
  95. package/lib/utils/redis.js +15 -0
  96. package/package.json +5 -5
  97. package/.vscode/extensions.json +0 -15
  98. package/.vscode/settings.json +0 -82
  99. package/lex.config.js +0 -4
  100. package/src/config.ts +0 -127
  101. package/src/data/conversations.ts +0 -181
  102. package/src/data/dynamodb.ts +0 -157
  103. package/src/data/email.ts +0 -163
  104. package/src/data/files.ts +0 -352
  105. package/src/data/groups.ts +0 -308
  106. package/src/data/images.ts +0 -606
  107. package/src/data/ios.ts +0 -249
  108. package/src/data/locations.ts +0 -114
  109. package/src/data/messages.ts +0 -237
  110. package/src/data/notifications.ts +0 -48
  111. package/src/data/payments.ts +0 -675
  112. package/src/data/posts.ts +0 -580
  113. package/src/data/reactions.ts +0 -186
  114. package/src/data/s3.ts +0 -117
  115. package/src/data/search.ts +0 -74
  116. package/src/data/sms.ts +0 -60
  117. package/src/data/subscription.ts +0 -228
  118. package/src/data/tags.ts +0 -230
  119. package/src/data/users.ts +0 -254
  120. package/src/index.ts +0 -7
  121. package/src/types/apps.ts +0 -56
  122. package/src/types/arangodb.ts +0 -23
  123. package/src/types/auth.ts +0 -20
  124. package/src/types/conversations.ts +0 -11
  125. package/src/types/email.ts +0 -17
  126. package/src/types/files.ts +0 -31
  127. package/src/types/google.ts +0 -37
  128. package/src/types/groups.ts +0 -27
  129. package/src/types/images.ts +0 -32
  130. package/src/types/locations.ts +0 -24
  131. package/src/types/messages.ts +0 -16
  132. package/src/types/notifications.ts +0 -26
  133. package/src/types/payments.ts +0 -129
  134. package/src/types/posts.ts +0 -34
  135. package/src/types/reactions.ts +0 -8
  136. package/src/types/tags.ts +0 -13
  137. package/src/types/users.ts +0 -89
  138. package/src/utils/analytics.ts +0 -41
  139. package/src/utils/arangodb.ts +0 -100
  140. package/src/utils/auth.ts +0 -61
  141. package/src/utils/graphql.ts +0 -7
  142. package/src/utils/objects.ts +0 -34
  143. package/src/utils/redis.ts +0 -17
  144. package/tsconfig.json +0 -45
package/src/data/posts.ts DELETED
@@ -1,580 +0,0 @@
1
- /**
2
- * Copyright (c) 2019-Present, Nitrogen Labs, Inc.
3
- * Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms.
4
- */
5
- import {createHash, parseChar, parseId, parseNum, parseString, parseVarChar} from '@nlabs/utils';
6
- import {aql, Database} from 'arangojs';
7
- import {AqlQuery} from 'arangojs/lib/cjs/aql-query';
8
- import {ArrayCursor} from 'arangojs/lib/cjs/cursor';
9
- import flatten from 'lodash/flatten';
10
- import uniqBy from 'lodash/uniqBy';
11
-
12
- import {ApiContext, FileType, GroupType, PostOptions, PostType, TagType} from '../types';
13
- import {getLimit, useDb} from '../utils';
14
- import {updateFiles} from './files';
15
- import {extractTags} from './tags';
16
-
17
- // const eventCategory: string = 'posts';
18
- const MAX_CONTENT_LENGTH: number = 100000;
19
-
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[]> => {
75
- // const action: string = 'getListByApp';
76
- const {database, fields} = context;
77
- const {limit, type} = parsePostOptions(options);
78
- const {objects: selectObjects, queries: selectQueries} = getPostOptional(fields);
79
- const aqlQry: string = `FOR p IN posts
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(', ')}})`;
85
-
86
- return useDb(database).query(aqlQry)
87
- .then((cursor: ArrayCursor) => cursor.all())
88
- .catch((error: Error) => {
89
- throw error;
90
- });
91
- };
92
-
93
- export const getPostListByGroup = (context: ApiContext, groupId: string, options?: PostOptions): Promise<PostType[]> => {
94
- // const action: string = 'getListByGroup';
95
- const {database, fields, userId: sessionId} = context;
96
- const {objects: selectObjects, queries: selectQueries} = getPostOptional(fields);
97
-
98
- // Group id
99
- const formatGroupId: string = parseId(groupId);
100
- const db = useDb(database);
101
- const aqlQry: string = `FOR u, g IN INBOUND ${formatGroupId} hasGroup
102
- FILTER u._key == ${sessionId}
103
- RETURN g`;
104
-
105
- return db.query(aqlQry)
106
- .then((cursor: ArrayCursor) => cursor.all())
107
- .then((groups: GroupType[] = []) => {
108
- if(groups.length) {
109
- const {limit, type} = parsePostOptions(options);
110
- const postAqlQry: string = `FOR p IN posts
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(', ')}})`;
116
-
117
- return db.query(postAqlQry)
118
- .then((cursor: ArrayCursor) => cursor.all())
119
- .catch((error: Error) => {
120
- throw error;
121
- });
122
- }
123
-
124
- return [];
125
- })
126
- .catch((error: Error) => {
127
- throw error;
128
- });
129
- };
130
-
131
- export const getPostListByLatest = (context: ApiContext, options?: PostOptions): Promise<PostType[]> => {
132
- // const action: string = 'getListByLatest';
133
- const {database, fields} = context;
134
- const {limit, type} = parsePostOptions(options);
135
- const {objects: selectObjects, queries: selectQueries} = getPostOptional(fields);
136
- const aqlQry: string = `FOR p IN posts
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(', ')}})`;
142
-
143
- return useDb(database).query(aqlQry)
144
- .then((cursor: ArrayCursor) => cursor.all())
145
- .catch((error: Error) => {
146
- throw error;
147
- });
148
- };
149
-
150
- export const getPostListByTags = (
151
- context: ApiContext,
152
- tagNames: string[],
153
- options?: PostOptions
154
- ): Promise<PostType[]> => {
155
- // const action: string = 'getListByTags';
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');
175
-
176
- return Promise.all(
177
- tagNames.map((tagName: string) => {
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);
188
- return useDb(database).query(aqlQry)
189
- .then((cursor: ArrayCursor) => cursor.all())
190
- .catch(() => []);
191
- }))
192
- .then((results) => uniqBy(flatten(results), '_key'))
193
- .catch((error: Error) => {
194
- throw error;
195
- });
196
- };
197
-
198
- export const getPostListByUser = (context: ApiContext, userId: string, options?: PostOptions): Promise<PostType[]> => {
199
- // const action: string = 'getListByUser';
200
- const {database, fields} = context;
201
- const {limit, type} = parsePostOptions(options);
202
- const formatUserId: string = parseId(userId);
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
-
238
- const aqlQry: string = `FOR p IN posts
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(', ')}})`;
244
-
245
- return useDb(database).query(aqlQry)
246
- .then((cursor: ArrayCursor) => cursor.all())
247
- .catch((error: Error) => {
248
- throw error;
249
- });
250
- };
251
-
252
- export const getPost = (context: ApiContext, itemId: string): Promise<PostType> => {
253
- // const action: string = 'getItem';
254
- const {database, fields, userId: sessionId} = context;
255
- const formatItemId: string = parseId(itemId);
256
- const db = useDb(database);
257
- const {objects: selectObjects, queries: selectQueries} = getPostOptional(fields);
258
- const aqlQry: AqlQuery = aql`FOR p IN posts
259
- FILTER p._key == ${formatItemId}
260
- LIMIT 1
261
- RETURN p`;
262
-
263
- return db.query(aqlQry)
264
- .then((cursor: ArrayCursor) => cursor.next())
265
- .then((post: PostType = {}) => {
266
- const {
267
- _key,
268
- groupId,
269
- privacy = 'default'
270
- }: PostType = post;
271
-
272
- // Query based on privacy level
273
- let privacyAqlQry: string;
274
-
275
- if(groupId && privacy === 'group') {
276
- privacyAqlQry = `FOR p IN posts
277
- FILTER p._key == "${_key}"
278
- ${selectQueries.join('\n')}
279
- FOR group IN groups
280
- FILTER group._key == p.groupId
281
- FOR u, e IN OUTBOUND group._id isGrouped
282
- FILTER u._key == ${sessionId}
283
- LIMIT 1
284
- RETURN MERGE(p, {${selectObjects.join(', ')}})`;
285
- } else if(privacy === 'public') {
286
- privacyAqlQry = `FOR p IN posts
287
- FILTER p._key == "${_key}"
288
- ${selectQueries.join('\n')}
289
- LIMIT 1
290
- RETURN MERGE(p, {${selectObjects.join(', ')}})`;
291
- }
292
-
293
- if(privacyAqlQry) {
294
- return db.query(privacyAqlQry)
295
- .then((cursor: ArrayCursor) => cursor.next())
296
- .then((filteredPost: PostType = {}) => filteredPost)
297
- .catch((error: Error) => {
298
- throw error;
299
- });
300
- }
301
-
302
- return {};
303
- })
304
- .catch((error: Error) => {
305
- throw error;
306
- });
307
- };
308
-
309
- export const getPostComments = (context: ApiContext, itemId: string, options?: PostOptions): Promise<PostType[]> => {
310
- // const action: string = 'getComments';
311
- const {database, userId: sessionId} = context;
312
- const {limit, type} = parsePostOptions(options);
313
- const formatItemId: string = parseId(itemId);
314
-
315
- // Get the parent post to get restrictions
316
- const db = useDb(database);
317
- const aqlQry: AqlQuery = aql`FOR p IN posts
318
- FILTER p.type == ${type} && p._key == ${formatItemId}
319
- LIMIT 1
320
- RETURN p`;
321
-
322
- return db.query(aqlQry)
323
- .then((cursor: ArrayCursor) => cursor.next())
324
- .then((post: PostType = {}) => {
325
- const {
326
- _key,
327
- groupId,
328
- privacy = 'public'
329
- }: PostType = post;
330
-
331
- // Query based on privacy level
332
- let privacyAqlQry: string;
333
-
334
- if(groupId && privacy === 'group') {
335
- privacyAqlQry = `FOR p IN posts
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})`;
350
- } else if(privacy === 'public') {
351
- privacyAqlQry = `FOR p IN posts
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})`;
362
- }
363
-
364
- if(privacyAqlQry) {
365
- return db.query(privacyAqlQry)
366
- .then((cursor: ArrayCursor) => cursor.all())
367
- .catch((error: Error) => {
368
- throw error;
369
- });
370
- }
371
-
372
- return [];
373
- })
374
- .catch((error: Error) => {
375
- throw error;
376
- });
377
- };
378
-
379
- export const addPost = (context: ApiContext, item: PostType): Promise<PostType> => {
380
- // const action: string = 'add';
381
- const {database, userId: sessionId} = context;
382
-
383
- const {
384
- content = '',
385
- groupId = '',
386
- location,
387
- latitude,
388
- longitude,
389
- name = '',
390
- parentId = null,
391
- privacy = 'public',
392
- type = 'default'
393
- }: PostType = item;
394
-
395
- const now: number = Date.now();
396
-
397
- const insert: PostType = {
398
- _key: createHash(`post-${sessionId}`),
399
- added: now,
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,
405
- modified: now,
406
- name: parseString(name, 160),
407
- parentId: parentId ? parseId(parentId) : undefined,
408
- privacy: privacy ? parseVarChar(privacy, 16) : undefined,
409
- type: parseChar(type, 32),
410
- userId: sessionId
411
- };
412
-
413
- const db: Database = useDb(database);
414
- const aqlQry: AqlQuery = aql`INSERT ${insert} IN posts RETURN NEW`;
415
-
416
- return db.query(aqlQry)
417
- .then((cursor: ArrayCursor) => cursor.next())
418
- .then((post: PostType = {}) => {
419
- const {_key: postKey} = post;
420
-
421
- // Update linked tags within posts
422
- return extractTags(db, 'posts', postKey, insert.content)
423
- .then((tagList: TagType[]) => {
424
- post.tags = tagList;
425
- return post;
426
- });
427
- })
428
- .catch((error: Error) => {
429
- throw error;
430
- });
431
- };
432
-
433
- export const updatePost = (context: ApiContext, item: PostType): Promise<PostType> => {
434
- // const action: string = 'update';
435
- const {database, userId: sessionId} = context;
436
- const now: number = Date.now();
437
- const {
438
- content,
439
- groupId,
440
- name,
441
- parentId,
442
- postId,
443
- privacy,
444
- type
445
- }: PostType = item;
446
-
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
454
- };
455
-
456
- let formatId: string = parseId(postId);
457
- formatId = formatId === '' ? createHash(`post-${sessionId}`) : formatId;
458
- const formatGroupId: string = parseId(groupId);
459
- const insert: any = {
460
- ...update,
461
- _key: formatId,
462
- added: now,
463
- groupId: formatGroupId,
464
- privacy,
465
- userId: sessionId
466
- };
467
- const db: Database = useDb(database);
468
- const aqlQry: AqlQuery = aql`UPSERT {_key: ${formatId}, userId: ${sessionId}}
469
- INSERT ${insert}
470
- UPDATE ${update}
471
- IN posts RETURN NEW`;
472
-
473
- return db.query(aqlQry)
474
- .then((cursor: ArrayCursor) => cursor.next())
475
- .then((updatedPost: PostType = {}) => {
476
- const {_key: updatedPostKey} = updatedPost;
477
-
478
- // Update linked tags
479
- return extractTags(db, 'posts', updatedPostKey, update.content || '')
480
- .then((tagList = []) => {
481
- updatedPost.tags = tagList;
482
-
483
- // Update linked files
484
- const files: FileType[] = updatedPost.files || [];
485
-
486
- if(files.length) {
487
- return updateFiles(db, formatId, files)
488
- .then((fileList = []) => {
489
- updatedPost.files = fileList;
490
- return updatedPost;
491
- });
492
- }
493
-
494
- updatedPost.files = [];
495
- return updatedPost;
496
- });
497
- })
498
- .catch((error: Error) => {
499
- throw error;
500
- });
501
- };
502
-
503
- export const deletePost = (context: ApiContext, itemId: string): Promise<PostType> => {
504
- // const action: string = 'delete';
505
- const {database, userId: sessionId} = context;
506
- const formatItemId: string = parseId(itemId);
507
- const db: Database = useDb(database);
508
- const aqlQry = aql`FOR p IN posts
509
- FILTER p._key == ${formatItemId} && p.userId == ${sessionId}
510
- LIMIT 1
511
- REMOVE p IN posts
512
- RETURN OLD`;
513
-
514
- return db.query(aqlQry)
515
- .then((cursor: ArrayCursor) => cursor.next())
516
- .then((post: PostType = {}) => {
517
- if(post) {
518
- // Remove tag links
519
- const edgeAqlQry: AqlQuery = aql`FOR t IN isTagged
520
- FILTER t._to == ${formatItemId}
521
- REMOVE t IN isTagged`;
522
-
523
- return db.query(edgeAqlQry)
524
- .then(() => {
525
- // Remove attached files
526
- const fileAqlQry: AqlQuery = aql`FOR f IN hasFile
527
- FILTER f._to == ${formatItemId}
528
- REMOVE f IN hasFile`;
529
-
530
- return db.query(fileAqlQry)
531
- .then(() => post)
532
- .catch((error: Error) => {
533
- throw error;
534
- });
535
- })
536
- .catch((error: Error) => {
537
- throw error;
538
- });
539
- }
540
- return {};
541
- })
542
- .catch((error: Error) => {
543
- throw error;
544
- });
545
- };
546
-
547
- export const cleanPosts = (database: string): Promise<number> => {
548
- // Remove all messages that are over 60 days and not saved
549
- const aqlQry: AqlQuery = aql`FOR p IN posts
550
- FILTER p.added < DATE_TIMESTAMP(DATE_SUBTRACT(DATE_NOW(), 60, 'day')) && p.type == "default"
551
- REMOVE p IN posts
552
- RETURN OLD`;
553
-
554
- return useDb(database).query(aqlQry)
555
- .then((cursor: ArrayCursor) => cursor.all())
556
- .then((results: PostType[] = []) => results.length)
557
- .catch((error: Error) => {
558
- throw error;
559
- });
560
- }
561
-
562
- export const createPostEdge = (db: Database, file: FileType, postId: string): Promise<FileType> => {
563
- const edgeCollection = db.edgeCollection('isPosted');
564
- const fileId: string = parseId(file.id);
565
- const edgeId: string = createHash(`file-${postId}-${fileId}`);
566
- const formatPostId: string = parseId(postId);
567
- const fileType: string = parseChar(file.fileType, 16);
568
-
569
- const edge: any = {
570
- _key: edgeId,
571
- added: Date.now(),
572
- type: fileType
573
- };
574
-
575
- return edgeCollection.save(edge, `posts/${formatPostId}`, `files/${fileId}`)
576
- .then(() => file)
577
- .catch((error: Error) => {
578
- throw error;
579
- });
580
- };