cordova-plugin-unvired-universal-sdk 1.0.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 (82) hide show
  1. package/README.md +59 -0
  2. package/aar/README.md +3 -0
  3. package/aar/Unvired_Kernel_Android.aar +0 -0
  4. package/aar/Unvired_Kernel_HTML5_Android.aar +0 -0
  5. package/package.json +69 -0
  6. package/plugin.xml +23 -0
  7. package/src/android/build.gradle +35 -0
  8. package/src/android/xml/provider_paths.xml +21 -0
  9. package/src/browser/UnviredPluginProxy.js +2430 -0
  10. package/src/browser/bootstrap.min.js +17 -0
  11. package/src/browser/codemirror.js +9755 -0
  12. package/src/browser/jquery-3.2.1.js +10253 -0
  13. package/src/browser/sql-wasm.wasm +0 -0
  14. package/src/browser/sql.js +203 -0
  15. package/src/browser/src_index_worker_js.unvired-db-worker.js +231 -0
  16. package/src/browser/unvired-db-worker.js +166 -0
  17. package/src/browser/vendors-node_modules_comlink_dist_esm_comlink_mjs.unvired-db-worker.js +22 -0
  18. package/src/ios/AttachmentPlugin.h +21 -0
  19. package/src/ios/AttachmentPlugin.m +180 -0
  20. package/src/ios/DataStructureHelper.h +28 -0
  21. package/src/ios/DataStructureHelper.m +188 -0
  22. package/src/ios/IOSAuthPlugin.h +14 -0
  23. package/src/ios/IOSAuthPlugin.m +13 -0
  24. package/src/ios/IOSDatabasePlugin.h +28 -0
  25. package/src/ios/IOSDatabasePlugin.m +253 -0
  26. package/src/ios/IOSFWSettingsPlugin.h +65 -0
  27. package/src/ios/IOSFWSettingsPlugin.m +363 -0
  28. package/src/ios/IOSLoggerPlugin.h +34 -0
  29. package/src/ios/IOSLoggerPlugin.m +198 -0
  30. package/src/ios/IOSLoginPlugin.h +29 -0
  31. package/src/ios/IOSLoginPlugin.m +480 -0
  32. package/src/ios/IOSProxyPlugin.h +21 -0
  33. package/src/ios/IOSProxyPlugin.m +172 -0
  34. package/src/ios/IOSSyncEnginePlugin.h +54 -0
  35. package/src/ios/IOSSyncEnginePlugin.m +847 -0
  36. package/src/ios/PluginConstants.h +195 -0
  37. package/src/ios/PluginHelper.h +29 -0
  38. package/src/ios/PluginHelper.m +74 -0
  39. package/src/ios/SyncHTML5Response.h +50 -0
  40. package/src/ios/SyncHTML5Response.m +68 -0
  41. package/www/applicationMeta/applicationMetadataParser.ts +285 -0
  42. package/www/applicationMeta/fieldConstants.ts +92 -0
  43. package/www/attachment/attachmentHelper.ts +326 -0
  44. package/www/attachment/attachmentQHelper.ts +158 -0
  45. package/www/attachment/attachmentService.ts +259 -0
  46. package/www/authenticationService.ts +746 -0
  47. package/www/bootstrap.min.js +17 -0
  48. package/www/codemirror.js +9755 -0
  49. package/www/database/appDatabaseManager.ts +54 -0
  50. package/www/database/databaseManager.ts +616 -0
  51. package/www/helper/dbCreateTablesManager.ts +354 -0
  52. package/www/helper/frameworkHelper.ts +127 -0
  53. package/www/helper/frameworkSettingsManager.ts +287 -0
  54. package/www/helper/getMessageTimerManager.ts +81 -0
  55. package/www/helper/httpConnection.ts +1051 -0
  56. package/www/helper/logger.ts +312 -0
  57. package/www/helper/notificationListnerHelper.ts +56 -0
  58. package/www/helper/passcodeGenerator.ts +61 -0
  59. package/www/helper/reconciler.ts +1062 -0
  60. package/www/helper/serverResponseHandler.ts +677 -0
  61. package/www/helper/serviceConstants.ts +254 -0
  62. package/www/helper/settingsHelper.ts +386 -0
  63. package/www/helper/status.ts +83 -0
  64. package/www/helper/syncInputDataManager.ts +205 -0
  65. package/www/helper/unviredAccount.ts +104 -0
  66. package/www/helper/unviredAccountManager.ts +120 -0
  67. package/www/helper/urlService.ts +43 -0
  68. package/www/helper/userSettingsManager.ts +172 -0
  69. package/www/helper/utils.ts +110 -0
  70. package/www/inbox/downloadMessageService.ts +270 -0
  71. package/www/inbox/inboxHelper.ts +132 -0
  72. package/www/inbox/inboxService.ts +223 -0
  73. package/www/jquery-3.2.1.js +10253 -0
  74. package/www/kernel.js +1380 -0
  75. package/www/outbox/outboxAttachmentManager.ts +152 -0
  76. package/www/outbox/outboxHelper.ts +67 -0
  77. package/www/outbox/outboxService.ts +519 -0
  78. package/www/sql-wasm.wasm +0 -0
  79. package/www/sql.js +209 -0
  80. package/www/subtract.ts +5 -0
  81. package/www/sum.ts +4 -0
  82. package/www/syncEngine.ts +687 -0
@@ -0,0 +1,677 @@
1
+ import { FieldMeta, StructureMeta } from "../applicationMeta/applicationMetadataParser";
2
+ import { DatabaseManager, DatabaseType } from "../database/databaseManager";
3
+ import { Logger } from "./logger";
4
+ import { RequestType } from "./serviceConstants";
5
+ import * as FieldConstants from '../applicationMeta/fieldConstants';
6
+ import * as ServiceConstants from '../helper/serviceConstants';
7
+ import { LogType, ObjectStatus, SyncStatus } from "./utils";
8
+ import FrameworkHelper from "./frameworkHelper";
9
+ import Reconciler, { ReconcilerType } from "./reconciler";
10
+ import { SyncEngine } from "../syncEngine";
11
+ import AttachmentQHelper from "../attachment/attachmentQHelper";
12
+ import { NotificationListenerHelper, NotificationListnerType } from "./notificationListnerHelper";
13
+
14
+ const EventFieldBeName = "beName";
15
+ const EventFieldBeLid = "lid";
16
+ const EventFieldActionType = "actionType";
17
+ const EventFieldRequestType = "requestType";
18
+ const EventFieldHeaderDataStructure = "headerDataStructure";
19
+
20
+ class ServerResponseHandler {
21
+ static sourceClass: string = "ServerResponseHandler";
22
+
23
+ static async handleResponseData(responseData: any, autoSave: boolean, isForeground: boolean, lid: string, entityName: string, requestType: RequestType) {
24
+ Logger.logInfo(this.sourceClass, "handleResponseData", "Starting of Server response Handler.");
25
+ if (Object.keys(responseData).length > 0) {
26
+ Logger.logInfo(this.sourceClass, "handleResponseData", "Starting of Server response Handler(Response is not empty)");
27
+ try {
28
+ const databaseManager = await DatabaseManager.getInstance();
29
+ const processedHeaders: any[] = [];
30
+ let metaData: any = {};
31
+ let infoMessages: any[] = [];
32
+ if (responseData[ServiceConstants.KeyMeta] != null) {
33
+ metaData = responseData[ServiceConstants.KeyMeta];
34
+ delete responseData[ServiceConstants.KeyMeta];
35
+ }
36
+ let isInfoMessageFailure = false;
37
+ let isInfoMessageFailureAndProcess = false;
38
+ let infoMsgCategory = "";
39
+ const beMetas = await DatabaseManager.getInstance().select(DatabaseType.FrameworkDb, "BusinessEntityMeta");
40
+ var structureMetas = await DatabaseManager.getInstance().select(DatabaseType.FrameworkDb, "StructureMeta");
41
+ const fieldMetas = await DatabaseManager.getInstance().select(DatabaseType.FrameworkDb, "FieldMeta");
42
+
43
+ if (entityName && entityName.length > 0) {
44
+ const structureMeta = structureMetas.find(
45
+ (element) => element.structureName === entityName
46
+ );
47
+ if (!structureMeta) {
48
+ const msgString = "Entity definition is not available in metadata.json";
49
+ Logger.logError(this.sourceClass, "handleResponseData", msgString);
50
+ throw new Error(msgString);
51
+ }
52
+ const beMeta = beMetas.find(
53
+ (element) => element.beName === structureMeta.beName
54
+ );
55
+ if (!beMeta) {
56
+ const msgString = "Business Entity Meta is not available in metadata.json";
57
+ Logger.logError(this.sourceClass, "handleResponseData", msgString);
58
+ throw new Error(msgString);
59
+ }
60
+ if (beMeta.save === "false") {
61
+ lid = "";
62
+ entityName = "";
63
+ }
64
+ }
65
+
66
+ const structureMetaTemp: any[] = [];
67
+ for (const structureMeta of structureMetas) {
68
+ const beMeta = beMetas.find(
69
+ (element) => element.beName === structureMeta.beName
70
+ );
71
+ if (!beMeta) {
72
+ const msgString = "Business Entity Meta is not available in metadata.json";
73
+ Logger.logError(this.sourceClass, "handleResponseData", msgString);
74
+ throw new Error(msgString);
75
+ }
76
+ if (beMeta.save === "true") {
77
+ structureMetaTemp.push(structureMeta);
78
+ }
79
+ }
80
+ structureMetas = structureMetaTemp;
81
+
82
+ // Save InfoMessages
83
+ if (responseData[ServiceConstants.KeyInfoMessage] != null) {
84
+ infoMessages = responseData[ServiceConstants.KeyInfoMessage];
85
+ if (infoMessages.length > 0) {
86
+ const updatedInfoMessages: any[] = [];
87
+ for (const element of infoMessages) {
88
+ if (element[FieldConstants.FieldInfoMessageCategory] != null) {
89
+ if (this.getRank(element[FieldConstants.FieldInfoMessageCategory]) <
90
+ this.getRank(infoMsgCategory)) {
91
+ infoMsgCategory = element[FieldConstants.FieldInfoMessageCategory];
92
+ }
93
+ }
94
+
95
+ if (element[FieldConstants.FieldInfoMessageCategory] != null &&
96
+ element[FieldConstants.FieldInfoMessageCategory] === FieldConstants.InfoMessageFailure &&
97
+ !isInfoMessageFailure) {
98
+ isInfoMessageFailure = true;
99
+ }
100
+ if (element[FieldConstants.FieldInfoMessageCategory] != null &&
101
+ element[FieldConstants.FieldInfoMessageCategory] === FieldConstants.InfoMessageFailureAndProcess &&
102
+ !isInfoMessageFailureAndProcess) {
103
+ isInfoMessageFailureAndProcess = true;
104
+ }
105
+ const infoMessage = {
106
+ lid: FrameworkHelper.getUUID(),
107
+ timestamp: Date.now(),
108
+ objectStatus: ObjectStatus.global,
109
+ syncStatus: SyncStatus.none,
110
+ type: "",
111
+ subtype: "",
112
+ category: element[FieldConstants.FieldInfoMessageCategory],
113
+ message: element[FieldConstants.FieldInfoMessageMessage],
114
+ bename: entityName,
115
+ belid: lid,
116
+ messagedetails: new Uint8Array(0)
117
+ };
118
+ await databaseManager.insert(DatabaseType.FrameworkDb, 'InfoMessage', infoMessage, true);
119
+ const infoMessageClientData = {
120
+ LID: infoMessage.lid,
121
+ TIME_STAMP: infoMessage.timestamp,
122
+ OBJECT_STATUS: infoMessage.objectStatus,
123
+ SYNC_STATUS: infoMessage.syncStatus,
124
+ TYPE: infoMessage.type,
125
+ SUBTYPE: infoMessage.subtype,
126
+ CATEGORY: infoMessage.category,
127
+ MESSAGE: infoMessage.message,
128
+ BE_NAME: infoMessage.bename,
129
+ BE_LID: infoMessage.belid,
130
+ MESSAGE_BLOB: infoMessage.messagedetails
131
+ };
132
+ updatedInfoMessages.push(infoMessageClientData);
133
+ }
134
+ if (!isForeground) {
135
+ NotificationListenerHelper.postDataSenderNotification(updatedInfoMessages, NotificationListnerType.infoMessage);
136
+ }
137
+ this.updateInfoMessageCategoryInHeader(isForeground, entityName, lid, infoMsgCategory);
138
+ }
139
+ delete responseData[ServiceConstants.KeyInfoMessage];
140
+ } else {
141
+ this.updateInfoMessageCategoryInHeader(isForeground, entityName, lid, "");
142
+ }
143
+
144
+ if (isInfoMessageFailure || isInfoMessageFailureAndProcess) {
145
+ if (requestType === RequestType.RQST) {
146
+ Logger.logError(this.sourceClass, "handleResponseData", `Info Message Failure. Marking header sync status to error. Response Data: ${JSON.stringify(responseData)}`);
147
+ const errorString =
148
+ `Info Message Failure. Marking header sync status to error. BE name: ${entityName}. LID: ${lid}`;
149
+ await this.updateErrorStatusInHeaderAndCreateInfoMessage(isForeground,
150
+ errorString, entityName, lid, infoMsgCategory);
151
+ }
152
+ if (!isForeground) {
153
+ // TODO: Post Notification to the app
154
+ }
155
+ if (!isInfoMessageFailureAndProcess) {
156
+ return;
157
+ }
158
+ }
159
+
160
+ if (autoSave && Object.keys(responseData).length > 0) {
161
+
162
+ if (requestType === RequestType.RQST) {
163
+ const structureMeta = structureMetas.find(
164
+ (element) => element.structureName === entityName
165
+ );
166
+ if (!structureMeta) {
167
+ const msgString =
168
+ "Entity definition is not available in metadata.json";
169
+ Logger.logError(this.sourceClass, "handleResponseData", msgString);
170
+ throw new Error(msgString);
171
+ }
172
+ const hasAtleastOneBe = await this.checkAtleastOneBeAvailable(
173
+ entityName, responseData, structureMeta
174
+ );
175
+ if (!hasAtleastOneBe) {
176
+ const msgString =
177
+ "For Request type RQST, Response should contain at least one Input Entity. But the response data does not contain Input Entity.";
178
+ Logger.logError(this.sourceClass, "handleResponseData", msgString);
179
+ throw new Error(msgString);
180
+ }
181
+ }
182
+
183
+ // Handle Metadata Node
184
+ let metaDataDeleteFlag = false;
185
+ let pullMessageMetaDataBENames: any[] = [];
186
+
187
+ if (requestType === RequestType.PULLD) {
188
+ if (Object.keys(metaData).length > 0) {
189
+ const deletionRequiredFlag = metaData[ServiceConstants.KeyMetadataDelete];
190
+ if (deletionRequiredFlag != null &&
191
+ deletionRequiredFlag.toLowerCase() === "true") {
192
+ metaDataDeleteFlag = true;
193
+ }
194
+ if (Object.keys(metaData).length > 0) {
195
+ pullMessageMetaDataBENames = metaData[ServiceConstants.KeyBeName];
196
+ }
197
+ }
198
+ }
199
+ if (metaDataDeleteFlag && requestType === RequestType.PULLD) {
200
+ try {
201
+ try {
202
+ await DatabaseManager.getInstance().beginTransaction(DatabaseType.FrameworkDb);
203
+ await DatabaseManager.getInstance().beginTransaction(DatabaseType.AppDb);
204
+ } catch (e) {
205
+ Logger.logError(this.sourceClass, "handleResponseData", `RequestType.PULLD: Error while starting transaction. Error : ${JSON.stringify(e)}.`);
206
+ return;
207
+ }
208
+ Logger.logInfo(this.sourceClass, "handleResponseData", "Inside transaction start.");
209
+ for (const beName of pullMessageMetaDataBENames) {
210
+ Logger.logInfo(this.sourceClass, "handleResponseData", `Deleting BE: ${beName}.`);
211
+ const currentBeMeta = beMetas.find((element) => element.beName === beName);
212
+ if (!currentBeMeta) {
213
+ Logger.logError(this.sourceClass, "handleResponseData", `There was an error while trying to get Business Entity Meta for BE: ${beName}`);
214
+ }
215
+ const currentHeaderStructureMeta = structureMetas.find((element) =>
216
+ element.beName === beName && element.isHeader === "1"
217
+ );
218
+ if (!currentHeaderStructureMeta) {
219
+ Logger.logError(this.sourceClass, "handleResponseData", `There was an error while trying to get Header Structure Meta for BE: ${beName}`);
220
+ }
221
+
222
+ const databaseManager = DatabaseManager.getInstance();
223
+ if (currentBeMeta!.conflictRules === FieldConstants.ConflictModeServerWins) {
224
+ Logger.logInfo(this.sourceClass, "handleResponseData", `Deleting the contents of ${currentHeaderStructureMeta!.structureName} table regardless of the state of the header.`);
225
+ const childTables = structureMetas
226
+ .filter((itemStruct) =>
227
+ itemStruct.beName === currentHeaderStructureMeta.beName &&
228
+ itemStruct.structureName !== currentHeaderStructureMeta.structureName
229
+ )
230
+ .map((e) => e.structureName);
231
+ try {
232
+ Logger.logInfo(this.sourceClass, "handleResponseData", "Before Deleting child tables.");
233
+ for (const childName of childTables) {
234
+ Logger.logInfo(this.sourceClass, "handleResponseData", `Deleting child table ${childName}.`);
235
+ await databaseManager.delete(DatabaseType.AppDb, childName);
236
+ Logger.logInfo(this.sourceClass, "handleResponseData", `Child table ${childName} deleted.`);
237
+ }
238
+ await databaseManager.delete(DatabaseType.AppDb, currentHeaderStructureMeta.structureName);
239
+ Logger.logInfo(this.sourceClass, "handleResponseData", `Header table ${currentHeaderStructureMeta.structureName} deleted.`);
240
+ } catch (e) {
241
+ Logger.logError(this.sourceClass, "handleResponseData", `Could not cleanup database for ${currentHeaderStructureMeta.structureName}.`);
242
+ }
243
+ } else {
244
+ Logger.logInfo(this.sourceClass, "handleResponseData", `Deleting the contents of ${currentHeaderStructureMeta!.structureName} table whose header is in GLOBAL state.`);
245
+ const whereClause = `${FieldConstants.FieldObjectStatus} = ${ObjectStatus.global}`
246
+ await databaseManager.delete(DatabaseType.AppDb, currentHeaderStructureMeta.structureName, whereClause);
247
+ }
248
+ }
249
+ try {
250
+ await DatabaseManager.getInstance().endTransaction(DatabaseType.AppDb);
251
+ await DatabaseManager.getInstance().endTransaction(DatabaseType.FrameworkDb);
252
+ } catch (e) {
253
+ Logger.logError(this.sourceClass, "handleResponseData", `Error while ending transaction. Error : ${JSON.stringify(e)}.`);
254
+ }
255
+ } catch (e) {
256
+ try {
257
+ await DatabaseManager.getInstance().rollbackTransaction(DatabaseType.AppDb);
258
+ await DatabaseManager.getInstance().rollbackTransaction(DatabaseType.FrameworkDb);
259
+ } catch (e) {
260
+ Logger.logError(this.sourceClass, "handleResponseData", `Error while rolling back transaction. Error : ${JSON.stringify(e)}.`);
261
+ }
262
+ Logger.logError(this.sourceClass, "handleResponseData", `Error while deleting BE data. Error : ${JSON.stringify(e)}.`);
263
+ }
264
+ }
265
+ const conflictBEs: any[] = [];
266
+ const databaseManager = DatabaseManager.getInstance();
267
+ const responseDataKeys = Object.keys(responseData);
268
+ let headerInDB: any | null = null;
269
+ try {
270
+ try {
271
+ await DatabaseManager.getInstance().beginTransaction(DatabaseType.FrameworkDb);
272
+ await DatabaseManager.getInstance().beginTransaction(DatabaseType.AppDb);
273
+ } catch (e) {
274
+ Logger.logError(this.sourceClass, "handleResponseData", `Error while starting transaction. Error : ${JSON.stringify(e)}.`);
275
+ return;
276
+ }
277
+ for (const key of responseDataKeys) {
278
+ const value = responseData[key];
279
+ const currentBEMeta = beMetas.find((element) => element.beName === key);
280
+ Logger.logInfo(this.sourceClass, "handleResponseData", `Processing BE META ${currentBEMeta}`);
281
+ if (currentBEMeta) {
282
+ const currentHeaderStructureMeta = structureMetas.find((element) =>
283
+ element.beName === key && element.isHeader === "1"
284
+ );
285
+ if (currentHeaderStructureMeta) {
286
+ Logger.logInfo(this.sourceClass, "handleResponseData", `Processing HEADER ${currentHeaderStructureMeta.structureName}`);
287
+ const beValues = value;
288
+ let index = 0;
289
+ for (const element of beValues) {
290
+ const beObject = element;
291
+ const headerObject = beObject[currentHeaderStructureMeta.structureName];
292
+
293
+ const actionType = beObject[ServiceConstants.KeyActionAttribute];
294
+ delete beObject[currentHeaderStructureMeta.structureName];
295
+ delete beObject[ServiceConstants.KeyActionAttribute];
296
+
297
+ if (!headerObject) {
298
+ Logger.logError(this.sourceClass, "handleResponseData", `Error while getting Header for BE name: ${key}. Continuing with next BE.`);
299
+ continue;
300
+ }
301
+ let headerInDatabase: any | null = null;
302
+
303
+ if (requestType !== RequestType.PULLD) {
304
+ try {
305
+ let currentHeaderLid = lid;
306
+ if (requestType === RequestType.RQST &&
307
+ entityName !== currentHeaderStructureMeta.structureName) {
308
+ currentHeaderLid = "";
309
+ }
310
+ headerInDatabase = await this.checkDuplicateBe(currentHeaderStructureMeta.structureName, fieldMetas, headerObject, requestType!, currentHeaderLid);
311
+ headerInDB = headerInDatabase;
312
+ } catch (e) {
313
+ Logger.logError(this.sourceClass, "handleResponseData", `Error while checking for duplicate BE name: ${key}. Error : ${JSON.stringify(e)}.`);
314
+ }
315
+ }
316
+
317
+ if (requestType !== RequestType.PULL &&
318
+ requestType !== RequestType.PULLD) {
319
+ if (headerInDatabase) {
320
+ if (actionType === ServiceConstants.ActionTypeD) {
321
+ const whereClause = `${FieldConstants.FieldLid} = ${headerInDatabase[FieldConstants.FieldLid]}`
322
+ await databaseManager.delete(DatabaseType.AppDb, currentHeaderStructureMeta.structureName, whereClause);
323
+ // TODO: Post Notification to the app
324
+ continue;
325
+ } else {
326
+ headerObject[FieldConstants.FieldLid] = headerInDatabase[FieldConstants.FieldLid];
327
+ }
328
+ try {
329
+ const whereClause = `belid = '${headerInDatabase[FieldConstants.FieldLid]}'`
330
+ await databaseManager.delete(DatabaseType.FrameworkDb, "InfoMessage", whereClause);
331
+ } catch (e) {
332
+ Logger.logError(this.sourceClass, "handleResponseData", `Error while deleting info message. Error : ${JSON.stringify(e)}.`);
333
+ }
334
+ }
335
+ }
336
+ if (actionType !== ServiceConstants.ActionTypeD) {
337
+ if (!headerInDatabase) {
338
+ if (!headerObject[FieldConstants.FieldLid]) {
339
+ headerObject[FieldConstants.FieldLid] = FrameworkHelper.getUUID();
340
+ }
341
+ processedHeaders.push({
342
+ [EventFieldBeName]: currentHeaderStructureMeta.structureName,
343
+ [EventFieldBeLid]: headerObject[FieldConstants.FieldLid],
344
+ [EventFieldActionType]: actionType,
345
+ [EventFieldRequestType]: requestType,
346
+ [EventFieldHeaderDataStructure]: headerObject
347
+ });
348
+ Logger.logInfo(this.sourceClass, "handleResponseData", `Inserting BE DATA : ${currentHeaderStructureMeta.structureName} LID : ${headerObject[FieldConstants.FieldLid]} ${index.toString()}`);
349
+ index++;
350
+ await this.insertIncomingBeData(isForeground, currentHeaderStructureMeta.structureName, headerObject, beObject);
351
+ } else {
352
+ Logger.logInfo(this.sourceClass, "handleResponseData", `Reconciling BE DATA : ${currentHeaderStructureMeta.structureName} LID : ${headerObject[FieldConstants.FieldLid]} ${index.toString()}`);
353
+ index++;
354
+ processedHeaders.push({
355
+ [EventFieldBeName]: currentHeaderStructureMeta.structureName,
356
+ [EventFieldBeLid]: headerObject[FieldConstants.FieldLid],
357
+ [EventFieldActionType]: actionType,
358
+ [EventFieldRequestType]: requestType,
359
+ [EventFieldHeaderDataStructure]: headerInDatabase
360
+ });
361
+ if (requestType === RequestType.RQST &&
362
+ entityName === currentHeaderStructureMeta.structureName) {
363
+ const requestResponseReconciler = new Reconciler(currentHeaderStructureMeta.structureName,
364
+ headerInDatabase,
365
+ headerObject,
366
+ beObject,
367
+ currentBEMeta.conflictRules,
368
+ isForeground,
369
+ ReconcilerType.RequestResponse
370
+ );
371
+ const status = await requestResponseReconciler.reconcile(
372
+ structureMetas,
373
+ fieldMetas,
374
+ requestType!,
375
+ headerInDatabase[FieldConstants.FieldLid]
376
+ );
377
+ if (requestResponseReconciler.getConflictBe().length > 0) {
378
+ conflictBEs.push(
379
+ requestResponseReconciler.getConflictBe()
380
+ );
381
+ }
382
+ if (!status) {
383
+ Logger.logError(this.sourceClass, "handleResponseData", `Reconciliation failed (RequestResponseReconciler). Rolling back db operation. Updating header sync status to error. BE Name: ${entityName}, headerInDatabase: ${JSON.stringify(headerInDatabase)}`);
384
+ const errorString =
385
+ `Reconciliation failed (RequestResponseReconciler). Rolling back db operation. Updating header sync status to error. BE Name: ${entityName}, headerInDatabase(lid): ${headerInDatabase[FieldConstants.FieldLid]}`;
386
+ throw new Error(errorString);
387
+ }
388
+ } else {
389
+ const pullPushQueryReconciler = new Reconciler(
390
+ currentHeaderStructureMeta.structureName,
391
+ headerInDatabase,
392
+ headerObject,
393
+ beObject,
394
+ currentBEMeta.conflictRules,
395
+ isForeground,
396
+ ReconcilerType.PullPushQuery
397
+ );
398
+ const status = await pullPushQueryReconciler.reconcile(
399
+ structureMetas,
400
+ fieldMetas,
401
+ requestType!,
402
+ headerInDatabase[FieldConstants.FieldLid]
403
+ );
404
+ if (!status) {
405
+ Logger.logError(this.sourceClass, "handleResponseData", `Reconciliation failed (PullPushQueryReconciler). Rolling back db operation. Updating header sync status to error. BE Name: ${entityName}, headerInDatabase: ${JSON.stringify(headerInDatabase)}`);
406
+ const errorString =
407
+ `Reconciliation failed (PullPushQueryReconciler). Rolling back db operation. Updating header sync status to error. BE Name: ${entityName}, headerInDatabase(lid): ${headerInDatabase[FieldConstants.FieldLid]}`;
408
+ throw new Error(errorString);
409
+ }
410
+ }
411
+ }
412
+ }
413
+ }
414
+ }
415
+ } else {
416
+ Logger.logInfo(this.sourceClass, "handleResponseData", `BE which is not defined in metadata.json: ${JSON.stringify(responseData)}`);
417
+ // processedHeaders.push(responseData);
418
+ }
419
+ }
420
+ try {
421
+ await DatabaseManager.getInstance().endTransaction(DatabaseType.AppDb);
422
+ await DatabaseManager.getInstance().endTransaction(DatabaseType.FrameworkDb);
423
+ } catch (e) {
424
+ Logger.logError(this.sourceClass, "handleResponseData", `Error while ending transaction. Error : ${JSON.stringify(e)}.`);
425
+ }
426
+ } catch (e) {
427
+ try {
428
+ await DatabaseManager.getInstance().rollbackTransaction(DatabaseType.AppDb);
429
+ await DatabaseManager.getInstance().rollbackTransaction(DatabaseType.FrameworkDb);
430
+ } catch (e) {
431
+ Logger.logError(this.sourceClass, "handleResponseData", `Error while rolling back transaction. Error : ${JSON.stringify(e)}.`);
432
+ }
433
+ let headerLid = lid;
434
+ if (headerInDB != null) {
435
+ headerLid = headerInDB[FieldConstants.FieldLid] ?? "";
436
+ }
437
+ const infoMessageData = await this.updateErrorStatusInHeaderAndCreateInfoMessage(
438
+ isForeground,
439
+ JSON.stringify(e),
440
+ entityName,
441
+ headerLid,
442
+ FieldConstants.InfoMessageFailure
443
+ );
444
+ await DatabaseManager.getInstance().insert(DatabaseType.FrameworkDb, "InfoMessage", infoMessageData, true);
445
+ }
446
+ // TODO: set conflict handler
447
+ // const conflictHandler = SyncEngine.getConflictHandler();
448
+ // if (conflictHandler != null) {
449
+ // conflictHandler.handleConflict(conflictBEs);
450
+ // }
451
+ }
452
+ if (processedHeaders.length > 0 && !isForeground) {
453
+ NotificationListenerHelper.postDataSenderNotification(processedHeaders, NotificationListnerType.data_changed);
454
+ }
455
+ } catch (e) {
456
+ Logger.logError(this.sourceClass, "handleResponseData", `Common catch block. Error: ${JSON.stringify(e)}`);
457
+ }
458
+ }
459
+ }
460
+
461
+ private static getRank(infoMsgCategory: string): number {
462
+ switch (infoMsgCategory.toUpperCase()) {
463
+ case FieldConstants.InfoMessageFailure:
464
+ case FieldConstants.InfoMessageFailureAndProcess:
465
+ case FieldConstants.InfoMessageMsgWithheld:
466
+ return 1;
467
+ case FieldConstants.InfoMessageWarning:
468
+ return 2;
469
+ case FieldConstants.InfoMessageInfo:
470
+ return 3;
471
+ case FieldConstants.InfoMessageSuccess:
472
+ return 4;
473
+ default:
474
+ return 5;
475
+ }
476
+ }
477
+
478
+ private static async checkAtleastOneBeAvailable(entityName: string, responseData: any, structureMeta: StructureMeta): Promise<boolean> {
479
+ if (responseData[structureMeta.beName] != null) {
480
+ let returnValue = false;
481
+ const beValues = responseData[structureMeta.beName];
482
+ for (const data of beValues) {
483
+ if (data[entityName] != null) {
484
+ returnValue = true;
485
+ break;
486
+ }
487
+ }
488
+ return returnValue;
489
+ }
490
+ return false;
491
+ }
492
+
493
+ static async checkDuplicateBe(tableName: string, fieldMetas: FieldMeta[], dataObj: any, requestType: RequestType, lid: string): Promise<any | null> {
494
+ if (fieldMetas.length === 0) {
495
+ return null;
496
+ }
497
+ let whereClaues = "";
498
+ if (requestType !== RequestType.RQST) {
499
+ whereClaues = ServerResponseHandler.getWhereClauseBasedOnGidFields(tableName, fieldMetas, dataObj);
500
+ } else {
501
+ if (tableName.endsWith("_HEADER") && lid.length > 0) {
502
+ whereClaues = `${FieldConstants.FieldLid} = '${lid}'`;
503
+ } else {
504
+ whereClaues = ServerResponseHandler.getWhereClauseBasedOnGidFields(tableName, fieldMetas, dataObj);
505
+ if (lid.length > 0) {
506
+ whereClaues += whereClaues.length === 0 ? "" : " AND ";
507
+ whereClaues += `${FieldConstants.FieldFid} = '${lid}'`;
508
+ }
509
+ }
510
+ }
511
+
512
+ const isPresent = await ServerResponseHandler.checkIfEntityPresentInDB(tableName, whereClaues);
513
+ if (isPresent) {
514
+ const databaseManager = DatabaseManager.getInstance();
515
+ const result = await databaseManager.select(DatabaseType.AppDb, tableName, whereClaues);
516
+ if (result.length > 0) {
517
+ return result[0];
518
+ }
519
+ }
520
+ return null;
521
+ }
522
+
523
+ private static async checkIfEntityPresentInDB(tableName: string, whereClause: string): Promise<boolean> {
524
+ const result = await DatabaseManager.getInstance().count(DatabaseType.AppDb, tableName, whereClause);
525
+ return result > 0;
526
+ }
527
+
528
+ private static getWhereClauseBasedOnGidFields(tableName: string, fieldMetas: FieldMeta[], dataObj: any): string {
529
+ let whereClaues = "";
530
+ var gidFields: string[] = [];
531
+ try {
532
+ gidFields = fieldMetas
533
+ .filter((fMeta) => fMeta.structureName === tableName && fMeta.isGid === "1")
534
+ .map((e) => e.fieldName);
535
+ } catch (e) {
536
+ Logger.logError(
537
+ "ServerResponseHandler",
538
+ "_getWhereClauseBasedOnGidFields",
539
+ `Error while getting GID fields. Error: ${e}`);
540
+ }
541
+ for (const element of gidFields) {
542
+ let val = dataObj[element];
543
+ if (val != null) {
544
+ if (typeof val === 'string') {
545
+ val = DatabaseManager.getInstance().escapeSqlString(val);
546
+ }
547
+ whereClaues += whereClaues.length === 0 ? "" : " AND ";
548
+ whereClaues += `${element} = '${val}'`;
549
+ }
550
+ }
551
+ return whereClaues;
552
+ }
553
+
554
+ private static async insertIncomingBeData(isForeground: boolean, entityName: string, incomingHeader: any, incomingItems: any) {
555
+ incomingHeader[FieldConstants.FieldTimestamp] = Date.now();
556
+ incomingHeader[FieldConstants.FieldObjectStatus] = ObjectStatus.global;
557
+ incomingHeader[FieldConstants.FieldSyncStatus] = SyncStatus.none;
558
+ try {
559
+ await DatabaseManager.getInstance().insert(DatabaseType.AppDb, entityName, incomingHeader, true);
560
+ } catch (e) {
561
+ const errorString =
562
+ `Error while inserting incoming be - ${entityName}. Error: ${JSON.stringify(e)}`;
563
+ Logger.logError(this.sourceClass, "insertIncomingBeData", errorString);
564
+ const infoMessageData = await this.updateErrorStatusInHeaderAndCreateInfoMessage(
565
+ isForeground,
566
+ errorString,
567
+ entityName,
568
+ incomingHeader[FieldConstants.FieldLid] ?? "",
569
+ FieldConstants.InfoMessageFailure
570
+ );
571
+ await DatabaseManager.getInstance().insert(DatabaseType.FrameworkDb, "InfoMessage", infoMessageData, true);
572
+ return;
573
+ }
574
+ const keys = Object.keys(incomingItems);
575
+ for (const key of keys) {
576
+ const itemsArray = incomingItems[key];
577
+ let index = 0;
578
+ for (const value of itemsArray) {
579
+ if (!value[FieldConstants.FieldLid]) {
580
+ value[FieldConstants.FieldLid] = FrameworkHelper.getUUID();
581
+ }
582
+ value[FieldConstants.FieldFid] = incomingHeader[FieldConstants.FieldLid];
583
+ value[FieldConstants.FieldTimestamp] = Date.now();
584
+ value[FieldConstants.FieldObjectStatus] = ObjectStatus.global;
585
+ value[FieldConstants.FieldSyncStatus] = SyncStatus.none;
586
+ Logger.logInfo(this.sourceClass, "insertIncomingBeData", `Inserting BE ITEM : ${key} LID : ${value[FieldConstants.FieldLid]} ${index.toString()}`);
587
+ try {
588
+ await DatabaseManager.getInstance().insert(DatabaseType.AppDb, key, value, false);
589
+ if (key.endsWith(ServiceConstants.AttachmentBE)) {
590
+ await AttachmentQHelper.checkAttachmentAndQueueForAutoDownload(key, value);
591
+ }
592
+ } catch (e) {
593
+ const errorString =
594
+ `Error while inserting incoming items. ERROR: ${JSON.stringify(e)}`;
595
+ Logger.logError(this.sourceClass, "insertIncomingBeData", errorString);
596
+ const infoMessageData = await this.updateErrorStatusInHeaderAndCreateInfoMessage(
597
+ isForeground,
598
+
599
+ errorString,
600
+ entityName,
601
+ incomingHeader[FieldConstants.FieldLid] ?? "",
602
+ FieldConstants.InfoMessageFailure
603
+ );
604
+ await DatabaseManager.getInstance().insert(DatabaseType.FrameworkDb, "InfoMessage", infoMessageData, true);
605
+ return;
606
+ }
607
+ index++;
608
+ }
609
+ }
610
+ }
611
+
612
+ static async updateErrorStatusInHeaderAndCreateInfoMessage(isForeground: boolean, errorString: string, entityName: string, headerLid: string, infoMsgCategory: string): Promise<any> {
613
+ const infoMessage = {
614
+ lid: FrameworkHelper.getUUID(),
615
+ timestamp: Date.now(),
616
+ objectStatus: ObjectStatus.global,
617
+ syncStatus: SyncStatus.none,
618
+ type: "",
619
+ subtype: "",
620
+ category: FieldConstants.InfoMessageFailure,
621
+ message: errorString,
622
+ bename: entityName,
623
+ belid: headerLid,
624
+ messagedetails: new Uint8Array(0)
625
+ };
626
+ if (headerLid.length === 0) {
627
+ return infoMessage;
628
+ }
629
+ try {
630
+ await DatabaseManager.getInstance().update(DatabaseType.AppDb, entityName, {
631
+ [FieldConstants.FieldSyncStatus]: SyncStatus.error,
632
+ [FieldConstants.FieldInfoMsgCat]: infoMsgCategory
633
+ }, `${FieldConstants.FieldLid} = '${headerLid}'`, true); // isFromApp is true because it just need to update the data and should not set the missing fields to null.
634
+ } catch (e) {
635
+ Logger.logError(this.sourceClass, "updateErrorStatusInHeaderAndCreateInfoMessage", `Error while updating header (${entityName}) status into database. Error: ${JSON.stringify(e)}`);
636
+ }
637
+
638
+ const allStructureMetas = await DatabaseManager.getInstance().select(DatabaseType.FrameworkDb, "StructureMeta");
639
+ const headerStructureMeta = allStructureMetas.find((element) => element.structureName === entityName);
640
+
641
+ if (!headerStructureMeta) {
642
+ Logger.logError(this.sourceClass, "updateErrorStatusInHeaderAndCreateInfoMessage", `Error while getting header structure meta. Error: Structure meta for ${entityName} is not found.`);
643
+ return infoMessage;
644
+ }
645
+
646
+ try {
647
+ const childStructureMetas = allStructureMetas.filter((element) => element.beName === headerStructureMeta.beName && element.isHeader !== "1");
648
+ for (const childStructureMeta of childStructureMetas) {
649
+ try {
650
+ await DatabaseManager.getInstance().update(DatabaseType.AppDb, childStructureMeta.structureName, {
651
+ [FieldConstants.FieldSyncStatus]: SyncStatus.none
652
+ }, `${FieldConstants.FieldFid} = '${headerLid}'`, true); // isFromApp is true because it just need to update the data and should not set the missing fields to null.
653
+ } catch (e) {
654
+ Logger.logError(this.sourceClass, "updateErrorStatusInHeaderAndCreateInfoMessage", `Error while Updating Children Data Structure : ${childStructureMeta.structureName}. Error: ${JSON.stringify(e)}`);
655
+ }
656
+ }
657
+ } catch (e) {
658
+ Logger.logError(this.sourceClass, "updateErrorStatusInHeaderAndCreateInfoMessage", `Error while Fetching Children For Data Structure : ${entityName}. Error: ${JSON.stringify(e)}`);
659
+ }
660
+ return infoMessage;
661
+ }
662
+
663
+ private static async updateInfoMessageCategoryInHeader(isForeground: boolean, entityName: string, headerLid: string, infoMsgCategory: string) {
664
+ if (!entityName || entityName.length === 0 || !headerLid || headerLid.length === 0) {
665
+ return;
666
+ }
667
+ try {
668
+ await DatabaseManager.getInstance().update(DatabaseType.AppDb, entityName, {
669
+ [FieldConstants.FieldInfoMsgCat]: infoMsgCategory
670
+ }, `${FieldConstants.FieldLid} = '${headerLid}'`, true); // isFromApp is true because it just need to update the data and should not set the missing fields to null.
671
+ } catch (e) {
672
+ Logger.logError(this.sourceClass, "updateInfoMessageCategoryInHeader", `Error while updating header (${entityName}) Info Message Category into database. Error: ${JSON.stringify(e)}`);
673
+ }
674
+ }
675
+ }
676
+
677
+ export default ServerResponseHandler;