@nlabs/reaktor 0.1.1 → 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.
- package/.DS_Store +0 -0
- package/lib/config.js +10 -7
- package/lib/data/posts.d.ts +13 -7
- package/lib/data/posts.js +77 -39
- package/lib/types/posts.d.ts +1 -0
- package/package.json +8 -8
- package/.vscode/extensions.json +0 -15
- package/.vscode/settings.json +0 -82
- package/lex.config.js +0 -4
- package/src/config.ts +0 -121
- package/src/data/conversations.ts +0 -181
- package/src/data/dynamodb.ts +0 -157
- package/src/data/email.ts +0 -163
- package/src/data/files.ts +0 -352
- package/src/data/groups.ts +0 -308
- package/src/data/images.ts +0 -606
- package/src/data/index.ts +0 -23
- package/src/data/ios.ts +0 -249
- package/src/data/locations.ts +0 -114
- package/src/data/messages.ts +0 -237
- package/src/data/notifications.ts +0 -48
- package/src/data/payments.ts +0 -675
- package/src/data/posts.ts +0 -561
- package/src/data/reactions.ts +0 -186
- package/src/data/s3.ts +0 -117
- package/src/data/search.ts +0 -74
- package/src/data/sms.ts +0 -60
- package/src/data/subscription.ts +0 -228
- package/src/data/tags.ts +0 -230
- package/src/data/users.ts +0 -254
- package/src/index.ts +0 -7
- package/src/types/apps.ts +0 -56
- package/src/types/arangodb.ts +0 -23
- package/src/types/auth.ts +0 -20
- package/src/types/conversations.ts +0 -11
- package/src/types/email.ts +0 -17
- package/src/types/files.ts +0 -31
- package/src/types/google.ts +0 -37
- package/src/types/groups.ts +0 -27
- package/src/types/images.ts +0 -32
- package/src/types/index.ts +0 -21
- package/src/types/locations.ts +0 -24
- package/src/types/messages.ts +0 -16
- package/src/types/notifications.ts +0 -26
- package/src/types/payments.ts +0 -129
- package/src/types/posts.ts +0 -33
- package/src/types/reactions.ts +0 -8
- package/src/types/tags.ts +0 -13
- package/src/types/users.ts +0 -89
- package/src/utils/analytics.ts +0 -41
- package/src/utils/arangodb.ts +0 -100
- package/src/utils/auth.ts +0 -61
- package/src/utils/graphql.ts +0 -7
- package/src/utils/index.ts +0 -10
- package/src/utils/objects.ts +0 -34
- package/src/utils/redis.ts +0 -17
- package/tsconfig.json +0 -45
package/src/data/posts.ts
DELETED
|
@@ -1,561 +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, ArangoDBLimit, 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 getPostOptional = (fields: string[]) =>
|
|
21
|
-
fields.reduce((selects: any, field: string) => {
|
|
22
|
-
switch(field) {
|
|
23
|
-
case 'reactions': {
|
|
24
|
-
selects.queries.push(`LET reactions = (
|
|
25
|
-
FOR post, r IN INBOUND p._id reactions
|
|
26
|
-
COLLECT reactionName = r.value INTO reactionItems
|
|
27
|
-
RETURN {name: reactionName, count: LENGTH(reactionItems[*].r.value)}
|
|
28
|
-
)`);
|
|
29
|
-
selects.objects.push('reactions:reactions');
|
|
30
|
-
return selects;
|
|
31
|
-
}
|
|
32
|
-
case 'tags': {
|
|
33
|
-
selects.queries.push(`LET tags = (
|
|
34
|
-
FOR t, pl IN INBOUND p._id isTagged
|
|
35
|
-
RETURN t
|
|
36
|
-
)`);
|
|
37
|
-
selects.objects.push('tags:tags');
|
|
38
|
-
return selects;
|
|
39
|
-
}
|
|
40
|
-
case 'user': {
|
|
41
|
-
selects.queries.push(`LET user = FIRST(
|
|
42
|
-
FOR u IN users
|
|
43
|
-
FILTER p.userId == u._key
|
|
44
|
-
LIMIT 1
|
|
45
|
-
RETURN u
|
|
46
|
-
)`);
|
|
47
|
-
selects.objects.push('user:user');
|
|
48
|
-
return selects;
|
|
49
|
-
}
|
|
50
|
-
default: {
|
|
51
|
-
return selects;
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
}, {objects: [], queries: []});
|
|
55
|
-
|
|
56
|
-
export const getPostList = (context: ApiContext, from: number, to: number): Promise<PostType[]> => {
|
|
57
|
-
// const action: string = 'getListByApp';
|
|
58
|
-
const {database, fields} = context;
|
|
59
|
-
const limit: ArangoDBLimit = getLimit(from, to);
|
|
60
|
-
const {objects: selectObjects, queries: selectQueries} = getPostOptional(fields);
|
|
61
|
-
const aqlQry: string = `FOR p IN posts
|
|
62
|
-
FILTER p.privacy == "public" && p.parent == null
|
|
63
|
-
${selectQueries.join('\n')}
|
|
64
|
-
${limit.aql}
|
|
65
|
-
SORT p.added
|
|
66
|
-
RETURN DISTINCT MERGE(p, {${selectObjects.join(', ')}})`;
|
|
67
|
-
|
|
68
|
-
return useDb(database).query(aqlQry)
|
|
69
|
-
.then((cursor: ArrayCursor) => cursor.all())
|
|
70
|
-
.catch((error: Error) => {
|
|
71
|
-
throw error;
|
|
72
|
-
});
|
|
73
|
-
};
|
|
74
|
-
|
|
75
|
-
export const getPostListByGroup = (context: ApiContext, groupId: string, from: number, to: number): Promise<PostType[]> => {
|
|
76
|
-
// const action: string = 'getListByGroup';
|
|
77
|
-
const {database, fields, userId: sessionId} = context;
|
|
78
|
-
const {objects: selectObjects, queries: selectQueries} = getPostOptional(fields);
|
|
79
|
-
|
|
80
|
-
// Group id
|
|
81
|
-
const formatGroupId: string = parseId(groupId);
|
|
82
|
-
const db = useDb(database);
|
|
83
|
-
const aqlQry: string = `FOR u, g IN INBOUND ${formatGroupId} hasGroup
|
|
84
|
-
FILTER u._key == ${sessionId}
|
|
85
|
-
RETURN g`;
|
|
86
|
-
|
|
87
|
-
return db.query(aqlQry)
|
|
88
|
-
.then((cursor: ArrayCursor) => cursor.all())
|
|
89
|
-
.then((groups: GroupType[] = []) => {
|
|
90
|
-
if(groups.length) {
|
|
91
|
-
const limit: ArangoDBLimit = getLimit(from, to);
|
|
92
|
-
const postAqlQry: string = `FOR p IN posts
|
|
93
|
-
FILTER p.groupId == "${formatGroupId}" && p.parent == null
|
|
94
|
-
${selectQueries.join('\n')}
|
|
95
|
-
${limit.aql}
|
|
96
|
-
SORT p.added
|
|
97
|
-
RETURN DISTINCT MERGE(p, {${selectObjects.join(', ')}})`;
|
|
98
|
-
|
|
99
|
-
return db.query(postAqlQry)
|
|
100
|
-
.then((cursor: ArrayCursor) => cursor.all())
|
|
101
|
-
.catch((error: Error) => {
|
|
102
|
-
throw error;
|
|
103
|
-
});
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
return [];
|
|
107
|
-
})
|
|
108
|
-
.catch((error: Error) => {
|
|
109
|
-
throw error;
|
|
110
|
-
});
|
|
111
|
-
};
|
|
112
|
-
|
|
113
|
-
export const getPostListByLatest = (context: ApiContext, from: number, to: number): Promise<PostType[]> => {
|
|
114
|
-
// const action: string = 'getListByLatest';
|
|
115
|
-
const {database, fields} = context;
|
|
116
|
-
const limit: ArangoDBLimit = getLimit(from, to);
|
|
117
|
-
const {objects: selectObjects, queries: selectQueries} = getPostOptional(fields);
|
|
118
|
-
const aqlQry: string = `FOR p IN posts
|
|
119
|
-
FILTER p.privacy == "public" && p.parent == null
|
|
120
|
-
${selectQueries.join('\n')}
|
|
121
|
-
${limit.aql}
|
|
122
|
-
SORT p.added
|
|
123
|
-
RETURN DISTINCT MERGE(p, {${selectObjects.join(', ')}})`;
|
|
124
|
-
|
|
125
|
-
return useDb(database).query(aqlQry)
|
|
126
|
-
.then((cursor: ArrayCursor) => cursor.all())
|
|
127
|
-
.catch((error: Error) => {
|
|
128
|
-
throw error;
|
|
129
|
-
});
|
|
130
|
-
};
|
|
131
|
-
|
|
132
|
-
export const getPostListByTags = (
|
|
133
|
-
context: ApiContext,
|
|
134
|
-
tagNames: string[],
|
|
135
|
-
options: PostOptions
|
|
136
|
-
): Promise<PostType[]> => {
|
|
137
|
-
// const action: string = 'getListByTags';
|
|
138
|
-
const {database, fields} = context;
|
|
139
|
-
const {latitude, longitude, from = 0, to = 30} = options;
|
|
140
|
-
const {objects: selectObjects, queries: selectQueries} = getPostOptional(fields);
|
|
141
|
-
const sortBy: string[] = [];
|
|
142
|
-
|
|
143
|
-
if(latitude !== undefined && longitude !== undefined) {
|
|
144
|
-
const formatLatitude: number = parseNum(latitude);
|
|
145
|
-
const formatLongitude: number = parseNum(longitude);
|
|
146
|
-
selectQueries.push(`LET distance = DISTANCE(
|
|
147
|
-
${formatLatitude},
|
|
148
|
-
${formatLongitude},
|
|
149
|
-
NOT_NULL(p.latitude, 0),
|
|
150
|
-
NOT_NULL(p.longitude, 0))
|
|
151
|
-
`);
|
|
152
|
-
selectObjects.push('distance:distance');
|
|
153
|
-
sortBy.push('distance');
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
sortBy.push('p.added');
|
|
157
|
-
|
|
158
|
-
return Promise.all(
|
|
159
|
-
tagNames.map((tagName: string) => {
|
|
160
|
-
const limit: ArangoDBLimit = getLimit(from, to);
|
|
161
|
-
const aqlQry: string = `FOR targetTag IN tags
|
|
162
|
-
FILTER targetTag.name == "${tagName}"
|
|
163
|
-
FOR p, e IN OUTBOUND targetTag._id isTagged
|
|
164
|
-
${selectQueries.join('\n')}
|
|
165
|
-
FILTER p.privacy == "public" && e.type == 'posts'
|
|
166
|
-
${limit.aql}
|
|
167
|
-
SORT ${sortBy.join(', ')}
|
|
168
|
-
RETURN DISTINCT MERGE(p, {${selectObjects.join(', ')}})`;
|
|
169
|
-
|
|
170
|
-
console.log(aqlQry);
|
|
171
|
-
return useDb(database).query(aqlQry)
|
|
172
|
-
.then((cursor: ArrayCursor) => cursor.all())
|
|
173
|
-
.catch(() => []);
|
|
174
|
-
}))
|
|
175
|
-
.then((results) => uniqBy(flatten(results), '_key'))
|
|
176
|
-
.catch((error: Error) => {
|
|
177
|
-
throw error;
|
|
178
|
-
});
|
|
179
|
-
};
|
|
180
|
-
|
|
181
|
-
export const getPostListByUser = (context: ApiContext, userId: string, options): Promise<PostType[]> => {
|
|
182
|
-
// const action: string = 'getListByUser';
|
|
183
|
-
const {database, fields} = context;
|
|
184
|
-
const {from = 0, to = 30} = options;
|
|
185
|
-
const formatUserId: string = parseId(userId);
|
|
186
|
-
const limit: ArangoDBLimit = getLimit(from, to);
|
|
187
|
-
const {objects: selectObjects, queries: selectQueries} = getPostOptional(fields);
|
|
188
|
-
const aqlQry: string = `FOR p IN posts
|
|
189
|
-
FILTER p.userId == "${formatUserId}" && p.privacy == "public" && p.parent == null
|
|
190
|
-
${selectQueries.join('\n')}
|
|
191
|
-
${limit.aql}
|
|
192
|
-
SORT p.added
|
|
193
|
-
RETURN DISTINCT MERGE(p, {${selectObjects.join(', ')}})`;
|
|
194
|
-
|
|
195
|
-
return useDb(database).query(aqlQry)
|
|
196
|
-
.then((cursor: ArrayCursor) => cursor.all())
|
|
197
|
-
.catch((error: Error) => {
|
|
198
|
-
throw error;
|
|
199
|
-
});
|
|
200
|
-
};
|
|
201
|
-
|
|
202
|
-
export const getPostListByArea = (
|
|
203
|
-
context: ApiContext,
|
|
204
|
-
latitude: number,
|
|
205
|
-
longitude: number,
|
|
206
|
-
from: number,
|
|
207
|
-
to: number
|
|
208
|
-
): Promise<PostType[]> => {
|
|
209
|
-
// const action: string = 'getListByUser';
|
|
210
|
-
const {database, fields} = context;
|
|
211
|
-
const formatLatitude: number = parseNum(latitude);
|
|
212
|
-
const formatLongitude: number = parseNum(longitude);
|
|
213
|
-
const limit: ArangoDBLimit = getLimit(from, to);
|
|
214
|
-
const {objects: selectObjects, queries: selectQueries} = getPostOptional(fields);
|
|
215
|
-
selectQueries.push(`LET distance = DISTANCE(
|
|
216
|
-
${formatLatitude},
|
|
217
|
-
${formatLongitude},
|
|
218
|
-
NOT_NULL(p.latitude, 0),
|
|
219
|
-
NOT_NULL(p.longitude, 0))
|
|
220
|
-
`);
|
|
221
|
-
selectObjects.push('distance:distance');
|
|
222
|
-
|
|
223
|
-
const aqlQry: string = `FOR p IN posts
|
|
224
|
-
${selectQueries.join('\n')}
|
|
225
|
-
FILTER p.privacy == "public" && p.parentId == null
|
|
226
|
-
${limit.aql}
|
|
227
|
-
SORT distance, p.added
|
|
228
|
-
RETURN DISTINCT MERGE(p, {${selectObjects.join(', ')}})`;
|
|
229
|
-
|
|
230
|
-
return useDb(database).query(aqlQry)
|
|
231
|
-
.then((cursor: ArrayCursor) => cursor.all())
|
|
232
|
-
.catch((error: Error) => {
|
|
233
|
-
throw error;
|
|
234
|
-
});
|
|
235
|
-
};
|
|
236
|
-
|
|
237
|
-
export const getPost = (context: ApiContext, itemId: string): Promise<PostType> => {
|
|
238
|
-
// const action: string = 'getItem';
|
|
239
|
-
const {database, fields, userId: sessionId} = context;
|
|
240
|
-
const formatItemId: string = parseId(itemId);
|
|
241
|
-
const db = useDb(database);
|
|
242
|
-
const {objects: selectObjects, queries: selectQueries} = getPostOptional(fields);
|
|
243
|
-
const aqlQry: AqlQuery = aql`FOR p IN posts
|
|
244
|
-
FILTER p._key == ${formatItemId}
|
|
245
|
-
LIMIT 1
|
|
246
|
-
RETURN p`;
|
|
247
|
-
|
|
248
|
-
return db.query(aqlQry)
|
|
249
|
-
.then((cursor: ArrayCursor) => cursor.next())
|
|
250
|
-
.then((post: PostType = {}) => {
|
|
251
|
-
const {
|
|
252
|
-
_key,
|
|
253
|
-
groupId,
|
|
254
|
-
privacy = 'default'
|
|
255
|
-
}: PostType = post;
|
|
256
|
-
|
|
257
|
-
// Query based on privacy level
|
|
258
|
-
let privacyAqlQry: string;
|
|
259
|
-
|
|
260
|
-
if(groupId && privacy === 'group') {
|
|
261
|
-
privacyAqlQry = `FOR p IN posts
|
|
262
|
-
FILTER p._key == "${_key}"
|
|
263
|
-
${selectQueries.join('\n')}
|
|
264
|
-
FOR group IN groups
|
|
265
|
-
FILTER group._key == p.groupId
|
|
266
|
-
FOR u, e IN OUTBOUND group._id isGrouped
|
|
267
|
-
FILTER u._key == ${sessionId}
|
|
268
|
-
LIMIT 1
|
|
269
|
-
RETURN MERGE(p, {${selectObjects.join(', ')}})`;
|
|
270
|
-
} else if(privacy === 'public') {
|
|
271
|
-
privacyAqlQry = `FOR p IN posts
|
|
272
|
-
FILTER p._key == "${_key}"
|
|
273
|
-
${selectQueries.join('\n')}
|
|
274
|
-
LIMIT 1
|
|
275
|
-
RETURN MERGE(p, {${selectObjects.join(', ')}})`;
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
if(privacyAqlQry) {
|
|
279
|
-
return db.query(privacyAqlQry)
|
|
280
|
-
.then((cursor: ArrayCursor) => cursor.next())
|
|
281
|
-
.then((filteredPost: PostType = {}) => filteredPost)
|
|
282
|
-
.catch((error: Error) => {
|
|
283
|
-
throw error;
|
|
284
|
-
});
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
return {};
|
|
288
|
-
})
|
|
289
|
-
.catch((error: Error) => {
|
|
290
|
-
throw error;
|
|
291
|
-
});
|
|
292
|
-
};
|
|
293
|
-
|
|
294
|
-
export const getPostComments = (context: ApiContext, itemId: string, from: number, to: number): Promise<PostType[]> => {
|
|
295
|
-
// const action: string = 'getComments';
|
|
296
|
-
const {database, userId: sessionId} = context;
|
|
297
|
-
const formatItemId: string = parseId(itemId);
|
|
298
|
-
|
|
299
|
-
// Get the parent post to get restrictions
|
|
300
|
-
const db = useDb(database);
|
|
301
|
-
const aqlQry: AqlQuery = aql`FOR p IN posts
|
|
302
|
-
FILTER p._key == ${formatItemId}
|
|
303
|
-
LIMIT 1
|
|
304
|
-
RETURN p`;
|
|
305
|
-
|
|
306
|
-
return db.query(aqlQry)
|
|
307
|
-
.then((cursor: ArrayCursor) => cursor.next())
|
|
308
|
-
.then((post: PostType = {}) => {
|
|
309
|
-
const {
|
|
310
|
-
_key,
|
|
311
|
-
groupId,
|
|
312
|
-
privacy = 'public'
|
|
313
|
-
}: PostType = post;
|
|
314
|
-
|
|
315
|
-
// Query based on privacy level
|
|
316
|
-
let privacyAqlQry: string;
|
|
317
|
-
const limit = getLimit(from, to);
|
|
318
|
-
|
|
319
|
-
if(groupId && privacy === 'group') {
|
|
320
|
-
privacyAqlQry = `FOR p IN posts
|
|
321
|
-
FOR user IN users
|
|
322
|
-
FILTER p.parent == "${_key}" && user._key == p.userId
|
|
323
|
-
LET reactions = (
|
|
324
|
-
FOR post, r IN INBOUND p._id reactions
|
|
325
|
-
COLLECT reactionName = r.value INTO reactionItems
|
|
326
|
-
RETURN {name: reactionName, count: LENGTH(reactionItems[*].r.value)}
|
|
327
|
-
)
|
|
328
|
-
FOR group IN groups
|
|
329
|
-
FILTER group._key == p.groupId
|
|
330
|
-
FOR u, e IN OUTBOUND group._id isGrouped
|
|
331
|
-
FILTER u._key == "${sessionId}"
|
|
332
|
-
SORT p.added
|
|
333
|
-
${limit.aql}
|
|
334
|
-
RETURN MERGE(p, {user: user, reactions: reactions})`;
|
|
335
|
-
} else if(privacy === 'public') {
|
|
336
|
-
privacyAqlQry = `FOR p IN posts
|
|
337
|
-
FOR user IN users
|
|
338
|
-
FILTER p.parent == "${_key}" && user._key == p.userId
|
|
339
|
-
LET reactions = (
|
|
340
|
-
FOR post, r IN INBOUND p._id reactions
|
|
341
|
-
COLLECT reactionName = r.value INTO reactionItems
|
|
342
|
-
RETURN {name: reactionName, count: LENGTH(reactionItems[*].r.value)}
|
|
343
|
-
)
|
|
344
|
-
SORT p.added
|
|
345
|
-
${limit.aql}
|
|
346
|
-
RETURN MERGE(p, {user: user, reactions: reactions})`;
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
if(privacyAqlQry) {
|
|
350
|
-
return db.query(privacyAqlQry)
|
|
351
|
-
.then((cursor: ArrayCursor) => cursor.all())
|
|
352
|
-
.catch((error: Error) => {
|
|
353
|
-
throw error;
|
|
354
|
-
});
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
return [];
|
|
358
|
-
})
|
|
359
|
-
.catch((error: Error) => {
|
|
360
|
-
throw error;
|
|
361
|
-
});
|
|
362
|
-
};
|
|
363
|
-
|
|
364
|
-
export const addPost = (context: ApiContext, item: PostType): Promise<PostType> => {
|
|
365
|
-
// const action: string = 'add';
|
|
366
|
-
const {database, userId: sessionId} = context;
|
|
367
|
-
|
|
368
|
-
const {
|
|
369
|
-
content = '',
|
|
370
|
-
groupId = '',
|
|
371
|
-
location,
|
|
372
|
-
latitude,
|
|
373
|
-
longitude,
|
|
374
|
-
name = '',
|
|
375
|
-
parentId = null,
|
|
376
|
-
privacy = 'public'
|
|
377
|
-
}: PostType = item;
|
|
378
|
-
|
|
379
|
-
const now: number = Date.now();
|
|
380
|
-
|
|
381
|
-
const insert: PostType = {
|
|
382
|
-
_key: createHash(`post-${sessionId}`),
|
|
383
|
-
added: now,
|
|
384
|
-
content: parseString(content, MAX_CONTENT_LENGTH),
|
|
385
|
-
groupId: groupId ? parseId(groupId) : undefined,
|
|
386
|
-
latitude: latitude !== undefined ? parseNum(latitude) : undefined,
|
|
387
|
-
location: location ? parseString(location, 160) : undefined,
|
|
388
|
-
longitude: longitude !== undefined ? parseNum(longitude) : undefined,
|
|
389
|
-
modified: now,
|
|
390
|
-
name: parseString(name, 160),
|
|
391
|
-
parentId: parentId ? parseId(parentId) : undefined,
|
|
392
|
-
privacy: privacy ? parseVarChar(privacy, 16) : undefined,
|
|
393
|
-
userId: sessionId
|
|
394
|
-
};
|
|
395
|
-
|
|
396
|
-
const db: Database = useDb(database);
|
|
397
|
-
const aqlQry: AqlQuery = aql`INSERT ${insert} IN posts RETURN NEW`;
|
|
398
|
-
|
|
399
|
-
return db.query(aqlQry)
|
|
400
|
-
.then((cursor: ArrayCursor) => cursor.next())
|
|
401
|
-
.then((post: PostType = {}) => {
|
|
402
|
-
const {_key: postKey} = post;
|
|
403
|
-
|
|
404
|
-
// Update linked tags within posts
|
|
405
|
-
return extractTags(db, 'posts', postKey, insert.content)
|
|
406
|
-
.then((tagList: TagType[]) => {
|
|
407
|
-
post.tags = tagList;
|
|
408
|
-
return post;
|
|
409
|
-
});
|
|
410
|
-
})
|
|
411
|
-
.catch((error: Error) => {
|
|
412
|
-
throw error;
|
|
413
|
-
});
|
|
414
|
-
};
|
|
415
|
-
|
|
416
|
-
export const updatePost = (context: ApiContext, item: PostType): Promise<PostType> => {
|
|
417
|
-
// const action: string = 'update';
|
|
418
|
-
const {database, userId: sessionId} = context;
|
|
419
|
-
const now: number = Date.now();
|
|
420
|
-
const {
|
|
421
|
-
content,
|
|
422
|
-
groupId,
|
|
423
|
-
name,
|
|
424
|
-
parentId,
|
|
425
|
-
postId,
|
|
426
|
-
privacy
|
|
427
|
-
}: PostType = item;
|
|
428
|
-
|
|
429
|
-
const update: PostType = {
|
|
430
|
-
content: content ? parseString(content, MAX_CONTENT_LENGTH) : undefined,
|
|
431
|
-
modified: now,
|
|
432
|
-
name: name ? parseString(name, 160) : undefined,
|
|
433
|
-
parentId: parentId ? parseString(parentId, 160) : undefined,
|
|
434
|
-
privacy: privacy ? parseVarChar(privacy, 16) : undefined,
|
|
435
|
-
};
|
|
436
|
-
|
|
437
|
-
let formatId: string = parseId(postId);
|
|
438
|
-
formatId = formatId === '' ? createHash(`post-${sessionId}`) : formatId;
|
|
439
|
-
const formatGroupId: string = parseId(groupId);
|
|
440
|
-
const insert: any = {
|
|
441
|
-
...update,
|
|
442
|
-
_key: formatId,
|
|
443
|
-
added: now,
|
|
444
|
-
groupId: formatGroupId,
|
|
445
|
-
privacy,
|
|
446
|
-
userId: sessionId
|
|
447
|
-
};
|
|
448
|
-
const db: Database = useDb(database);
|
|
449
|
-
const aqlQry: AqlQuery = aql`UPSERT {_key: ${formatId}, userId: ${sessionId}}
|
|
450
|
-
INSERT ${insert}
|
|
451
|
-
UPDATE ${update}
|
|
452
|
-
IN posts RETURN NEW`;
|
|
453
|
-
|
|
454
|
-
return db.query(aqlQry)
|
|
455
|
-
.then((cursor: ArrayCursor) => cursor.next())
|
|
456
|
-
.then((updatedPost: PostType = {}) => {
|
|
457
|
-
const {_key: updatedPostKey} = updatedPost;
|
|
458
|
-
|
|
459
|
-
// Update linked tags
|
|
460
|
-
return extractTags(db, 'posts', updatedPostKey, update.content || '')
|
|
461
|
-
.then((tagList = []) => {
|
|
462
|
-
updatedPost.tags = tagList;
|
|
463
|
-
|
|
464
|
-
// Update linked files
|
|
465
|
-
const files: FileType[] = updatedPost.files || [];
|
|
466
|
-
|
|
467
|
-
if(files.length) {
|
|
468
|
-
return updateFiles(db, formatId, files)
|
|
469
|
-
.then((fileList = []) => {
|
|
470
|
-
updatedPost.files = fileList;
|
|
471
|
-
return updatedPost;
|
|
472
|
-
});
|
|
473
|
-
}
|
|
474
|
-
|
|
475
|
-
updatedPost.files = [];
|
|
476
|
-
return updatedPost;
|
|
477
|
-
});
|
|
478
|
-
})
|
|
479
|
-
.catch((error: Error) => {
|
|
480
|
-
throw error;
|
|
481
|
-
});
|
|
482
|
-
};
|
|
483
|
-
|
|
484
|
-
export const deletePost = (context: ApiContext, itemId: string): Promise<PostType> => {
|
|
485
|
-
// const action: string = 'delete';
|
|
486
|
-
const {database, userId: sessionId} = context;
|
|
487
|
-
const formatItemId: string = parseId(itemId);
|
|
488
|
-
const db: Database = useDb(database);
|
|
489
|
-
const aqlQry = aql`FOR p IN posts
|
|
490
|
-
FILTER p._key == ${formatItemId} && p.userId == ${sessionId}
|
|
491
|
-
LIMIT 1
|
|
492
|
-
REMOVE p IN posts
|
|
493
|
-
RETURN OLD`;
|
|
494
|
-
|
|
495
|
-
return db.query(aqlQry)
|
|
496
|
-
.then((cursor: ArrayCursor) => cursor.next())
|
|
497
|
-
.then((post: PostType = {}) => {
|
|
498
|
-
if(post) {
|
|
499
|
-
// Remove tag links
|
|
500
|
-
const edgeAqlQry: AqlQuery = aql`FOR t IN isTagged
|
|
501
|
-
FILTER t._to == ${formatItemId}
|
|
502
|
-
REMOVE t IN isTagged`;
|
|
503
|
-
|
|
504
|
-
return db.query(edgeAqlQry)
|
|
505
|
-
.then(() => {
|
|
506
|
-
// Remove attached files
|
|
507
|
-
const fileAqlQry: AqlQuery = aql`FOR f IN hasFile
|
|
508
|
-
FILTER f._to == ${formatItemId}
|
|
509
|
-
REMOVE f IN hasFile`;
|
|
510
|
-
|
|
511
|
-
return db.query(fileAqlQry)
|
|
512
|
-
.then(() => post)
|
|
513
|
-
.catch((error: Error) => {
|
|
514
|
-
throw error;
|
|
515
|
-
});
|
|
516
|
-
})
|
|
517
|
-
.catch((error: Error) => {
|
|
518
|
-
throw error;
|
|
519
|
-
});
|
|
520
|
-
}
|
|
521
|
-
return {};
|
|
522
|
-
})
|
|
523
|
-
.catch((error: Error) => {
|
|
524
|
-
throw error;
|
|
525
|
-
});
|
|
526
|
-
};
|
|
527
|
-
|
|
528
|
-
export const cleanPosts = (database: string): Promise<number> => {
|
|
529
|
-
// Remove all messages that are over 60 days and not saved
|
|
530
|
-
const aqlQry: AqlQuery = aql`FOR p IN posts
|
|
531
|
-
FILTER p.added < DATE_TIMESTAMP(DATE_SUBTRACT(DATE_NOW(), 60, 'day')) && p.type == 1
|
|
532
|
-
REMOVE p IN posts
|
|
533
|
-
RETURN OLD`;
|
|
534
|
-
|
|
535
|
-
return useDb(database).query(aqlQry)
|
|
536
|
-
.then((cursor: ArrayCursor) => cursor.all())
|
|
537
|
-
.then((results: PostType[] = []) => results.length)
|
|
538
|
-
.catch((error: Error) => {
|
|
539
|
-
throw error;
|
|
540
|
-
});
|
|
541
|
-
}
|
|
542
|
-
|
|
543
|
-
export const createPostEdge = (db: Database, file: FileType, postId: string): Promise<FileType> => {
|
|
544
|
-
const edgeCollection = db.edgeCollection('isPosted');
|
|
545
|
-
const fileId: string = parseId(file.id);
|
|
546
|
-
const edgeId: string = createHash(`file-${postId}-${fileId}`);
|
|
547
|
-
const formatPostId: string = parseId(postId);
|
|
548
|
-
const fileType: string = parseChar(file.fileType, 16);
|
|
549
|
-
|
|
550
|
-
const edge: any = {
|
|
551
|
-
_key: edgeId,
|
|
552
|
-
added: Date.now(),
|
|
553
|
-
type: fileType
|
|
554
|
-
};
|
|
555
|
-
|
|
556
|
-
return edgeCollection.save(edge, `posts/${formatPostId}`, `files/${fileId}`)
|
|
557
|
-
.then(() => file)
|
|
558
|
-
.catch((error: Error) => {
|
|
559
|
-
throw error;
|
|
560
|
-
});
|
|
561
|
-
};
|