@webiny/api-form-builder-so-ddb-es 0.0.0-mt-1

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 (63) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +12 -0
  3. package/configurations.d.ts +9 -0
  4. package/configurations.js +28 -0
  5. package/definitions/elasticsearch.d.ts +8 -0
  6. package/definitions/elasticsearch.js +47 -0
  7. package/definitions/form.d.ts +8 -0
  8. package/definitions/form.js +104 -0
  9. package/definitions/settings.d.ts +8 -0
  10. package/definitions/settings.js +53 -0
  11. package/definitions/submission.d.ts +8 -0
  12. package/definitions/submission.js +74 -0
  13. package/definitions/system.d.ts +8 -0
  14. package/definitions/system.js +44 -0
  15. package/definitions/table.d.ts +7 -0
  16. package/definitions/table.js +23 -0
  17. package/definitions/tableElasticsearch.d.ts +7 -0
  18. package/definitions/tableElasticsearch.js +23 -0
  19. package/index.d.ts +2 -0
  20. package/index.js +188 -0
  21. package/operations/form/elasticsearchBody.d.ts +13 -0
  22. package/operations/form/elasticsearchBody.js +187 -0
  23. package/operations/form/elasticsearchFields.d.ts +3 -0
  24. package/operations/form/elasticsearchFields.js +33 -0
  25. package/operations/form/fields.d.ts +3 -0
  26. package/operations/form/fields.js +15 -0
  27. package/operations/form/index.d.ts +17 -0
  28. package/operations/form/index.js +903 -0
  29. package/operations/settings/index.d.ts +7 -0
  30. package/operations/settings/index.js +122 -0
  31. package/operations/submission/elasticsearchBody.d.ts +13 -0
  32. package/operations/submission/elasticsearchBody.js +197 -0
  33. package/operations/submission/elasticsearchFields.d.ts +3 -0
  34. package/operations/submission/elasticsearchFields.js +30 -0
  35. package/operations/submission/index.d.ts +12 -0
  36. package/operations/submission/index.js +340 -0
  37. package/operations/system/createElasticsearchIndex.d.ts +6 -0
  38. package/operations/system/createElasticsearchIndex.js +70 -0
  39. package/operations/system/index.d.ts +7 -0
  40. package/operations/system/index.js +105 -0
  41. package/package.json +67 -0
  42. package/plugins/FormDynamoDbFieldPlugin.d.ts +4 -0
  43. package/plugins/FormDynamoDbFieldPlugin.js +17 -0
  44. package/plugins/FormElasticsearchBodyModifierPlugin.d.ts +4 -0
  45. package/plugins/FormElasticsearchBodyModifierPlugin.js +17 -0
  46. package/plugins/FormElasticsearchFieldPlugin.d.ts +4 -0
  47. package/plugins/FormElasticsearchFieldPlugin.js +17 -0
  48. package/plugins/FormElasticsearchQueryModifierPlugin.d.ts +4 -0
  49. package/plugins/FormElasticsearchQueryModifierPlugin.js +17 -0
  50. package/plugins/FormElasticsearchSortModifierPlugin.d.ts +4 -0
  51. package/plugins/FormElasticsearchSortModifierPlugin.js +17 -0
  52. package/plugins/SubmissionElasticsearchBodyModifierPlugin.d.ts +4 -0
  53. package/plugins/SubmissionElasticsearchBodyModifierPlugin.js +17 -0
  54. package/plugins/SubmissionElasticsearchFieldPlugin.d.ts +4 -0
  55. package/plugins/SubmissionElasticsearchFieldPlugin.js +17 -0
  56. package/plugins/SubmissionElasticsearchQueryModifierPlugin.d.ts +4 -0
  57. package/plugins/SubmissionElasticsearchQueryModifierPlugin.js +17 -0
  58. package/plugins/SubmissionElasticsearchSortModifierPlugin.d.ts +4 -0
  59. package/plugins/SubmissionElasticsearchSortModifierPlugin.js +17 -0
  60. package/types.d.ts +66 -0
  61. package/types.js +17 -0
  62. package/upgrades/5.16.0/index.d.ts +8 -0
  63. package/upgrades/5.16.0/index.js +141 -0
@@ -0,0 +1,903 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+
5
+ Object.defineProperty(exports, "__esModule", {
6
+ value: true
7
+ });
8
+ exports.createFormStorageOperations = void 0;
9
+
10
+ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
11
+
12
+ var _query = require("@webiny/db-dynamodb/utils/query");
13
+
14
+ var _error = _interopRequireDefault(require("@webiny/error"));
15
+
16
+ var _cleanup = require("@webiny/db-dynamodb/utils/cleanup");
17
+
18
+ var _batchWrite = require("@webiny/db-dynamodb/utils/batchWrite");
19
+
20
+ var _configurations = _interopRequireDefault(require("../../configurations"));
21
+
22
+ var _filter = require("@webiny/db-dynamodb/utils/filter");
23
+
24
+ var _fields = _interopRequireDefault(require("./fields"));
25
+
26
+ var _sort = require("@webiny/db-dynamodb/utils/sort");
27
+
28
+ var _utils = require("@webiny/utils");
29
+
30
+ var _elasticsearchBody = require("./elasticsearchBody");
31
+
32
+ var _cursors = require("@webiny/api-elasticsearch/cursors");
33
+
34
+ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; }
35
+
36
+ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { (0, _defineProperty2.default)(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
37
+
38
+ const getESDataForLatestRevision = form => ({
39
+ __type: (0, _elasticsearchBody.createFormElasticType)(),
40
+ id: form.id,
41
+ createdOn: form.createdOn,
42
+ savedOn: form.savedOn,
43
+ name: form.name,
44
+ slug: form.slug,
45
+ published: form.published,
46
+ publishedOn: form.publishedOn,
47
+ version: form.version,
48
+ locked: form.locked,
49
+ status: form.status,
50
+ createdBy: form.createdBy,
51
+ ownedBy: form.ownedBy,
52
+ tenant: form.tenant,
53
+ locale: form.locale,
54
+ webinyVersion: form.webinyVersion,
55
+ formId: form.formId
56
+ });
57
+
58
+ const createFormStorageOperations = params => {
59
+ const {
60
+ entity,
61
+ esEntity,
62
+ table,
63
+ plugins,
64
+ elasticsearch
65
+ } = params;
66
+ const formDynamoDbFields = (0, _fields.default)();
67
+
68
+ const createFormPartitionKey = params => {
69
+ const {
70
+ tenant,
71
+ locale,
72
+ id: targetId
73
+ } = params;
74
+ const {
75
+ id
76
+ } = (0, _utils.parseIdentifier)(targetId);
77
+ return `T#${tenant}#L#${locale}#FB#F#${id}`;
78
+ };
79
+
80
+ const createRevisionSortKey = value => {
81
+ const version = typeof value === "number" ? Number(value) : (0, _utils.parseIdentifier)(value).version;
82
+ return `REV#${(0, _utils.zeroPad)(version)}`;
83
+ };
84
+
85
+ const createLatestSortKey = () => {
86
+ return "L";
87
+ };
88
+
89
+ const createLatestPublishedSortKey = () => {
90
+ return "LP";
91
+ };
92
+
93
+ const createFormType = () => {
94
+ return "fb.form";
95
+ };
96
+
97
+ const createFormLatestType = () => {
98
+ return "fb.form.latest";
99
+ };
100
+
101
+ const createFormLatestPublishedType = () => {
102
+ return "fb.form.latestPublished";
103
+ };
104
+
105
+ const createForm = async params => {
106
+ const {
107
+ form
108
+ } = params;
109
+ const revisionKeys = {
110
+ PK: createFormPartitionKey(form),
111
+ SK: createRevisionSortKey(form.id)
112
+ };
113
+ const latestKeys = {
114
+ PK: createFormPartitionKey(form),
115
+ SK: createLatestSortKey()
116
+ };
117
+ const items = [entity.putBatch(_objectSpread(_objectSpread({}, form), {}, {
118
+ TYPE: createFormType()
119
+ }, revisionKeys)), entity.putBatch(_objectSpread(_objectSpread({}, form), {}, {
120
+ TYPE: createFormLatestType()
121
+ }, latestKeys))];
122
+
123
+ try {
124
+ await (0, _batchWrite.batchWriteAll)({
125
+ table,
126
+ items
127
+ });
128
+ } catch (ex) {
129
+ throw new _error.default(ex.message || "Could not insert form data into regular table.", ex.code || "CREATE_FORM_ERROR", {
130
+ revisionKeys,
131
+ latestKeys,
132
+ form
133
+ });
134
+ }
135
+
136
+ try {
137
+ const {
138
+ index
139
+ } = _configurations.default.es({
140
+ tenant: form.tenant
141
+ });
142
+
143
+ await esEntity.put(_objectSpread({
144
+ index,
145
+ data: getESDataForLatestRevision(form),
146
+ TYPE: createFormType()
147
+ }, latestKeys));
148
+ } catch (ex) {
149
+ throw new _error.default(ex.message || "Could not insert form data into Elasticsearch table.", ex.code || "CREATE_FORM_ERROR", {
150
+ latestKeys,
151
+ form
152
+ });
153
+ }
154
+
155
+ return form;
156
+ };
157
+
158
+ const createFormFrom = async params => {
159
+ const {
160
+ form,
161
+ original,
162
+ latest
163
+ } = params;
164
+ const revisionKeys = {
165
+ PK: createFormPartitionKey(form),
166
+ SK: createRevisionSortKey(form.version)
167
+ };
168
+ const latestKeys = {
169
+ PK: createFormPartitionKey(form),
170
+ SK: createLatestSortKey()
171
+ };
172
+ const items = [entity.putBatch(_objectSpread(_objectSpread(_objectSpread({}, form), revisionKeys), {}, {
173
+ TYPE: createFormType()
174
+ })), entity.putBatch(_objectSpread(_objectSpread(_objectSpread({}, form), latestKeys), {}, {
175
+ TYPE: createFormLatestType()
176
+ }))];
177
+
178
+ try {
179
+ await (0, _batchWrite.batchWriteAll)({
180
+ table,
181
+ items
182
+ });
183
+ } catch (ex) {
184
+ throw new _error.default(ex.message || "Could not create form data in the regular table, from existing form.", ex.code || "CREATE_FORM_FROM_ERROR", {
185
+ revisionKeys,
186
+ latestKeys,
187
+ original,
188
+ form,
189
+ latest
190
+ });
191
+ }
192
+
193
+ try {
194
+ const {
195
+ index
196
+ } = _configurations.default.es({
197
+ tenant: form.tenant
198
+ });
199
+
200
+ await esEntity.put(_objectSpread({
201
+ index,
202
+ data: getESDataForLatestRevision(form),
203
+ TYPE: createFormLatestType()
204
+ }, latestKeys));
205
+ } catch (ex) {
206
+ throw new _error.default(ex.message || "Could not create form in the Elasticsearch table, from existing form.", ex.code || "CREATE_FORM_FROM_ERROR", {
207
+ latestKeys,
208
+ form,
209
+ latest,
210
+ original
211
+ });
212
+ }
213
+
214
+ return form;
215
+ };
216
+
217
+ const updateForm = async params => {
218
+ const {
219
+ form,
220
+ original
221
+ } = params;
222
+ const revisionKeys = {
223
+ PK: createFormPartitionKey(form),
224
+ SK: createRevisionSortKey(form.id)
225
+ };
226
+ const latestKeys = {
227
+ PK: createFormPartitionKey(form),
228
+ SK: createLatestSortKey()
229
+ };
230
+ const {
231
+ formId,
232
+ tenant,
233
+ locale
234
+ } = form;
235
+ const latestForm = await getForm({
236
+ where: {
237
+ formId,
238
+ tenant,
239
+ locale,
240
+ latest: true
241
+ }
242
+ });
243
+ const isLatestForm = latestForm ? latestForm.id === form.id : false;
244
+ const items = [entity.putBatch(_objectSpread(_objectSpread({}, form), {}, {
245
+ TYPE: createFormType()
246
+ }, revisionKeys))];
247
+
248
+ if (isLatestForm) {
249
+ items.push(entity.putBatch(_objectSpread(_objectSpread({}, form), {}, {
250
+ TYPE: createFormLatestType()
251
+ }, latestKeys)));
252
+ }
253
+
254
+ try {
255
+ await (0, _batchWrite.batchWriteAll)({
256
+ table,
257
+ items
258
+ });
259
+ } catch (ex) {
260
+ throw new _error.default(ex.message || "Could not update form data in the regular table.", ex.code || "UPDATE_FORM_ERROR", {
261
+ revisionKeys,
262
+ latestKeys,
263
+ original,
264
+ form,
265
+ latestForm
266
+ });
267
+ }
268
+ /**
269
+ * No need to go further if its not latest form.
270
+ */
271
+
272
+
273
+ if (!isLatestForm) {
274
+ return form;
275
+ }
276
+
277
+ try {
278
+ const {
279
+ index
280
+ } = _configurations.default.es({
281
+ tenant: form.tenant
282
+ });
283
+
284
+ await esEntity.put(_objectSpread({
285
+ index,
286
+ data: getESDataForLatestRevision(form),
287
+ TYPE: createFormLatestType()
288
+ }, latestKeys));
289
+ } catch (ex) {
290
+ throw new _error.default(ex.message || "Could not update form data in the Elasticsearch table.", ex.code || "UPDATE_FORM_ERROR", {
291
+ latestKeys,
292
+ form,
293
+ latestForm,
294
+ original
295
+ });
296
+ }
297
+
298
+ return form;
299
+ };
300
+
301
+ const getForm = async params => {
302
+ const {
303
+ where
304
+ } = params;
305
+ const {
306
+ id,
307
+ formId,
308
+ latest,
309
+ published,
310
+ version,
311
+ tenant,
312
+ locale
313
+ } = where;
314
+
315
+ if (latest && published) {
316
+ throw new _error.default("Cannot have both latest and published params.");
317
+ }
318
+
319
+ let sortKey;
320
+
321
+ if (latest) {
322
+ sortKey = createLatestSortKey();
323
+ } else if (published && !version) {
324
+ /**
325
+ * Because of the specifics how DynamoDB works, we must not load the published record if version is sent.
326
+ */
327
+ sortKey = createLatestPublishedSortKey();
328
+ } else if (id || version) {
329
+ sortKey = createRevisionSortKey(version || id);
330
+ } else {
331
+ throw new _error.default("Missing parameter to create a sort key.", "MISSING_WHERE_PARAMETER", {
332
+ where
333
+ });
334
+ }
335
+
336
+ const keys = {
337
+ PK: createFormPartitionKey({
338
+ tenant,
339
+ locale,
340
+ id: formId || id
341
+ }),
342
+ SK: sortKey
343
+ };
344
+
345
+ try {
346
+ const result = await entity.get(keys);
347
+
348
+ if (!result || !result.Item) {
349
+ return null;
350
+ }
351
+
352
+ return (0, _cleanup.cleanupItem)(entity, result.Item);
353
+ } catch (ex) {
354
+ throw new _error.default(ex.message || "Could not get form by keys.", ex.code || "GET_FORM_ERROR", {
355
+ keys
356
+ });
357
+ }
358
+ };
359
+
360
+ const listForms = async params => {
361
+ const {
362
+ sort,
363
+ limit,
364
+ where,
365
+ after
366
+ } = params;
367
+ const body = (0, _elasticsearchBody.createElasticsearchBody)({
368
+ plugins,
369
+ sort,
370
+ limit: limit + 1,
371
+ where,
372
+ after: (0, _cursors.decodeCursor)(after)
373
+ });
374
+
375
+ const esConfig = _configurations.default.es({
376
+ tenant: where.tenant
377
+ });
378
+
379
+ const query = _objectSpread(_objectSpread({}, esConfig), {}, {
380
+ body
381
+ });
382
+
383
+ let response;
384
+
385
+ try {
386
+ response = await elasticsearch.search(query);
387
+ } catch (ex) {
388
+ throw new _error.default(ex.message || "Could list forms.", ex.code || "LIST_FORMS_ERROR", {
389
+ where,
390
+ query
391
+ });
392
+ }
393
+
394
+ const {
395
+ hits,
396
+ total
397
+ } = response.body.hits;
398
+ const items = hits.map(item => item._source);
399
+ const hasMoreItems = items.length > limit;
400
+
401
+ if (hasMoreItems) {
402
+ /**
403
+ * Remove the last item from results, we don't want to include it.
404
+ */
405
+ items.pop();
406
+ }
407
+ /**
408
+ * Cursor is the `sort` value of the last item in the array.
409
+ * https://www.elastic.co/guide/en/elasticsearch/reference/current/paginate-search-results.html#search-after
410
+ */
411
+
412
+
413
+ const meta = {
414
+ hasMoreItems,
415
+ totalCount: total.value,
416
+ cursor: items.length > 0 ? (0, _cursors.encodeCursor)(hits[items.length - 1].sort) : null
417
+ };
418
+ return {
419
+ items,
420
+ meta
421
+ };
422
+ };
423
+
424
+ const listFormRevisions = async params => {
425
+ const {
426
+ where: initialWhere,
427
+ sort
428
+ } = params;
429
+ const {
430
+ id,
431
+ formId,
432
+ tenant,
433
+ locale
434
+ } = initialWhere;
435
+ const queryAllParams = {
436
+ entity,
437
+ partitionKey: createFormPartitionKey({
438
+ tenant,
439
+ locale,
440
+ id: id || formId
441
+ }),
442
+ options: {
443
+ beginsWith: "REV#"
444
+ }
445
+ };
446
+ let items = [];
447
+
448
+ try {
449
+ items = await (0, _query.queryAll)(queryAllParams);
450
+ } catch (ex) {
451
+ throw new _error.default(ex.message || "Could not query forms by given params.", ex.code || "QUERY_FORMS_ERROR", {
452
+ partitionKey: queryAllParams.partitionKey,
453
+ options: queryAllParams.options
454
+ });
455
+ }
456
+
457
+ const where = _objectSpread(_objectSpread({}, initialWhere), {}, {
458
+ id: undefined,
459
+ formId: undefined
460
+ });
461
+
462
+ const filteredItems = (0, _filter.filterItems)({
463
+ plugins,
464
+ items,
465
+ where,
466
+ fields: formDynamoDbFields
467
+ });
468
+
469
+ if (Array.isArray(sort) === false || sort.length === 0) {
470
+ return filteredItems;
471
+ }
472
+
473
+ return (0, _sort.sortItems)({
474
+ items: filteredItems,
475
+ sort,
476
+ fields: formDynamoDbFields
477
+ });
478
+ };
479
+
480
+ const deleteForm = async params => {
481
+ const {
482
+ form
483
+ } = params;
484
+ let items;
485
+ /**
486
+ * This will find all form and submission records.
487
+ */
488
+
489
+ const queryAllParams = {
490
+ entity,
491
+ partitionKey: createFormPartitionKey(form),
492
+ options: {
493
+ gte: " "
494
+ }
495
+ };
496
+
497
+ try {
498
+ items = await (0, _query.queryAll)(queryAllParams);
499
+ } catch (ex) {
500
+ throw new _error.default(ex.message || "Could not query forms and submissions by given params.", ex.code || "QUERY_FORM_AND_SUBMISSIONS_ERROR", {
501
+ partitionKey: queryAllParams.partitionKey,
502
+ options: queryAllParams.options
503
+ });
504
+ }
505
+
506
+ const deleteItems = items.map(item => {
507
+ return entity.deleteBatch({
508
+ PK: item.PK,
509
+ SK: item.SK
510
+ });
511
+ });
512
+
513
+ try {
514
+ await (0, _batchWrite.batchWriteAll)({
515
+ table,
516
+ items: deleteItems
517
+ });
518
+ } catch (ex) {
519
+ throw new _error.default(ex.message || "Could not delete form and it's submissions.", ex.code || "DELETE_FORM_AND_SUBMISSIONS_ERROR");
520
+ }
521
+
522
+ const latestKeys = {
523
+ PK: createFormPartitionKey(form),
524
+ SK: createLatestSortKey()
525
+ };
526
+
527
+ try {
528
+ await esEntity.delete(latestKeys);
529
+ } catch (ex) {
530
+ throw new _error.default(ex.message || "Could not delete latest form record from Elasticsearch.", ex.code || "DELETE_FORM_ERROR", {
531
+ latestKeys
532
+ });
533
+ }
534
+
535
+ return form;
536
+ };
537
+ /**
538
+ * We need to:
539
+ * - delete current revision
540
+ * - get previously published revision and update the record if it exists or delete if it does not
541
+ * - update latest record if current one is the latest
542
+ */
543
+
544
+
545
+ const deleteFormRevision = async params => {
546
+ const {
547
+ form,
548
+ revisions,
549
+ previous
550
+ } = params;
551
+ const revisionKeys = {
552
+ PK: createFormPartitionKey(form),
553
+ SK: createRevisionSortKey(form.id)
554
+ };
555
+ const latestKeys = {
556
+ PK: createFormPartitionKey(form),
557
+ SK: createLatestSortKey()
558
+ };
559
+ const latestForm = revisions[0];
560
+ const latestPublishedForm = revisions.find(rev => rev.published === true);
561
+ const isLatest = latestForm ? latestForm.id === form.id : false;
562
+ const isLatestPublished = latestPublishedForm ? latestPublishedForm.id === form.id : false;
563
+ const items = [entity.deleteBatch(revisionKeys)];
564
+ let esDataItem = undefined;
565
+
566
+ if (isLatest || isLatestPublished) {
567
+ /**
568
+ * Sort out the latest published record.
569
+ */
570
+ if (isLatestPublished) {
571
+ const previouslyPublishedForm = revisions.filter(f => !!f.publishedOn && f.version !== form.version).sort((a, b) => {
572
+ return new Date(b.publishedOn).getTime() - new Date(a.publishedOn).getTime();
573
+ }).shift();
574
+
575
+ if (previouslyPublishedForm) {
576
+ items.push(entity.putBatch(_objectSpread(_objectSpread({}, previouslyPublishedForm), {}, {
577
+ PK: createFormPartitionKey(previouslyPublishedForm),
578
+ SK: createLatestPublishedSortKey(),
579
+ TYPE: createFormLatestPublishedType()
580
+ })));
581
+ } else {
582
+ items.push(entity.deleteBatch({
583
+ PK: createFormPartitionKey(previouslyPublishedForm),
584
+ SK: createLatestPublishedSortKey()
585
+ }));
586
+ }
587
+ }
588
+ /**
589
+ * Sort out the latest record.
590
+ */
591
+
592
+
593
+ if (isLatest) {
594
+ items.push(entity.putBatch(_objectSpread(_objectSpread(_objectSpread({}, previous), latestKeys), {}, {
595
+ TYPE: createFormLatestType()
596
+ })));
597
+
598
+ const {
599
+ index
600
+ } = _configurations.default.es({
601
+ tenant: previous.tenant
602
+ });
603
+
604
+ esDataItem = _objectSpread(_objectSpread({
605
+ index
606
+ }, latestKeys), {}, {
607
+ data: getESDataForLatestRevision(previous)
608
+ });
609
+ }
610
+ }
611
+ /**
612
+ * Now save the batch data.
613
+ */
614
+
615
+
616
+ try {
617
+ await (0, _batchWrite.batchWriteAll)({
618
+ table,
619
+ items
620
+ });
621
+ } catch (ex) {
622
+ throw new _error.default(ex.message || "Could not delete form revision from regular table.", ex.code || "DELETE_FORM_REVISION_ERROR", {
623
+ form,
624
+ latestForm,
625
+ revisionKeys,
626
+ latestKeys
627
+ });
628
+ }
629
+ /**
630
+ * And then the Elasticsearch data, if any.
631
+ */
632
+
633
+
634
+ if (!esDataItem) {
635
+ return form;
636
+ }
637
+
638
+ try {
639
+ await esEntity.put(esDataItem);
640
+ return form;
641
+ } catch (ex) {
642
+ throw new _error.default(ex.message || "Could not delete form from to the Elasticsearch table.", ex.code || "DELETE_FORM_REVISION_ERROR", {
643
+ form,
644
+ latestForm,
645
+ revisionKeys,
646
+ latestKeys
647
+ });
648
+ }
649
+ };
650
+ /**
651
+ * We need to save form in:
652
+ * - regular form record
653
+ * - latest published form record
654
+ * - latest form record - if form is latest one
655
+ * - elasticsearch latest form record
656
+ */
657
+
658
+
659
+ const publishForm = async params => {
660
+ const {
661
+ form,
662
+ original
663
+ } = params;
664
+ const revisionKeys = {
665
+ PK: createFormPartitionKey(form),
666
+ SK: createRevisionSortKey(form.version)
667
+ };
668
+ const latestKeys = {
669
+ PK: createFormPartitionKey(form),
670
+ SK: createLatestSortKey()
671
+ };
672
+ const latestPublishedKeys = {
673
+ PK: createFormPartitionKey(form),
674
+ SK: createLatestPublishedSortKey()
675
+ };
676
+ const {
677
+ locale,
678
+ tenant,
679
+ formId
680
+ } = form;
681
+ const latestForm = await getForm({
682
+ where: {
683
+ formId,
684
+ tenant,
685
+ locale,
686
+ latest: true
687
+ }
688
+ });
689
+ const isLatestForm = latestForm ? latestForm.id === form.id : false;
690
+ /**
691
+ * Update revision and latest published records
692
+ */
693
+
694
+ const items = [entity.putBatch(_objectSpread(_objectSpread(_objectSpread({}, form), revisionKeys), {}, {
695
+ TYPE: createFormType()
696
+ })), entity.putBatch(_objectSpread(_objectSpread(_objectSpread({}, form), latestPublishedKeys), {}, {
697
+ TYPE: createFormLatestPublishedType()
698
+ }))];
699
+ /**
700
+ * Update the latest form as well
701
+ */
702
+
703
+ if (isLatestForm) {
704
+ items.push(entity.putBatch(_objectSpread(_objectSpread(_objectSpread({}, form), latestKeys), {}, {
705
+ TYPE: createFormLatestType()
706
+ })));
707
+ }
708
+
709
+ try {
710
+ await (0, _batchWrite.batchWriteAll)({
711
+ table,
712
+ items
713
+ });
714
+ } catch (ex) {
715
+ throw new _error.default(ex.message || "Could not publish form.", ex.code || "PUBLISH_FORM_ERROR", {
716
+ form,
717
+ original,
718
+ latestForm,
719
+ revisionKeys,
720
+ latestKeys,
721
+ latestPublishedKeys
722
+ });
723
+ }
724
+
725
+ if (!isLatestForm) {
726
+ return form;
727
+ }
728
+
729
+ const {
730
+ index
731
+ } = _configurations.default.es({
732
+ tenant: form.tenant
733
+ });
734
+
735
+ const esData = getESDataForLatestRevision(form);
736
+
737
+ try {
738
+ await esEntity.put(_objectSpread(_objectSpread({}, latestKeys), {}, {
739
+ index,
740
+ TYPE: createFormLatestType(),
741
+ data: esData
742
+ }));
743
+ return form;
744
+ } catch (ex) {
745
+ throw new _error.default(ex.message || "Could not publish form to the Elasticsearch.", ex.code || "PUBLISH_FORM_ERROR", {
746
+ form,
747
+ original,
748
+ latestForm,
749
+ revisionKeys,
750
+ latestKeys,
751
+ latestPublishedKeys
752
+ });
753
+ }
754
+ };
755
+ /**
756
+ * We need to:
757
+ * - update form revision record
758
+ * - if latest published (LP) is current form, find the previously published record and update LP if there is some previously published, delete otherwise
759
+ * - if is latest update the Elasticsearch record
760
+ */
761
+
762
+
763
+ const unpublishForm = async params => {
764
+ const {
765
+ form,
766
+ original
767
+ } = params;
768
+ const revisionKeys = {
769
+ PK: createFormPartitionKey(form),
770
+ SK: createRevisionSortKey(form.version)
771
+ };
772
+ const latestKeys = {
773
+ PK: createFormPartitionKey(form),
774
+ SK: createLatestSortKey()
775
+ };
776
+ const latestPublishedKeys = {
777
+ PK: createFormPartitionKey(form),
778
+ SK: createLatestPublishedSortKey()
779
+ };
780
+ const {
781
+ formId,
782
+ tenant,
783
+ locale
784
+ } = form;
785
+ const latestForm = await getForm({
786
+ where: {
787
+ formId,
788
+ tenant,
789
+ locale,
790
+ latest: true
791
+ }
792
+ });
793
+ const latestPublishedForm = await getForm({
794
+ where: {
795
+ formId,
796
+ tenant,
797
+ locale,
798
+ published: true
799
+ }
800
+ });
801
+ const isLatest = latestForm ? latestForm.id === form.id : false;
802
+ const isLatestPublished = latestPublishedForm ? latestPublishedForm.id === form.id : false;
803
+ const items = [entity.putBatch(_objectSpread(_objectSpread(_objectSpread({}, form), revisionKeys), {}, {
804
+ TYPE: createFormType()
805
+ }))];
806
+ let esData = undefined;
807
+
808
+ if (isLatest) {
809
+ esData = getESDataForLatestRevision(form);
810
+ }
811
+ /**
812
+ * In case previously published revision exists, replace current one with that one.
813
+ * And if it does not, delete the record.
814
+ */
815
+
816
+
817
+ if (isLatestPublished) {
818
+ const revisions = await listFormRevisions({
819
+ where: {
820
+ formId,
821
+ tenant,
822
+ locale,
823
+ version_not: form.version,
824
+ publishedOn_not: null
825
+ },
826
+ sort: ["savedOn_DESC"]
827
+ });
828
+ const previouslyPublishedRevision = revisions.shift();
829
+
830
+ if (previouslyPublishedRevision) {
831
+ items.push(entity.putBatch(_objectSpread(_objectSpread(_objectSpread({}, previouslyPublishedRevision), latestPublishedKeys), {}, {
832
+ TYPE: createFormLatestPublishedType()
833
+ })));
834
+ } else {
835
+ items.push(entity.deleteBatch(latestPublishedKeys));
836
+ }
837
+ }
838
+
839
+ try {
840
+ await (0, _batchWrite.batchWriteAll)({
841
+ table,
842
+ items
843
+ });
844
+ } catch (ex) {
845
+ throw new _error.default(ex.message || "Could not unpublish form.", ex.code || "UNPUBLISH_FORM_ERROR", {
846
+ form,
847
+ original,
848
+ latestForm,
849
+ revisionKeys,
850
+ latestKeys,
851
+ latestPublishedKeys
852
+ });
853
+ }
854
+ /**
855
+ * No need to go further in case of non-existing Elasticsearch data.
856
+ */
857
+
858
+
859
+ if (!esData) {
860
+ return form;
861
+ }
862
+
863
+ const {
864
+ index
865
+ } = _configurations.default.es({
866
+ tenant: form.tenant
867
+ });
868
+
869
+ try {
870
+ await esEntity.put(_objectSpread(_objectSpread({}, latestKeys), {}, {
871
+ index,
872
+ TYPE: createFormLatestType(),
873
+ data: esData
874
+ }));
875
+ return form;
876
+ } catch (ex) {
877
+ throw new _error.default(ex.message || "Could not unpublish form from the Elasticsearch.", ex.code || "UNPUBLISH_FORM_ERROR", {
878
+ form,
879
+ original,
880
+ latestForm,
881
+ revisionKeys,
882
+ latestKeys,
883
+ latestPublishedKeys
884
+ });
885
+ }
886
+ };
887
+
888
+ return {
889
+ createForm,
890
+ createFormFrom,
891
+ updateForm,
892
+ listForms,
893
+ listFormRevisions,
894
+ getForm,
895
+ deleteForm,
896
+ deleteFormRevision,
897
+ publishForm,
898
+ unpublishForm,
899
+ createFormPartitionKey
900
+ };
901
+ };
902
+
903
+ exports.createFormStorageOperations = createFormStorageOperations;