1 |
|
2 |
|
3 |
|
4 |
|
5 | import AWS from 'aws-sdk';
|
6 | import gql from 'graphql-tag';
|
7 | import Cookies from 'universal-cookie';
|
8 |
|
9 | import { mutation, params, types, query } from 'typed-graphqlify'
|
10 | import {IC_USER_ID} from "../authentication/auth-middleware";
|
11 |
|
12 |
|
13 |
|
14 |
|
15 | const promisify = foo => new Promise((resolve, reject) => {
|
16 | foo((error, result) => {
|
17 | if(error) {
|
18 | reject(error)
|
19 | } else {
|
20 | resolve(result)
|
21 | }
|
22 | })
|
23 | });
|
24 |
|
25 | const applyOfflineConfig = (offline: boolean) => {
|
26 | return offline ? {
|
27 | region: 'localhost',
|
28 | endpoint: 'http://localhost:8000'
|
29 | } : {}
|
30 | };
|
31 |
|
32 | export const setEntry = (tableName, pkEntity, pkId, skEntity, skId, jsonData, isOffline) => {
|
33 |
|
34 |
|
35 |
|
36 | return promisify(callback =>
|
37 | new AWS.DynamoDB.DocumentClient(applyOfflineConfig(isOffline)).update({
|
38 | TableName: tableName,
|
39 | |
40 |
|
41 |
|
42 | Key: {
|
43 | pk: `${pkEntity}|${pkId}`,
|
44 | sk: `${skEntity}|${skId}`
|
45 | },
|
46 | UpdateExpression: `SET jsonData = :jsonData`,
|
47 | ExpressionAttributeValues: {
|
48 | ':jsonData': `${JSON.stringify(jsonData)}`,
|
49 | }
|
50 | }, callback))
|
51 | .then(() => {
|
52 |
|
53 |
|
54 | var result = {};
|
55 | result[pkEntity] = pkId;
|
56 | result[skEntity] = skId;
|
57 | result["data"] = `${JSON.stringify(jsonData).replace(/"/g, "\\\"")}`;
|
58 |
|
59 | return result;
|
60 | }).catch(error => { console.log(error) });
|
61 | };
|
62 |
|
63 |
|
64 |
|
65 |
|
66 |
|
67 |
|
68 |
|
69 |
|
70 |
|
71 |
|
72 |
|
73 | export const ddbListEntries = (tableName, key, entity, value, rangeEntity, isOffline) => {
|
74 |
|
75 |
|
76 |
|
77 | const q = {
|
78 |
|
79 | TableName: tableName,
|
80 | IndexName: key === "sk" ? "reverse" : undefined,
|
81 | |
82 |
|
83 |
|
84 | KeyConditionExpression: `${
|
85 | key
|
86 | } = :value and begins_with(${
|
87 | key === "pk" ? "sk" : "pk"
|
88 | }, :entity)`,
|
89 | ExpressionAttributeValues: {
|
90 | ":value": `${entity}|${value}`,
|
91 | ":entity": rangeEntity ? rangeEntity : "undefined"
|
92 | }
|
93 | };
|
94 |
|
95 |
|
96 |
|
97 | return promisify(callback =>
|
98 | new AWS.DynamoDB.DocumentClient(applyOfflineConfig(isOffline)).query(q, callback))
|
99 | .then(result => {
|
100 |
|
101 | return result["Items"];
|
102 |
|
103 | |
104 |
|
105 |
|
106 |
|
107 |
|
108 |
|
109 |
|
110 |
|
111 | }).catch(error => { console.log(error) });
|
112 | };
|
113 |
|
114 | export const ddbGetEntry = (tableName, pkEntity, pkValue, skEntity, skValue, isOffline) => {
|
115 |
|
116 |
|
117 |
|
118 | const q = {
|
119 | TableName: tableName,
|
120 | Key: {
|
121 | pk: `${pkEntity}|${pkValue}`,
|
122 | sk: `${skEntity}|${skValue}`
|
123 | }
|
124 | };
|
125 |
|
126 |
|
127 |
|
128 | return promisify(callback =>
|
129 | new AWS.DynamoDB.DocumentClient(applyOfflineConfig(isOffline)).get(q, callback))
|
130 | .then(result => {
|
131 |
|
132 |
|
133 | return result["Item"] ? result["Item"] : result;
|
134 |
|
135 | }).catch(error => { console.log(error) });
|
136 | };
|
137 |
|
138 | export const ddbScan = (tableName, key, entity, start_value, end_value, rangeEntity, isOffline) => {
|
139 |
|
140 |
|
141 |
|
142 | const q = {
|
143 |
|
144 | TableName: tableName,
|
145 | FilterExpression: `${
|
146 | key
|
147 | } between :sv and :ev and begins_with(${
|
148 | key === "pk" ? "sk" : "pk"
|
149 | }, :entity)`,
|
150 | ExpressionAttributeValues: {
|
151 | ":sv": `${entity}|${start_value}`,
|
152 | ":ev": `${entity}|${end_value}`,
|
153 | ":entity": rangeEntity ? rangeEntity : "undefined"
|
154 | }
|
155 | };
|
156 |
|
157 | const allQ = {
|
158 |
|
159 | TableName: tableName,
|
160 | FilterExpression: `begins_with(${key}, :entity) and begins_with(${
|
161 | key === "pk" ? "sk" : "pk"}, :rangeentity)`,
|
162 | ExpressionAttributeValues: {
|
163 | ":entity": entity,
|
164 | ":rangeentity": rangeEntity ? rangeEntity : "undefined"
|
165 | }
|
166 | };
|
167 |
|
168 |
|
169 |
|
170 |
|
171 |
|
172 | return promisify(callback =>
|
173 | new AWS.DynamoDB.DocumentClient(applyOfflineConfig(isOffline)).scan(start_value && end_value ? q : allQ, callback))
|
174 | .then(result => {
|
175 |
|
176 | return result["Items"];
|
177 |
|
178 | |
179 |
|
180 |
|
181 |
|
182 |
|
183 |
|
184 |
|
185 |
|
186 |
|
187 |
|
188 |
|
189 |
|
190 |
|
191 |
|
192 |
|
193 |
|
194 |
|
195 |
|
196 |
|
197 |
|
198 |
|
199 |
|
200 |
|
201 |
|
202 |
|
203 |
|
204 |
|
205 |
|
206 |
|
207 |
|
208 | }).catch(error => { console.log(error) });
|
209 | };
|
210 |
|
211 |
|
212 |
|
213 | export const deleteEntry = (tableName, pkEntity, pkValue, skEntity, skValue, isOffline) => {
|
214 |
|
215 |
|
216 |
|
217 |
|
218 |
|
219 | return promisify(callback =>
|
220 | new AWS.DynamoDB.DocumentClient(applyOfflineConfig(isOffline)).delete({
|
221 |
|
222 | TableName: tableName,
|
223 | Key: {
|
224 | pk: `${pkEntity}|${pkValue}`,
|
225 | sk: `${skEntity}|${skValue}`
|
226 | }
|
227 | }, callback))
|
228 | .then(result => {
|
229 |
|
230 |
|
231 | return result["Item"] ? result["Item"] : result;
|
232 |
|
233 | }).catch(error => { console.log(error) });
|
234 | };
|
235 |
|
236 |
|
237 |
|
238 |
|
239 |
|
240 |
|
241 |
|
242 | export const setEntryMutation = ( entryId, data, fields, context={}) => {
|
243 |
|
244 |
|
245 |
|
246 | const mutationObj = {};
|
247 | mutationObj[`set_${entryId}`] = params(
|
248 | Object.keys(data).reduce((result, key) => {
|
249 | result[key] = `"${data[key]}"`;
|
250 | return result;
|
251 | },{}),
|
252 | Object.keys(fields).reduce((result, key) => {
|
253 | result[key] = types.string;
|
254 | return result;
|
255 | },{})
|
256 | );
|
257 |
|
258 | return {
|
259 | mutation: gql`${mutation(mutationObj)}`,
|
260 | context: context
|
261 | }
|
262 |
|
263 | };
|
264 |
|
265 |
|
266 | export const deleteEntryMutation = ( entryId, data, fields, context={}) => {
|
267 |
|
268 |
|
269 | const mutationObj = {};
|
270 | mutationObj[`delete_${entryId}`] = params(
|
271 | Object.keys(data).reduce((result, key) => {
|
272 | result[key] = `"${data[key]}"`;
|
273 | return result;
|
274 | },{}),
|
275 | Object.keys(fields).reduce((result, key) => {
|
276 | result[key] = types.string;
|
277 | return result;
|
278 | },{})
|
279 | );
|
280 |
|
281 | return {
|
282 | mutation: gql`${mutation(mutationObj)}`,
|
283 | context: context
|
284 | }
|
285 |
|
286 | };
|
287 |
|
288 |
|
289 |
|
290 |
|
291 |
|
292 | export const getEntryListQuery = ( entryId, data, fields, context={}) => {
|
293 |
|
294 |
|
295 | if (data == undefined) {
|
296 | console.error("getEntryListQuery requires a data argument");
|
297 | return undefined;
|
298 | }
|
299 |
|
300 |
|
301 |
|
302 | if (Object.keys(data).length !== 1) {
|
303 | console.error("getEntryListQuery requires exact 1 field provided in the data argument");
|
304 | return undefined;
|
305 | }
|
306 |
|
307 | const queryKey = Object.keys(data)[0];
|
308 |
|
309 | const queryObj = {};
|
310 | queryObj[`list_${entryId}_${queryKey}`] = params(
|
311 | Object.keys(data).filter(key => key === queryKey).reduce((result, key) => {
|
312 | result[key] = `"${data[key]}"`;
|
313 | return result;
|
314 | },{}),
|
315 | Object.keys(fields).reduce((result, key) => {
|
316 | result[key] = types.string;
|
317 | return result;
|
318 | },{})
|
319 | );
|
320 |
|
321 |
|
322 |
|
323 | return {
|
324 | query:gql`${query(queryObj)}`,
|
325 | context: context
|
326 | }
|
327 |
|
328 | };
|
329 |
|
330 | export const getEntryQuery = ( entryId, data, fields, context={}) => {
|
331 |
|
332 |
|
333 | if (data == undefined) {
|
334 | console.error("getEntryQuery requires a data argument");
|
335 | return undefined;
|
336 | }
|
337 |
|
338 | if (Object.keys(data).length !== 2) {
|
339 | console.error("getEntryQuery requires exact 2 fields provided in the data argument");
|
340 | return undefined;
|
341 | }
|
342 |
|
343 | const queryObj = {};
|
344 | queryObj[`get_${entryId}`] = params(
|
345 | Object.keys(data).reduce((result, key) => {
|
346 | result[key] = `"${data[key]}"`;
|
347 | return result;
|
348 | },{}),
|
349 | Object.keys(fields).reduce((result, key) => {
|
350 | result[key] = types.string;
|
351 | return result;
|
352 | },{})
|
353 | );
|
354 |
|
355 |
|
356 |
|
357 | return {
|
358 | query:gql`${query(queryObj)}`,
|
359 | context: context
|
360 | }
|
361 |
|
362 | };
|
363 |
|
364 | export const updateEntryQuery = ( entryId, callback, context={}) => {
|
365 | return {entryId: entryId, callback: callback, context: context };
|
366 | }
|
367 |
|
368 |
|
369 |
|
370 |
|
371 |
|
372 |
|
373 | export const getEntryScanQuery = ( entryId, data, fields, context={}) => {
|
374 |
|
375 |
|
376 | if (data == undefined) {
|
377 | console.error("getEntryScanQuery requires a data argument, this may be empty");
|
378 | return undefined;
|
379 | }
|
380 |
|
381 |
|
382 | const queryObj = {};
|
383 |
|
384 | if (Object.keys(data).length > 0) {
|
385 | const queryKey = Object.keys(data)[0];
|
386 |
|
387 | queryObj[`scan_${entryId}_${queryKey}`] = params(
|
388 | Object.keys(data).reduce((result, key) => {
|
389 |
|
390 | if (Array.isArray(data[key])) {
|
391 | if (data[key].length > 0 && data[key][0] !== undefined) {
|
392 | result[`start_${key}`] = `"${data[key][0]}"`;
|
393 | }
|
394 |
|
395 | if (data[key].length > 1 && data[key][1] !== undefined) {
|
396 | result[`end_${key}`] = `"${data[key][1]}"`;
|
397 | }
|
398 |
|
399 | } else {
|
400 | result[key] = `"${data[key]}"`;
|
401 | }
|
402 |
|
403 | return result;
|
404 | },{}),
|
405 | Object.keys(fields).reduce((result, key) => {
|
406 | result[key] = types.string;
|
407 | return result;
|
408 | },{})
|
409 | );
|
410 |
|
411 |
|
412 |
|
413 | return {
|
414 | query:gql`${query(queryObj)}`,
|
415 | context: context
|
416 | }
|
417 |
|
418 | } else {
|
419 |
|
420 | queryObj[`scan_${entryId}`] = params(
|
421 | {scanall:`"yes"`},
|
422 | Object.keys(fields).reduce((result, key) => {
|
423 | result[key] = types.string;
|
424 | return result;
|
425 | },{})
|
426 | );
|
427 |
|
428 |
|
429 |
|
430 | return {
|
431 | query:gql`${query(queryObj)}`,
|
432 | context: context
|
433 | }
|
434 |
|
435 | }
|
436 |
|
437 |
|
438 |
|
439 |
|
440 |
|
441 | };
|
442 |
|
443 | export async function select (client, {query, context={}}) {
|
444 |
|
445 |
|
446 | if (!context["userId"]) {
|
447 | context["userId"] = new Cookies().get(IC_USER_ID);
|
448 | }
|
449 |
|
450 |
|
451 |
|
452 |
|
453 | return await client.query({
|
454 | query: query,
|
455 | context: context
|
456 | }).then(result => {
|
457 |
|
458 |
|
459 | return result.data ? result.data : result;
|
460 |
|
461 | }).catch(error => {
|
462 | console.log(error);
|
463 | });
|
464 |
|
465 | };
|
466 |
|
467 |
|
468 |
|
469 |
|
470 |
|
471 |
|
472 |
|
473 |
|
474 |
|
475 |
|
476 |
|
477 |
|
478 |
|
479 | export async function mutate (client, { mutation, context={}}) {
|
480 |
|
481 | if (!context["userId"]) {
|
482 | context["userId"] = new Cookies().get(IC_USER_ID);
|
483 | }
|
484 |
|
485 |
|
486 |
|
487 |
|
488 |
|
489 |
|
490 | return await client.mutate({
|
491 | mutation: mutation,
|
492 | context: context
|
493 | }).then(result => { }).catch(error => { console.log(error) });
|
494 |
|
495 | };
|
496 |
|
497 |
|
498 |
|
499 |
|
500 |
|
501 |
|
502 |
|
503 |
|
504 | export async function update (client, { entryId, getEntryQuery, setEntryMutation}) {
|
505 |
|
506 | const oldData = await select(
|
507 | client,
|
508 | getEntryQuery()
|
509 | );
|
510 |
|
511 |
|
512 | return await mutate(
|
513 | client,
|
514 | setEntryMutation(oldData[`get_${entryId}`])
|
515 | );
|
516 |
|
517 |
|
518 | };
|
519 |
|