@po-ui/ng-sync 5.22.3 → 6.2.0

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 (145) hide show
  1. package/README.md +22 -22
  2. package/{esm2015/lib/index.js → esm2020/lib/index.mjs} +15 -15
  3. package/{esm2015/lib/models/index.js → esm2020/lib/models/index.mjs} +6 -6
  4. package/{esm2015/lib/models/po-data-message.model.js → esm2020/lib/models/po-data-message.model.mjs} +57 -57
  5. package/esm2020/lib/models/po-data-transform.model.mjs +22 -0
  6. package/esm2020/lib/models/po-entity/po-entity.model.mjs +214 -0
  7. package/{esm2015/lib/models/po-event-sourcing-error-response.model.js → esm2020/lib/models/po-event-sourcing-error-response.model.mjs} +17 -17
  8. package/{esm2015/lib/models/po-network-status.model.js → esm2020/lib/models/po-network-status.model.mjs} +44 -44
  9. package/{esm2015/lib/models/po-network-type.enum.js → esm2020/lib/models/po-network-type.enum.mjs} +30 -30
  10. package/esm2020/lib/models/po-query-builder/po-query-builder.model.mjs +238 -0
  11. package/{esm2015/lib/models/po-request-type.enum.js → esm2020/lib/models/po-request-type.enum.mjs} +16 -16
  12. package/esm2020/lib/po-sync.module.mjs +45 -0
  13. package/{esm2015/lib/services/po-event-sourcing/enums/po-event-sourcing-operation.enum.js → esm2020/lib/services/po-event-sourcing/enums/po-event-sourcing-operation.enum.mjs} +17 -17
  14. package/{esm2015/lib/services/po-event-sourcing/index.js → esm2020/lib/services/po-event-sourcing/index.mjs} +4 -4
  15. package/esm2020/lib/services/po-event-sourcing/interfaces/po-event-sourcing-item.interface.mjs +2 -0
  16. package/esm2020/lib/services/po-event-sourcing/interfaces/po-event-sourcing-summary-item.interface.mjs +2 -0
  17. package/esm2020/lib/services/po-event-sourcing/po-event-sourcing.service.mjs +372 -0
  18. package/{esm2015/lib/services/po-http-client/interfaces/po-http-header-option.interface.js → esm2020/lib/services/po-http-client/interfaces/po-http-header-option.interface.mjs} +11 -11
  19. package/esm2020/lib/services/po-http-client/interfaces/po-http-request-data.interface.mjs +2 -0
  20. package/esm2020/lib/services/po-http-client/interfaces/po-response-api.interface.mjs +2 -0
  21. package/esm2020/lib/services/po-http-client/po-http-client.service.mjs +148 -0
  22. package/{esm2015/lib/services/po-http-client/po-http-request-type.enum.js → esm2020/lib/services/po-http-client/po-http-request-type.enum.mjs} +25 -25
  23. package/esm2020/lib/services/po-network/po-network.service.mjs +58 -0
  24. package/{esm2015/lib/services/po-schema/index.js → esm2020/lib/services/po-schema/index.mjs} +4 -4
  25. package/esm2020/lib/services/po-schema/po-schema-definition/po-schema-definition.service.mjs +77 -0
  26. package/{esm2015/lib/services/po-schema/po-schema-util/po-schema-util.model.js → esm2020/lib/services/po-schema/po-schema-util/po-schema-util.model.mjs} +124 -124
  27. package/esm2020/lib/services/po-schema/po-schema.service.mjs +174 -0
  28. package/esm2020/lib/services/po-sync/interfaces/po-sync-config.interface.mjs +2 -0
  29. package/esm2020/lib/services/po-sync/interfaces/po-sync-field-options.interface.mjs +2 -0
  30. package/esm2020/lib/services/po-sync/interfaces/po-sync-response.interface.mjs +2 -0
  31. package/esm2020/lib/services/po-sync/interfaces/po-sync-schema.interface.mjs +2 -0
  32. package/esm2020/lib/services/po-sync/po-sync.service.mjs +325 -0
  33. package/{esm2015/lib/utils/utils.js → esm2020/lib/utils/utils.mjs} +63 -63
  34. package/esm2020/po-ui-ng-sync.mjs +5 -0
  35. package/{esm2015/public-api.js → esm2020/public-api.mjs} +2 -2
  36. package/fesm2015/{po-ui-ng-sync.js → po-ui-ng-sync.mjs} +2074 -2058
  37. package/fesm2015/po-ui-ng-sync.mjs.map +1 -0
  38. package/fesm2020/po-ui-ng-sync.mjs +2018 -0
  39. package/fesm2020/po-ui-ng-sync.mjs.map +1 -0
  40. package/lib/index.d.ts +14 -14
  41. package/lib/models/index.d.ts +5 -5
  42. package/lib/models/po-data-message.model.d.ts +46 -46
  43. package/lib/models/po-data-transform.model.d.ts +52 -52
  44. package/lib/models/po-entity/po-entity.model.d.ts +122 -122
  45. package/lib/models/po-event-sourcing-error-response.model.d.ts +20 -20
  46. package/lib/models/po-network-status.model.d.ts +25 -25
  47. package/lib/models/po-network-type.enum.d.ts +28 -28
  48. package/lib/models/po-query-builder/po-query-builder.model.d.ts +126 -126
  49. package/lib/models/po-request-type.enum.d.ts +14 -14
  50. package/lib/po-sync.module.d.ts +12 -7
  51. package/lib/services/po-event-sourcing/enums/po-event-sourcing-operation.enum.d.ts +11 -11
  52. package/lib/services/po-event-sourcing/index.d.ts +3 -3
  53. package/lib/services/po-event-sourcing/interfaces/po-event-sourcing-item.interface.d.ts +26 -26
  54. package/lib/services/po-event-sourcing/interfaces/po-event-sourcing-summary-item.interface.d.ts +16 -16
  55. package/lib/services/po-event-sourcing/po-event-sourcing.service.d.ts +74 -71
  56. package/lib/services/po-http-client/interfaces/po-http-header-option.interface.d.ts +15 -15
  57. package/lib/services/po-http-client/interfaces/po-http-request-data.interface.d.ts +24 -24
  58. package/lib/services/po-http-client/interfaces/po-response-api.interface.d.ts +14 -14
  59. package/lib/services/po-http-client/po-http-client.service.d.ts +78 -75
  60. package/lib/services/po-http-client/po-http-request-type.enum.d.ts +23 -23
  61. package/lib/services/po-network/po-network.service.d.ts +36 -33
  62. package/lib/services/po-schema/index.d.ts +3 -3
  63. package/lib/services/po-schema/po-schema-definition/po-schema-definition.service.d.ts +51 -48
  64. package/lib/services/po-schema/po-schema-util/po-schema-util.model.d.ts +79 -79
  65. package/lib/services/po-schema/po-schema.service.d.ts +98 -95
  66. package/lib/services/po-sync/interfaces/po-sync-config.interface.d.ts +24 -24
  67. package/lib/services/po-sync/interfaces/po-sync-field-options.interface.d.ts +15 -15
  68. package/lib/services/po-sync/interfaces/po-sync-response.interface.d.ts +20 -20
  69. package/lib/services/po-sync/interfaces/po-sync-schema.interface.d.ts +37 -37
  70. package/lib/services/po-sync/po-sync.service.d.ts +162 -159
  71. package/lib/utils/utils.d.ts +36 -36
  72. package/package.json +30 -15
  73. package/po-ui-ng-sync-6.2.0.tgz +0 -0
  74. package/po-ui-ng-sync.d.ts +5 -8
  75. package/public-api.d.ts +1 -1
  76. package/schematics/README.md +169 -169
  77. package/schematics/collection.json +15 -15
  78. package/schematics/migrations.json +30 -25
  79. package/schematics/ng-add/index.d.ts +7 -7
  80. package/schematics/ng-add/index.js +33 -33
  81. package/schematics/ng-add/index.js.map +1 -1
  82. package/schematics/ng-add/index.spec.d.ts +1 -1
  83. package/schematics/ng-add/index.spec.js +62 -62
  84. package/schematics/ng-add/index.spec.js.map +1 -1
  85. package/schematics/ng-add/schema.json +7 -7
  86. package/schematics/ng-generate/schema/files/__path__/__name@dasherize__/__name@dasherize__.constants.ts.template +13 -13
  87. package/schematics/ng-generate/schema/index.d.ts +4 -4
  88. package/schematics/ng-generate/schema/index.js +12 -12
  89. package/schematics/ng-generate/schema/index.js.map +1 -1
  90. package/schematics/ng-generate/schema/index.spec.d.ts +1 -1
  91. package/schematics/ng-generate/schema/index.spec.js +44 -44
  92. package/schematics/ng-generate/schema/index.spec.js.map +1 -1
  93. package/schematics/ng-generate/schema/schema.d.ts +3 -3
  94. package/schematics/ng-generate/schema/schema.js +2 -2
  95. package/schematics/ng-generate/schema/schema.json +31 -31
  96. package/schematics/ng-update/v2/changes.d.ts +8 -8
  97. package/schematics/ng-update/v2/changes.js +20 -20
  98. package/schematics/ng-update/v2/index.d.ts +5 -5
  99. package/schematics/ng-update/v2/index.js +101 -101
  100. package/schematics/ng-update/v2/index.js.map +1 -1
  101. package/schematics/ng-update/v3/changes.d.ts +2 -2
  102. package/schematics/ng-update/v3/changes.js +14 -14
  103. package/schematics/ng-update/v3/index.d.ts +1 -1
  104. package/schematics/ng-update/v3/index.js +16 -16
  105. package/schematics/ng-update/v3/index.js.map +1 -1
  106. package/schematics/ng-update/v4/changes.d.ts +2 -2
  107. package/schematics/ng-update/v4/changes.js +14 -14
  108. package/schematics/ng-update/v4/index.d.ts +1 -1
  109. package/schematics/ng-update/v4/index.js +15 -15
  110. package/schematics/ng-update/v4/index.js.map +1 -1
  111. package/schematics/ng-update/v5/changes.d.ts +2 -2
  112. package/schematics/ng-update/v5/changes.js +13 -13
  113. package/schematics/ng-update/v5/index.d.ts +1 -1
  114. package/schematics/ng-update/v5/index.js +15 -15
  115. package/schematics/ng-update/v5/index.js.map +1 -1
  116. package/schematics/ng-update/v6/changes.d.ts +2 -0
  117. package/schematics/ng-update/v6/changes.js +14 -0
  118. package/schematics/ng-update/v6/changes.js.map +1 -0
  119. package/schematics/ng-update/v6/index.d.ts +1 -0
  120. package/schematics/ng-update/v6/index.js +16 -0
  121. package/schematics/ng-update/v6/index.js.map +1 -0
  122. package/bundles/po-ui-ng-sync.umd.js +0 -3002
  123. package/bundles/po-ui-ng-sync.umd.js.map +0 -1
  124. package/esm2015/lib/models/po-data-transform.model.js +0 -22
  125. package/esm2015/lib/models/po-entity/po-entity.model.js +0 -229
  126. package/esm2015/lib/models/po-query-builder/po-query-builder.model.js +0 -241
  127. package/esm2015/lib/po-sync.module.js +0 -31
  128. package/esm2015/lib/services/po-event-sourcing/interfaces/po-event-sourcing-item.interface.js +0 -2
  129. package/esm2015/lib/services/po-event-sourcing/interfaces/po-event-sourcing-summary-item.interface.js +0 -2
  130. package/esm2015/lib/services/po-event-sourcing/po-event-sourcing.service.js +0 -411
  131. package/esm2015/lib/services/po-http-client/interfaces/po-http-request-data.interface.js +0 -2
  132. package/esm2015/lib/services/po-http-client/interfaces/po-response-api.interface.js +0 -2
  133. package/esm2015/lib/services/po-http-client/po-http-client.service.js +0 -147
  134. package/esm2015/lib/services/po-network/po-network.service.js +0 -58
  135. package/esm2015/lib/services/po-schema/po-schema-definition/po-schema-definition.service.js +0 -80
  136. package/esm2015/lib/services/po-schema/po-schema.service.js +0 -198
  137. package/esm2015/lib/services/po-sync/interfaces/po-sync-config.interface.js +0 -2
  138. package/esm2015/lib/services/po-sync/interfaces/po-sync-field-options.interface.js +0 -2
  139. package/esm2015/lib/services/po-sync/interfaces/po-sync-response.interface.js +0 -2
  140. package/esm2015/lib/services/po-sync/interfaces/po-sync-schema.interface.js +0 -2
  141. package/esm2015/lib/services/po-sync/po-sync.service.js +0 -336
  142. package/esm2015/po-ui-ng-sync.js +0 -9
  143. package/fesm2015/po-ui-ng-sync.js.map +0 -1
  144. package/po-ui-ng-sync-5.22.3.tgz +0 -0
  145. package/po-ui-ng-sync.metadata.json +0 -1
@@ -0,0 +1,2018 @@
1
+ import * as i0 from '@angular/core';
2
+ import { Injectable, NgModule } from '@angular/core';
3
+ import * as HttpStatus from 'http-status-codes';
4
+ import { Subject, Observable, of, merge, fromEvent, forkJoin, timer } from 'rxjs';
5
+ import { map, expand, reduce, mapTo, mergeMap } from 'rxjs/operators';
6
+ import * as i1 from '@po-ui/ng-storage';
7
+ import * as i1$1 from '@angular/common/http';
8
+ import { HttpHeaders, HttpClientModule } from '@angular/common/http';
9
+ import * as i1$2 from '@ionic-native/network/ngx';
10
+ import { Network } from '@ionic-native/network/ngx';
11
+
12
+ /**
13
+ * @description
14
+ *
15
+ * Classe responsável por adaptar dados de APIs que não seguem
16
+ * o padrão de [API do PO UI](https://po-ui.io/guides/api).
17
+ *
18
+ * Essa classe deve ser estendida por uma classe que implemente cada um de seus métodos, adaptando os parâmetros de
19
+ * acordo com a API do *backend* existente que se deseja comunicar.
20
+ */
21
+ class PoDataTransform {
22
+ /**
23
+ * @docsPrivate
24
+ *
25
+ * Método responsável por receber e armazenar os dados retornados pela API para manipulação na classe `PoDataTransform`.
26
+ *
27
+ * @param {any} data Dados retornados pela API.
28
+ */
29
+ transform(data) {
30
+ this.data = data;
31
+ }
32
+ }
33
+
34
+ /**
35
+ * Retorna um *array* contendo os pares `[chave, valor]` do objeto.
36
+ *
37
+ * Semelhante ao método `Object.entries()` nativo do javascript.
38
+ *
39
+ * > Veja mais em: https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Global_Objects/Object/entries
40
+ *
41
+ * @param object Objeto que será extraído os pares [chave, valor].
42
+ */
43
+ const getObjectEntries = (object) => {
44
+ const objectName = Object.keys(object)[0];
45
+ const objectValue = object[objectName];
46
+ return [objectName, objectValue];
47
+ };
48
+ /**
49
+ * Recebe um objeto e valida se o seu valor é diferente de *undefined* ou *null*.
50
+ *
51
+ * @param {object} parameter Objeto contento o nome do parâmetro que está sendo validado
52
+ * e o seu valor.
53
+ */
54
+ const validateParameter = (parameter) => {
55
+ const [paramName, paramValue] = getObjectEntries(parameter);
56
+ if (paramValue === undefined || paramValue === null) {
57
+ throw new Error(`The ${paramName} parameter cannot be undefined or null`);
58
+ }
59
+ };
60
+ /**
61
+ * Recebe um objeto e valida se o seu valor é uma instância de *Array* e se não
62
+ * está vazio.
63
+ *
64
+ * @param value Objeto contento o nome da propriedade que está sendo validada e o seu valor.
65
+ */
66
+ const validateArray = (value) => {
67
+ validateParameter(value);
68
+ const [paramName, paramValue] = getObjectEntries(value);
69
+ if (!(paramValue instanceof Array)) {
70
+ throw new Error(`${paramName} is not an Array instance`);
71
+ }
72
+ if (!paramValue.length) {
73
+ throw new Error(`${paramName} cannot be empty array`);
74
+ }
75
+ };
76
+ /**
77
+ * Recebe um arquivo e converte para uma string base64
78
+ *
79
+ * @param Objeto do tipo file.
80
+ */
81
+ const toBase64 = (file) => new Promise((resolve, reject) => {
82
+ const reader = new FileReader();
83
+ reader.readAsDataURL(file);
84
+ reader.onload = () => resolve(reader.result);
85
+ /* istanbul ignore next */
86
+ reader.onerror = error => reject(error);
87
+ });
88
+ /**
89
+ * Recebe uma string base64 e converte para um arquivo
90
+ *
91
+ * @param string base64.
92
+ */
93
+ const toFile = (url, fileName, mimeType) => fetch(url)
94
+ .then(result => result.arrayBuffer())
95
+ .then(buffer => new File([buffer], fileName, { type: mimeType }));
96
+
97
+ /**
98
+ * @description
99
+ *
100
+ * Classe que define a resposta de erro para um item da fila de eventos que não foi enviado ao servidor por
101
+ * alguma inconsistência.
102
+ *
103
+ * > Pode ser utilizada em casos onde um item da fila é enviado ao servidor com inconsistência nos dados, por exemplo
104
+ * uma operação de *delete* ou *update* sem o `id` do objeto.
105
+ */
106
+ class PoEventSourcingErrorResponse {
107
+ /* istanbul ignore next */
108
+ constructor({ message, operation }) {
109
+ this.message = message;
110
+ this.operation = operation;
111
+ }
112
+ }
113
+
114
+ /**
115
+ * @docsPrivate
116
+ *
117
+ * Define as operações realizadas no sync.
118
+ */
119
+ var PoEventSourcingOperation;
120
+ (function (PoEventSourcingOperation) {
121
+ // Operação de exclusão.
122
+ PoEventSourcingOperation["Delete"] = "DELETE";
123
+ // Operação de requisição HTTP.
124
+ PoEventSourcingOperation["Http"] = "HTTP";
125
+ // Operação de inserção.
126
+ PoEventSourcingOperation["Insert"] = "INSERT";
127
+ // Operação de alteração.
128
+ PoEventSourcingOperation["Update"] = "UPDATE";
129
+ })(PoEventSourcingOperation || (PoEventSourcingOperation = {}));
130
+
131
+ /**
132
+ * @usedBy PoHttpClientService, PoHttpCommandResponse, PoSyncService
133
+ *
134
+ * @description
135
+ *
136
+ * Define o método de requisição HTTP.
137
+ */
138
+ var PoHttpRequestType;
139
+ (function (PoHttpRequestType) {
140
+ /** Método `delete` do protocolo HTTP. */
141
+ PoHttpRequestType["DELETE"] = "DELETE";
142
+ /** Método `get` do protocolo HTTP. */
143
+ PoHttpRequestType["GET"] = "GET";
144
+ /** Método `head` do protocolo HTTP. */
145
+ PoHttpRequestType["HEAD"] = "HEAD";
146
+ /** Método `options` do protocolo HTTP. */
147
+ PoHttpRequestType["OPTIONS"] = "OPTIONS";
148
+ /** Método `patch` do protocolo HTTP. */
149
+ PoHttpRequestType["PATCH"] = "PATCH";
150
+ /** Método `post` do protocolo HTTP. */
151
+ PoHttpRequestType["POST"] = "POST";
152
+ /** Método `put` do protocolo HTTP. */
153
+ PoHttpRequestType["PUT"] = "PUT";
154
+ })(PoHttpRequestType || (PoHttpRequestType = {}));
155
+
156
+ /**
157
+ * @docsPrivate
158
+ *
159
+ * @description
160
+ *
161
+ * Método de requisição HTTP.
162
+ */
163
+ var PoRequestType;
164
+ (function (PoRequestType) {
165
+ PoRequestType["GET"] = "get";
166
+ PoRequestType["DELETE"] = "delete";
167
+ PoRequestType["DIFF"] = "diff";
168
+ PoRequestType["PATCH"] = "patch";
169
+ PoRequestType["POST"] = "post";
170
+ })(PoRequestType || (PoRequestType = {}));
171
+
172
+ /**
173
+ * @docsPrivate
174
+ *
175
+ * @description
176
+ *
177
+ * Serviço utilitário para operações no PoSyncSchema.
178
+ */
179
+ class PoSchemaUtil {
180
+ /**
181
+ * Verica se existem campos locais no *schema* informado.
182
+ *
183
+ * @param {PoSyncSchema} schema **Schema* a ser processado.
184
+ *
185
+ * @returns {boolean} Valor do tipo *boolean* que indica se existem campos locais no *schema* informado.
186
+ */
187
+ static containsLocalFields(schema) {
188
+ if (schema.fields) {
189
+ return !!schema.fields.find(field => typeof field === 'object' && field.local);
190
+ }
191
+ }
192
+ /**
193
+ * Retorna o valor atual do `lastSync` para determinado *schema*.
194
+ *
195
+ * @param {Array<PoSyncSchema>} storageSchemas Lista de *schemas* a serem pesquisados.
196
+ * @param {string} schemaName Nome do *schema* que se deseja ler o lastSync.
197
+ *
198
+ * @returns {string} Retorna uma *string* com o valor da última sincronização.
199
+ */
200
+ static getLastSync(storageSchemas, schemaName) {
201
+ if (storageSchemas) {
202
+ const schemaFound = storageSchemas.find(schema => schema.name === schemaName);
203
+ return schemaFound && schemaFound.lastSync ? schemaFound.lastSync : PoSchemaUtil.defaultLastSync;
204
+ }
205
+ return PoSchemaUtil.defaultLastSync;
206
+ }
207
+ /**
208
+ * Retorna a lista de campos locais definidos no *schema*.
209
+ *
210
+ * @param {PoSyncSchema} schema **Schema* a ser processado.
211
+ */
212
+ static getLocalFieldNames(schema) {
213
+ if (schema.fields) {
214
+ return schema.fields.reduce((fieldsAccumulator, currentField) => {
215
+ if (typeof currentField === 'object' && currentField.local) {
216
+ fieldsAccumulator.push(currentField.name);
217
+ }
218
+ return fieldsAccumulator;
219
+ }, []);
220
+ }
221
+ }
222
+ /**
223
+ * Retorna a lista de campos não locais definidos no *schema*.
224
+ *
225
+ * @param {PoSyncSchema} schema **Schema* a ser processado.
226
+ */
227
+ static getNonLocalFieldNames(schema) {
228
+ if (schema.fields) {
229
+ return schema.fields.reduce((fieldsAccumulator, currentField) => {
230
+ if (typeof currentField === 'string' || !currentField.local) {
231
+ fieldsAccumulator.push(typeof currentField === 'string' ? currentField : currentField.name);
232
+ }
233
+ return fieldsAccumulator;
234
+ }, []);
235
+ }
236
+ }
237
+ /**
238
+ * Retorna o `id` referente ao registro do *schema* informado.
239
+ *
240
+ * @param {object} record Registro que será buscado o id.
241
+ * @param {PoSyncSchema} schema **Schema* a ser processado.
242
+ */
243
+ static getRecordId(record, schema) {
244
+ return record[schema.idField] || record[PoSchemaUtil.syncInternalIdFieldName];
245
+ }
246
+ /**
247
+ * Retorna a url correspondente do `PoSyncSchema` dependendo do tipo da requisição `PoRequestType`.
248
+ *
249
+ * @param {PoSyncSchema} schema **Schema* a ser processado.
250
+ * @param {PoRequestType} requestType Tipo da requisição.
251
+ */
252
+ static getUrl(schema, requestType) {
253
+ return schema[`${requestType}UrlApi`];
254
+ }
255
+ /**
256
+ * Compara se dois objetos são iguais baseado na lista de campos.
257
+ *
258
+ * @param {Array<string>} fields Lista de campos a serem considerados na comparação.
259
+ * @param {any} model1 Objeto 1 a ser comparado.
260
+ * @param {any} model2 Objeto 2 a ser comparado.
261
+ */
262
+ static isModelsEqual(fields, model1, model2) {
263
+ if (fields) {
264
+ return fields.every(field => JSON.stringify(model1[field]) === JSON.stringify(model2[field]));
265
+ }
266
+ }
267
+ /**
268
+ * Retorna uma lista com dois objetos referentes ao registro informado.
269
+ * O primeiro é o registro com os campos que vão para o servidor e o segundo é com os campos locais.
270
+ *
271
+ * @param {PoSyncSchema} schema **Schema* do registro.
272
+ * @param {object} record Registro que será realizada a separação dos campos locais e do servidor.
273
+ */
274
+ static separateSchemaFields(schema, record) {
275
+ const localFields = PoSchemaUtil.getLocalFieldNames(schema);
276
+ const localRecord = {};
277
+ const serverRecord = {};
278
+ Object.keys(record).forEach(field => {
279
+ if (localFields.includes(field)) {
280
+ localRecord[field] = record[field];
281
+ }
282
+ else {
283
+ serverRecord[field] = record[field];
284
+ }
285
+ });
286
+ return { serverRecord, localRecord };
287
+ }
288
+ }
289
+ /** Valor `default` para o campo `lastSync`. */
290
+ PoSchemaUtil.defaultLastSync = new Date(-8640000000000000).toISOString();
291
+ /** Nome da chave do identificador interno do sync. */
292
+ PoSchemaUtil.syncInternalIdFieldName = 'SyncInternalId';
293
+ /** Nome da chave no `storage` para os Schemas. */
294
+ PoSchemaUtil.syncSchemasName = 'SyncSchemas';
295
+
296
+ /**
297
+ * @docsPrivate
298
+ *
299
+ * @description
300
+ *
301
+ * Serviço que disponibiliza métodos que permite operar sobre as definições dos *schemas*.
302
+ */
303
+ class PoSchemaDefinitionService {
304
+ constructor(poStorage) {
305
+ this.poStorage = poStorage;
306
+ }
307
+ /**
308
+ * Destrói a chave do *storage* que contém as definições dos *schemas*.
309
+ *
310
+ * > Para que não venham ocorrer erros em ações que dependam das definições dos *schemas*,
311
+ * recomenda-se utilizar o método `prepare()` em seguida.
312
+ *
313
+ * @returns {Promise<void>} Promessa que é resolvida quando a chave referente as definições dos *schemas* for destruída.
314
+ */
315
+ destroy() {
316
+ return this.poStorage.remove(PoSchemaUtil.syncSchemasName);
317
+ }
318
+ /**
319
+ * Busca um *schema* a partir do nome informado.
320
+ *
321
+ * @param {string} schemaName Nome do *schema*.
322
+ * @returns {Promise<PoSyncSchema>} Promessa que é resolvida quando o *schema* for retornado.
323
+ */
324
+ get(schemaName) {
325
+ return this.poStorage.getItemByField(PoSchemaUtil.syncSchemasName, 'name', schemaName);
326
+ }
327
+ /**
328
+ * Retorna uma promessa com a lista dos *schemas* definidos.
329
+ *
330
+ * @returns {Promise<Array<PoSyncSchema>>} Promessa que é resolvida quando a lista dos *schemas* definidos for retornada.
331
+ */
332
+ getAll() {
333
+ return this.poStorage.get(PoSchemaUtil.syncSchemasName);
334
+ }
335
+ /**
336
+ * Salva uma lista de *schemas*.
337
+ *
338
+ * @param {Array<PoSyncSchema>} schemas Lista de schemas que serão salvos.
339
+ * @returns {Promise<Array<PoSyncSchema>>} Promessa que é resolvida quando a lista de *schemas* for salva.
340
+ */
341
+ saveAll(schemas) {
342
+ return this.poStorage.set(PoSchemaUtil.syncSchemasName, schemas);
343
+ }
344
+ /**
345
+ * Atualiza um *schema* a partir do *schema name*.
346
+ *
347
+ * @param {PoSyncSchema} updatedSchema **Schema* que será atualizado.
348
+ */
349
+ async update(updatedSchema) {
350
+ let schemas = await this.getAll();
351
+ const replaceUpdatedSchema = schema => {
352
+ if (schema.name === updatedSchema.name) {
353
+ return updatedSchema;
354
+ }
355
+ else {
356
+ return schema;
357
+ }
358
+ };
359
+ schemas = schemas.map(replaceUpdatedSchema);
360
+ return this.saveAll(schemas);
361
+ }
362
+ }
363
+ PoSchemaDefinitionService.ɵfac = function PoSchemaDefinitionService_Factory(t) { return new (t || PoSchemaDefinitionService)(i0.ɵɵinject(i1.PoStorageService)); };
364
+ PoSchemaDefinitionService.ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: PoSchemaDefinitionService, factory: PoSchemaDefinitionService.ɵfac });
365
+ (function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(PoSchemaDefinitionService, [{
366
+ type: Injectable
367
+ }], function () { return [{ type: i1.PoStorageService }]; }, null); })();
368
+
369
+ /**
370
+ * @docsPrivate
371
+ *
372
+ * @description
373
+ *
374
+ * Serviço que realiza as operações nos `schemas`.
375
+ */
376
+ class PoSchemaService {
377
+ constructor(poSchemaDefinitionService, poStorage) {
378
+ this.poSchemaDefinitionService = poSchemaDefinitionService;
379
+ this.poStorage = poStorage;
380
+ }
381
+ /**
382
+ * Retorna o id a partir de uma chave de um *schema*.
383
+ *
384
+ * @param {string} schemaKey Chave do *schema* em que será realizada a busca do id.
385
+ */
386
+ static getIdByRecordKey(schemaKey) {
387
+ return schemaKey.split(':')[1];
388
+ }
389
+ /**
390
+ * Retorna a chave do *schema* informado.
391
+ *
392
+ * @param {string} schemaName Nome do *schema*.
393
+ * @param {any} recordId Id do registro.
394
+ * @param {boolean} isLocalKey Indica se é uma chave local.
395
+ */
396
+ static getRecordKey(schemaName, recordId, isLocalKey = false) {
397
+ return isLocalKey ? `${schemaName}_local:${recordId}` : `${schemaName}:${recordId}`;
398
+ }
399
+ /**
400
+ * Verifica se o dado informado é uma chave de um *schema*.
401
+ *
402
+ * @param {string} data Dado que será verificado se é uma chave de um *schema*.
403
+ * @param {string} schemaName Nome do *schema*.
404
+ */
405
+ static isSchemaKey(data, schemaName) {
406
+ return data ? data.startsWith(`${schemaName}:`) : false;
407
+ }
408
+ /**
409
+ * Cria um novo registro para o *schema* informado.
410
+ *
411
+ * @param {PoSyncSchema} schema **Schema* em que será criado o registro.
412
+ * @param {object} newRecord Registro que será criado.
413
+ */
414
+ async create(schema, newRecord) {
415
+ const id = PoSchemaUtil.getRecordId(newRecord, schema);
416
+ return this.save(schema, newRecord, id);
417
+ }
418
+ /**
419
+ * Destrói as chaves do *storage* que contém os registros dos *schemas*.
420
+ *
421
+ * @returns {Promise<void>} Promessa que é resolvida quando as chaves referentes aos *schemas* forem destruídas.
422
+ */
423
+ async destroySchemasRecords() {
424
+ const schemas = await this.poSchemaDefinitionService.getAll();
425
+ const storageKeys = await this.poStorage.keys();
426
+ for (const key of storageKeys) {
427
+ const schemaKey = schemas.find(schema => PoSchemaService.isSchemaKey(key, schema.name));
428
+ if (schemaKey) {
429
+ const id = PoSchemaService.getIdByRecordKey(key);
430
+ await this.remove(schemaKey.name, id);
431
+ }
432
+ }
433
+ }
434
+ /**
435
+ * Retorna o registro referente ao *schema* informado.
436
+ *
437
+ * @param {string} schemaName Nome do *schema*.
438
+ * @param {any} recordId Id do registro.
439
+ */
440
+ async get(schemaName, recordId) {
441
+ const isLocalRecord = true;
442
+ const localRecord = await this.getRecord(schemaName, recordId, isLocalRecord);
443
+ const record = await this.getRecord(schemaName, recordId);
444
+ return Object.assign(record, localRecord);
445
+ }
446
+ /**
447
+ * Retorna todos os registros referente ao *schema* informado.
448
+ *
449
+ * @param {string} schemaName Nome do *schema*.
450
+ */
451
+ async getAll(schemaName) {
452
+ const storageKeys = await this.poStorage.keys();
453
+ const schemaRecords = [];
454
+ for (const key of storageKeys) {
455
+ if (PoSchemaService.isSchemaKey(key, schemaName)) {
456
+ const id = PoSchemaService.getIdByRecordKey(key);
457
+ schemaRecords.push(await this.get(schemaName, id));
458
+ }
459
+ }
460
+ return schemaRecords;
461
+ }
462
+ /**
463
+ * Aguarda a liberação do recurso limitado, posteriormente o envolve em um comportamento
464
+ * de bloqueio e desbloqueio.
465
+ *
466
+ * @param {Function} limitedResource Função que será envolvida no comportamento de bloqueio e desbloqueio.
467
+ */
468
+ limitedCallWrap(limitedResource) {
469
+ return this.poStorage.limitedCallWrap(limitedResource);
470
+ }
471
+ /**
472
+ * Remove um registro de um *schema* informado.
473
+ *
474
+ * @param {string} schemaName Nome do *schema*.
475
+ * @param {any} recordId Id do registro.
476
+ */
477
+ async remove(schemaName, recordId) {
478
+ const recordKey = PoSchemaService.getRecordKey(schemaName, recordId);
479
+ const localRecordKey = PoSchemaService.getRecordKey(schemaName, recordId, true);
480
+ await this.poStorage.remove(recordKey);
481
+ await this.poStorage.remove(localRecordKey);
482
+ }
483
+ /**
484
+ * Atualiza um registro de um *schema* informado.
485
+ *
486
+ * @param {PoSyncSchema} schema **Schema* referente ao registro que será alterado.
487
+ * @param {object} record Registro que será atualizado.
488
+ * @param {any} recordId Id do registro que deseja ser alterado. Deve ser utilizado em casos em que o id foi alterado.
489
+ */
490
+ async update(schema, record, recordId) {
491
+ const id = PoSchemaUtil.getRecordId(record, schema);
492
+ if (recordId) {
493
+ record = await this.updateRecordId(schema.name, record, recordId);
494
+ }
495
+ return this.save(schema, record, id);
496
+ }
497
+ /**
498
+ * Atualiza todos os registros de um *schema*.
499
+ *
500
+ * @param {PoSyncSchema} schema **Schema* referente aos registros que serão alterados.
501
+ * @param {Array<object>} records Lista de registros que serão alterados.
502
+ */
503
+ async updateAll(schema, records) {
504
+ for (const record of records) {
505
+ await this.update(schema, record);
506
+ }
507
+ }
508
+ async getRecord(schemaName, recordId, isLocalRecord = false) {
509
+ return (await this.poStorage.get(PoSchemaService.getRecordKey(schemaName, recordId, isLocalRecord))) || {};
510
+ }
511
+ async save(schema, record, recordId) {
512
+ const { serverRecord, localRecord } = PoSchemaUtil.separateSchemaFields(schema, record);
513
+ const recordKey = PoSchemaService.getRecordKey(schema.name, recordId);
514
+ await this.poStorage.set(recordKey, serverRecord);
515
+ await this.saveLocalFields(schema.name, localRecord, recordId);
516
+ return record;
517
+ }
518
+ async saveLocalFields(schemaName, localFields, recordId) {
519
+ const containsLocalFields = Object.keys(localFields).length;
520
+ if (containsLocalFields) {
521
+ const localRecordKey = PoSchemaService.getRecordKey(schemaName, recordId, true);
522
+ await this.poStorage.set(localRecordKey, localFields);
523
+ }
524
+ }
525
+ async updateRecordId(schemaName, record, recordId) {
526
+ const isLocalRecord = true;
527
+ const localRecord = await this.getRecord(schemaName, recordId, isLocalRecord);
528
+ await this.remove(schemaName, recordId);
529
+ return Object.assign(record, localRecord);
530
+ }
531
+ }
532
+ PoSchemaService.ɵfac = function PoSchemaService_Factory(t) { return new (t || PoSchemaService)(i0.ɵɵinject(PoSchemaDefinitionService), i0.ɵɵinject(i1.PoStorageService)); };
533
+ PoSchemaService.ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: PoSchemaService, factory: PoSchemaService.ɵfac });
534
+ (function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(PoSchemaService, [{
535
+ type: Injectable
536
+ }], function () { return [{ type: PoSchemaDefinitionService }, { type: i1.PoStorageService }]; }, null); })();
537
+
538
+ /**
539
+ * @docsPrivate
540
+ *
541
+ * @description
542
+ *
543
+ * Serviço para execução de requisições HTTP.
544
+ */
545
+ class PoHttpClientService {
546
+ constructor(httpClient) {
547
+ this.httpClient = httpClient;
548
+ }
549
+ /**
550
+ * Constrói uma requisição HTTP personalizada.
551
+ *
552
+ * @param {PoHttpRequestData} poHttpOperationData Parâmetros para a construção
553
+ * da requisição.
554
+ */
555
+ createRequest(poHttpOperationData) {
556
+ const httpHeaders = this.createHttpHeaders(poHttpOperationData.headers);
557
+ return this.httpClient.request(poHttpOperationData.method, poHttpOperationData.url, {
558
+ observe: 'response',
559
+ headers: httpHeaders,
560
+ body: poHttpOperationData.body
561
+ });
562
+ }
563
+ /**
564
+ * Constrói uma requisição com o método `delete`.
565
+ *
566
+ * @param {string} url URL da requisição.
567
+ * @param {Array<PoHeaderOption>} httpHeaders Cabeçalhos da requisição.
568
+ */
569
+ delete(url, httpHeaders) {
570
+ const requestData = {
571
+ url: url,
572
+ method: PoHttpRequestType.DELETE,
573
+ headers: httpHeaders
574
+ };
575
+ return this.createRequest(requestData);
576
+ }
577
+ /**
578
+ * Constrói uma requisição com o método `get`.
579
+ *
580
+ * @param {string} url URL da requisição.
581
+ * @param {Array<PoHeaderOption>} httpHeaders Cabeçalhos da requisição.
582
+ */
583
+ get(url, httpHeaders) {
584
+ const requestData = {
585
+ url: url,
586
+ method: PoHttpRequestType.GET,
587
+ headers: httpHeaders
588
+ };
589
+ return this.createRequest(requestData);
590
+ }
591
+ /**
592
+ * Constrói uma requisição com o método `head`.
593
+ *
594
+ * @param {string} url URL da requisição.
595
+ * @param {Array<PoHeaderOption>} httpHeaders Cabeçalhos da requisição.
596
+ */
597
+ head(url, httpHeaders) {
598
+ const requestData = {
599
+ url: url,
600
+ method: PoHttpRequestType.HEAD,
601
+ headers: httpHeaders
602
+ };
603
+ return this.createRequest(requestData);
604
+ }
605
+ /**
606
+ * Constrói uma requisição com o método `options`.
607
+ *
608
+ * @param {string} url URL da requisição.
609
+ * @param {Array<PoHeaderOption>} httpHeaders Cabeçalhos da requisição.
610
+ */
611
+ options(url, httpHeaders) {
612
+ const requestData = {
613
+ url: url,
614
+ method: PoHttpRequestType.OPTIONS,
615
+ headers: httpHeaders
616
+ };
617
+ return this.createRequest(requestData);
618
+ }
619
+ /**
620
+ * Constrói uma requisição com o método `patch`.
621
+ *
622
+ * @param {string} url URL da requisição.
623
+ * @param {any} body Corpo da requisição.
624
+ * @param {Array<PoHeaderOption>} httpHeaders Cabeçalhos da requisição.
625
+ */
626
+ patch(url, body, httpHeaders) {
627
+ const requestData = {
628
+ url: url,
629
+ method: PoHttpRequestType.PATCH,
630
+ headers: httpHeaders,
631
+ body: body
632
+ };
633
+ return this.createRequest(requestData);
634
+ }
635
+ /**
636
+ * Constrói uma requisição com o método `post`.
637
+ *
638
+ * @param {string} url URL da requisição.
639
+ * @param {any} body Corpo da requisição.
640
+ * @param {Array<PoHeaderOption>} httpHeaders Cabeçalhos da requisição.
641
+ */
642
+ post(url, body, httpHeaders) {
643
+ const requestData = {
644
+ url: url,
645
+ method: PoHttpRequestType.POST,
646
+ headers: httpHeaders,
647
+ body: body
648
+ };
649
+ return this.createRequest(requestData);
650
+ }
651
+ /**
652
+ * Constrói uma requisição com o método `put`.
653
+ *
654
+ * @param {string} url URL da requisição.
655
+ * @param {any} body Corpo da requisição.
656
+ * @param {Array<PoHeaderOption>} httpHeaders Cabeçalhos da requisição.
657
+ */
658
+ put(url, body, httpHeaders) {
659
+ const requestData = {
660
+ url: url,
661
+ method: PoHttpRequestType.PUT,
662
+ headers: httpHeaders,
663
+ body: body
664
+ };
665
+ return this.createRequest(requestData);
666
+ }
667
+ createHttpHeaders(poHttpOperationHeaders) {
668
+ let httpHeaders = new HttpHeaders();
669
+ if (poHttpOperationHeaders && poHttpOperationHeaders.length > 0) {
670
+ poHttpOperationHeaders.forEach(poHttpHeader => (httpHeaders = httpHeaders.append(poHttpHeader.name, poHttpHeader.value)));
671
+ }
672
+ return httpHeaders;
673
+ }
674
+ }
675
+ PoHttpClientService.ɵfac = function PoHttpClientService_Factory(t) { return new (t || PoHttpClientService)(i0.ɵɵinject(i1$1.HttpClient)); };
676
+ PoHttpClientService.ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: PoHttpClientService, factory: PoHttpClientService.ɵfac });
677
+ (function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(PoHttpClientService, [{
678
+ type: Injectable
679
+ }], function () { return [{ type: i1$1.HttpClient }]; }, null); })();
680
+
681
+ class PoEventSourcingService {
682
+ constructor(poSchemaDefinition, poSchemaService, poStorage, poHttpClient) {
683
+ this.poSchemaDefinition = poSchemaDefinition;
684
+ this.poSchemaService = poSchemaService;
685
+ this.poStorage = poStorage;
686
+ this.poHttpClient = poHttpClient;
687
+ this.stoppedQueueEventSourcing = false;
688
+ this.responseSubject = new Subject();
689
+ this.schemasSyncConfig = {};
690
+ }
691
+ static getUrl(eventSourcingItem, schema, requestType) {
692
+ const schemaUrl = PoSchemaUtil.getUrl(schema, requestType);
693
+ const schemaId = eventSourcingItem.record[schema.idField];
694
+ if (requestType === PoRequestType.GET) {
695
+ return schemaUrl;
696
+ }
697
+ if ([PoRequestType.DELETE, PoRequestType.PATCH].includes(requestType)) {
698
+ return schemaUrl ? `${schemaUrl}/${schemaId}` : `${PoSchemaUtil.getUrl(schema, PoRequestType.GET)}/${schemaId}`;
699
+ }
700
+ if (requestType === PoRequestType.POST) {
701
+ return schemaUrl ? schemaUrl : PoSchemaUtil.getUrl(schema, PoRequestType.GET);
702
+ }
703
+ }
704
+ create(schemaName, newItem, customRequestId) {
705
+ const eventSourcingItem = this.createEventSourcingItem(PoEventSourcingOperation.Insert, newItem, schemaName, customRequestId);
706
+ return this.insertEventSourcingQueue(eventSourcingItem);
707
+ }
708
+ async createBatchEvents(schemaName, eventList) {
709
+ const eventSourcingList = this.createEventSourcingList(schemaName, eventList);
710
+ await this.poStorage.appendArrayToArray(PoEventSourcingService.event_sourcing_name, eventSourcingList);
711
+ this.notifyEventCreation();
712
+ }
713
+ /**
714
+ * Destrói a chave do *storage* que contém a fila de dados que estão esperando para serem enviados ao
715
+ * servidor *(EventSourcing)*.
716
+ *
717
+ * @returns {Promise<void>} Promessa que é resolvida quando a chave referente a fila de *EventSourcing* for destruída.
718
+ */
719
+ destroyEventSourcingQueue() {
720
+ return this.poStorage.remove(PoEventSourcingService.event_sourcing_name);
721
+ }
722
+ async httpCommand(httpOperationData, customRequestId) {
723
+ httpOperationData = await this.serializeBody(httpOperationData);
724
+ const eventSourcingItem = this.createEventSourcingItem(PoEventSourcingOperation.Http, httpOperationData, undefined, customRequestId);
725
+ await this.insertEventSourcingQueue(eventSourcingItem);
726
+ return eventSourcingItem.id;
727
+ }
728
+ responsesSubject() {
729
+ return this.responseSubject.asObservable();
730
+ }
731
+ onSaveData() {
732
+ if (!this.eventSub) {
733
+ this.eventSub = Observable.create(subscriber => (this.emitter = subscriber));
734
+ }
735
+ return this.eventSub;
736
+ }
737
+ remove(schemaName, itemToDelete, customRequestId) {
738
+ const eventSourcingItem = this.createEventSourcingItem(PoEventSourcingOperation.Delete, itemToDelete, schemaName, customRequestId);
739
+ return this.insertEventSourcingQueue(eventSourcingItem);
740
+ }
741
+ removeEventSourcingItem(idEventSourcingItem) {
742
+ return this.poStorage.removeItemFromArray(PoEventSourcingService.event_sourcing_name, 'id', idEventSourcingItem);
743
+ }
744
+ syncGet() {
745
+ const syncGetFunction = async () => this.poSchemaDefinition.getAll().then(schemas => {
746
+ const schemaPromises = this.updateStorageSchemas(schemas);
747
+ return Promise.all(schemaPromises);
748
+ });
749
+ return this.poSchemaService.limitedCallWrap(syncGetFunction);
750
+ }
751
+ async syncSend() {
752
+ const syncSendFunction = async () => {
753
+ const itemOfQueue = await this.poStorage.getFirstItem(PoEventSourcingService.event_sourcing_name);
754
+ if (itemOfQueue) {
755
+ await this.selectOperation(itemOfQueue);
756
+ }
757
+ if (this.stoppedQueueEventSourcing || !itemOfQueue) {
758
+ this.stoppedQueueEventSourcing = false;
759
+ return Promise.resolve();
760
+ }
761
+ return syncSendFunction();
762
+ };
763
+ return this.poSchemaService.limitedCallWrap(syncSendFunction);
764
+ }
765
+ update(schemaName, itemUpdated, customRequestId) {
766
+ const eventSourcingItem = this.createEventSourcingItem(PoEventSourcingOperation.Update, itemUpdated, schemaName, customRequestId);
767
+ return this.insertEventSourcingQueue(eventSourcingItem);
768
+ }
769
+ /* Avalia se o body é do tipo File e se for converte para base64 */
770
+ async serializeBody(requestData) {
771
+ let { body, mimeType, bodyType, fileName } = requestData;
772
+ if (body instanceof File) {
773
+ bodyType = 'File';
774
+ mimeType = body.type;
775
+ fileName = body.name;
776
+ body = await toBase64(body);
777
+ }
778
+ return { ...requestData, body, mimeType, bodyType, fileName };
779
+ }
780
+ buildUrlParams(schema, baseUrl, pageNumber) {
781
+ const params = [];
782
+ params.push(`${this.config.dataTransform.getPageSizeParamName()}=${schema.pageSize}`);
783
+ params.push(`${this.config.dataTransform.getPageParamName()}=${pageNumber}`);
784
+ return `${baseUrl}?${params.join('&')}`;
785
+ }
786
+ checkRecordIdExists(recordId, operation) {
787
+ if (!recordId) {
788
+ const error = {
789
+ message: 'Identifier not defined',
790
+ operation: operation
791
+ };
792
+ throw new PoEventSourcingErrorResponse(error);
793
+ }
794
+ }
795
+ concatPageItems(pageAcumulator, requestBody) {
796
+ if (requestBody[this.config.dataTransform.getItemsFieldName()]) {
797
+ pageAcumulator.data = [...pageAcumulator.data, ...requestBody[this.config.dataTransform.getItemsFieldName()]];
798
+ }
799
+ return pageAcumulator;
800
+ }
801
+ createEventSourcingItem(operation, newItem, schemaName, customRequestId, id) {
802
+ if (!schemaName && operation !== PoEventSourcingOperation.Http) {
803
+ throw new Error('PoSyncSchema is not defined.');
804
+ }
805
+ return {
806
+ id: id ? id : new Date().getTime(),
807
+ dateTime: new Date().getTime(),
808
+ schema: schemaName,
809
+ operation: operation,
810
+ record: newItem,
811
+ customRequestId: customRequestId
812
+ };
813
+ }
814
+ createEventSourcingList(schemaName, eventList) {
815
+ return eventList.map((eventItem, index) => {
816
+ const id = new Date().getTime() + index;
817
+ return this.createEventSourcingItem(eventItem.operation, eventItem.record, schemaName, eventItem.customRequestId, id);
818
+ });
819
+ }
820
+ createSchemaSyncConfig(schemaName) {
821
+ this.schemasSyncConfig[schemaName] = {
822
+ page: undefined,
823
+ currentUrlDiff: undefined,
824
+ responseDate: undefined
825
+ };
826
+ }
827
+ async deleteOperation(eventSourcingItem) {
828
+ try {
829
+ const schema = await this.poSchemaDefinition.get(eventSourcingItem.schema);
830
+ const recordId = eventSourcingItem.record[schema.idField];
831
+ this.checkRecordIdExists(recordId, PoEventSourcingOperation.Delete);
832
+ const url = PoEventSourcingService.getUrl(eventSourcingItem, schema, PoRequestType.DELETE);
833
+ const response = await this.sendServerItem(url, PoHttpRequestType.DELETE);
834
+ await this.removeEventSourcingValidItem(response.status, eventSourcingItem);
835
+ return await this.sendResponseSubject(eventSourcingItem, response);
836
+ }
837
+ catch (errorResponse) {
838
+ return this.sendResponseSubject(eventSourcingItem, errorResponse, true);
839
+ }
840
+ }
841
+ diffServerItems(currentUrlDiff) {
842
+ return this.poHttpClient.get(currentUrlDiff);
843
+ }
844
+ getBodyAndDate(schemaName, response) {
845
+ const getDateFieldName = this.config.dataTransform.getDateFieldName();
846
+ const responseSyncDate = response.body[getDateFieldName];
847
+ this.schemasSyncConfig[schemaName]['responseDate'] = responseSyncDate;
848
+ return response.body;
849
+ }
850
+ async getServerDiffRecords(schema, baseUrl) {
851
+ const initialAcumulatorPage = { entity: schema.name, data: [] };
852
+ const diffUrl = this.schemasSyncConfig[schema.name]['currentUrlDiff'];
853
+ const serverResponse = await this.diffServerItems(diffUrl)
854
+ .pipe(map(response => this.getBodyAndDate(schema.name, response)), expand(data => this.paginateSchemaData(data, schema, baseUrl)), reduce((pageAcumulator, requestBody) => this.concatPageItems(pageAcumulator, requestBody), initialAcumulatorPage))
855
+ .toPromise();
856
+ return serverResponse.data;
857
+ }
858
+ async httpOperation(eventSourcingItem) {
859
+ try {
860
+ const requestData = await this.createPoHttpRequestData(eventSourcingItem.record.url, eventSourcingItem.record.method, eventSourcingItem.record, eventSourcingItem.record.headers);
861
+ const response = await this.poHttpClient.createRequest(requestData).toPromise();
862
+ const poHttpCommandResponse = {
863
+ id: eventSourcingItem.id,
864
+ customRequestId: eventSourcingItem.customRequestId,
865
+ request: eventSourcingItem.record,
866
+ response: response
867
+ };
868
+ this.responseSubject.next(poHttpCommandResponse);
869
+ return this.removeEventSourcingValidItem(response.status, eventSourcingItem);
870
+ }
871
+ catch (errorHttpClient) {
872
+ return this.sendResponseSubject(eventSourcingItem, errorHttpClient, true);
873
+ }
874
+ }
875
+ async insertEventSourcingQueue(eventSourcingItem) {
876
+ const eventSourcingUpdatedQueue = await this.poStorage.appendItemToArray(PoEventSourcingService.event_sourcing_name, eventSourcingItem);
877
+ this.notifyEventCreation();
878
+ return Promise.resolve(eventSourcingUpdatedQueue);
879
+ }
880
+ async insertOperation(currentEventSourcingItem) {
881
+ const schema = await this.poSchemaDefinition.get(currentEventSourcingItem.schema);
882
+ const url = PoEventSourcingService.getUrl(currentEventSourcingItem, schema, PoRequestType.POST);
883
+ try {
884
+ const response = await this.sendServerItem(url, PoHttpRequestType.POST, currentEventSourcingItem.record);
885
+ const recordUpdatedByServer = response.body;
886
+ await this.removeEventSourcingValidItem(response.status, currentEventSourcingItem);
887
+ const id = currentEventSourcingItem.record[PoSchemaUtil.syncInternalIdFieldName];
888
+ await this.poSchemaService.update(schema, recordUpdatedByServer, id);
889
+ const eventSourcingItems = await this.poStorage.get(PoEventSourcingService.event_sourcing_name);
890
+ await this.updatePendingEventSourcing(currentEventSourcingItem, schema.idField, recordUpdatedByServer, eventSourcingItems);
891
+ return this.sendResponseSubject(currentEventSourcingItem, response);
892
+ }
893
+ catch (errorHttpClient) {
894
+ return this.sendResponseSubject(currentEventSourcingItem, errorHttpClient, true);
895
+ }
896
+ }
897
+ isValidStatus(status) {
898
+ return PoEventSourcingService.VALID_HTTP_STATUS_CODES.includes(status);
899
+ }
900
+ notifyEventCreation() {
901
+ if (this.emitter) {
902
+ this.emitter.next();
903
+ }
904
+ }
905
+ paginateSchemaData(data, schema, baseUrl) {
906
+ this.config.dataTransform.transform(data);
907
+ if (this.config.dataTransform.hasNext()) {
908
+ this.schemasSyncConfig[schema.name]['currentUrlDiff'] = this.buildUrlParams(schema, baseUrl, ++this.schemasSyncConfig[schema.name]['page']);
909
+ return this.diffServerItems(this.schemasSyncConfig[schema.name]['currentUrlDiff']).pipe(map(response => this.getBodyAndDate(schema.name, response)));
910
+ }
911
+ return of();
912
+ }
913
+ removeEventSourcingValidItem(status, eventSourcingItem) {
914
+ if (this.isValidStatus(status) || eventSourcingItem.operation === PoEventSourcingOperation.Http) {
915
+ return this.removeEventSourcingItem(eventSourcingItem.id);
916
+ }
917
+ }
918
+ selectOperation(eventSourcingItem) {
919
+ switch (eventSourcingItem.operation) {
920
+ case PoEventSourcingOperation.Insert:
921
+ return this.insertOperation(eventSourcingItem);
922
+ case PoEventSourcingOperation.Update:
923
+ return this.updateOperation(eventSourcingItem);
924
+ case PoEventSourcingOperation.Delete:
925
+ return this.deleteOperation(eventSourcingItem);
926
+ case PoEventSourcingOperation.Http:
927
+ return this.httpOperation(eventSourcingItem);
928
+ }
929
+ }
930
+ sendResponseSubject(eventSourcingItem, response, isSubjectError = false) {
931
+ const poSyncResponse = {
932
+ id: eventSourcingItem.id,
933
+ customRequestId: eventSourcingItem.customRequestId,
934
+ request: eventSourcingItem.record,
935
+ response: response
936
+ };
937
+ this.stoppedQueueEventSourcing = isSubjectError;
938
+ this.responseSubject.next(poSyncResponse);
939
+ return Promise.resolve();
940
+ }
941
+ async sendServerItem(url, method, body) {
942
+ const requestData = await this.createPoHttpRequestData(url, method, body);
943
+ return this.poHttpClient.createRequest(requestData).toPromise();
944
+ }
945
+ async createPoHttpRequestData(url, method, record, headers) {
946
+ let body = record.body ?? record;
947
+ if (record.bodyType === 'File') {
948
+ body = await this.createFormData(body, record.fileName, record.mimeType, record.formField);
949
+ }
950
+ return { url, method, body, headers };
951
+ }
952
+ async createFormData(body, fileName, mimeType, formField = 'file') {
953
+ const file = await toFile(body, fileName, mimeType);
954
+ const formData = new FormData();
955
+ formData.append(formField, file, fileName);
956
+ return formData;
957
+ }
958
+ async updateOperation(eventSourcingItem) {
959
+ const schema = await this.poSchemaDefinition.get(eventSourcingItem.schema);
960
+ const url = PoEventSourcingService.getUrl(eventSourcingItem, schema, PoRequestType.PATCH);
961
+ try {
962
+ const recordId = eventSourcingItem.record[schema.idField];
963
+ this.checkRecordIdExists(recordId, PoEventSourcingOperation.Update);
964
+ const response = await this.sendServerItem(url, PoHttpRequestType.PUT, eventSourcingItem.record);
965
+ await this.removeEventSourcingValidItem(response.status, eventSourcingItem);
966
+ return await this.sendResponseSubject(eventSourcingItem, response);
967
+ }
968
+ catch (errorHttpClient) {
969
+ return this.sendResponseSubject(eventSourcingItem, errorHttpClient, true);
970
+ }
971
+ }
972
+ updatePendingEventSourcing(currentEventSourcingItem, idFieldSchema, inserted, eventSourcingItems) {
973
+ if (currentEventSourcingItem.record[PoSchemaUtil.syncInternalIdFieldName]) {
974
+ eventSourcingItems.forEach((eventSourcingItem, position) => {
975
+ const isCurrentEventSourcingItem = !eventSourcingItem.record[idFieldSchema] &&
976
+ eventSourcingItem.record[PoSchemaUtil.syncInternalIdFieldName] ===
977
+ currentEventSourcingItem.record[PoSchemaUtil.syncInternalIdFieldName];
978
+ if (isCurrentEventSourcingItem) {
979
+ eventSourcingItems[position].record[idFieldSchema] = inserted[idFieldSchema];
980
+ }
981
+ });
982
+ return this.poStorage.set(PoEventSourcingService.event_sourcing_name, eventSourcingItems);
983
+ }
984
+ else {
985
+ return Promise.resolve();
986
+ }
987
+ }
988
+ async updateRecords(serverRecords, schema) {
989
+ for (const serverRecord of serverRecords) {
990
+ await this.updateRecordByServerRecord(serverRecord, schema);
991
+ }
992
+ }
993
+ async updateRecordByServerRecord(serverRecord, schema) {
994
+ const recordId = serverRecord[schema.idField];
995
+ const storageRecord = await this.poSchemaService.get(schema.name, recordId);
996
+ const existsStorageRecord = !!Object.keys(storageRecord).length;
997
+ if (existsStorageRecord && serverRecord[schema.deletedField]) {
998
+ return await this.poSchemaService.remove(schema.name, serverRecord[schema.idField]);
999
+ }
1000
+ if (existsStorageRecord && !serverRecord[schema.deletedField]) {
1001
+ return await this.poSchemaService.update(schema, serverRecord);
1002
+ }
1003
+ if (!existsStorageRecord && !serverRecord[schema.deletedField]) {
1004
+ return await this.poSchemaService.create(schema, serverRecord);
1005
+ }
1006
+ }
1007
+ async updateStorageBySchema(schema) {
1008
+ this.createSchemaSyncConfig(schema.name);
1009
+ this.schemasSyncConfig[schema.name]['page'] = 1;
1010
+ const baseUrl = `${PoSchemaUtil.getUrl(schema, PoRequestType.DIFF)}/${schema.lastSync}`;
1011
+ this.schemasSyncConfig[schema.name]['currentUrlDiff'] = this.buildUrlParams(schema, baseUrl, this.schemasSyncConfig[schema.name]['page']);
1012
+ const serverRecords = await this.getServerDiffRecords(schema, baseUrl);
1013
+ await this.updateRecords(serverRecords, schema);
1014
+ schema.lastSync = this.schemasSyncConfig[schema.name]['responseDate'];
1015
+ await this.poSchemaDefinition.update(schema);
1016
+ }
1017
+ updateStorageSchemas(schemas) {
1018
+ return schemas.map((schema) => this.updateStorageBySchema(schema));
1019
+ }
1020
+ }
1021
+ PoEventSourcingService.event_sourcing_name = 'EventSourcing';
1022
+ PoEventSourcingService.VALID_HTTP_STATUS_CODES = [
1023
+ HttpStatus.OK,
1024
+ HttpStatus.CREATED,
1025
+ HttpStatus.ACCEPTED,
1026
+ HttpStatus.NON_AUTHORITATIVE_INFORMATION,
1027
+ HttpStatus.NO_CONTENT,
1028
+ HttpStatus.RESET_CONTENT,
1029
+ HttpStatus.PARTIAL_CONTENT,
1030
+ HttpStatus.MULTI_STATUS // 207
1031
+ ];
1032
+ PoEventSourcingService.ɵfac = function PoEventSourcingService_Factory(t) { return new (t || PoEventSourcingService)(i0.ɵɵinject(PoSchemaDefinitionService), i0.ɵɵinject(PoSchemaService), i0.ɵɵinject(i1.PoStorageService), i0.ɵɵinject(PoHttpClientService)); };
1033
+ PoEventSourcingService.ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: PoEventSourcingService, factory: PoEventSourcingService.ɵfac });
1034
+ (function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(PoEventSourcingService, [{
1035
+ type: Injectable
1036
+ }], function () { return [{ type: PoSchemaDefinitionService }, { type: PoSchemaService }, { type: i1.PoStorageService }, { type: PoHttpClientService }]; }, null); })();
1037
+
1038
+ /**
1039
+ * @description
1040
+ *
1041
+ * Classe utilitária para construir consultas sobre os registros de um *schema*.
1042
+ *
1043
+ * A utilização dos métodos desta classe é feita a partir do retorno do método `PoEntity.find()`. Por exemplo,
1044
+ * para utilizar o método `PoQueryBuilder.page()`, é necessário:
1045
+ *
1046
+ * ``` typescript
1047
+ * PoSyncService.getModel('schema name').find().page(2).exec();
1048
+ * ```
1049
+ *
1050
+ * O `PoQueryBuilder` foi projetado para que os seus métodos sejam
1051
+ * chamados em cascata e ao final desse encadeamento invocar o método
1052
+ * `PoQueryBuilder.exec()` para que a busca seja concluída. Por exemplo:
1053
+ *
1054
+ * ``` typescript
1055
+ * PoSyncService
1056
+ * .getModel('schema name')
1057
+ * .find()
1058
+ * .page(2)
1059
+ * .pageSize(5)
1060
+ * .sort()
1061
+ * .exec();
1062
+ * ```
1063
+ */
1064
+ class PoQueryBuilder {
1065
+ constructor(poSchemaService, schema) {
1066
+ this.poSchemaService = poSchemaService;
1067
+ this.schema = schema;
1068
+ this._page = 1;
1069
+ this.filters = {};
1070
+ }
1071
+ /**
1072
+ * Ao final da chamada dos métodos do `PoQueryBuilder` utilizados, este método deve ser chamado para que a busca seja concluída.
1073
+ *
1074
+ * @return {Promise<PoResponseApi | object>} Registros do *schema* na qual foi aplicado a consulta.
1075
+ */
1076
+ async exec() {
1077
+ let storageData = await this.poSchemaService.getAll(this.schema.name);
1078
+ if (storageData && storageData.length) {
1079
+ if (Object.keys(this.filters).length) {
1080
+ storageData = this.applyFilters(storageData);
1081
+ }
1082
+ if (this.fields) {
1083
+ storageData = this.applyFields(this.schema.fields, storageData);
1084
+ }
1085
+ if (this._sort) {
1086
+ storageData = this.order(storageData, this._sort);
1087
+ }
1088
+ if (this._limit) {
1089
+ return storageData[0];
1090
+ }
1091
+ else {
1092
+ return this.paginate(storageData);
1093
+ }
1094
+ }
1095
+ else {
1096
+ return {
1097
+ hasNext: false,
1098
+ items: []
1099
+ };
1100
+ }
1101
+ }
1102
+ /**
1103
+ * Aplica filtros sobre os registros, baseados nos campos e valores definidos como filtro. Por exemplo:
1104
+ *
1105
+ * ```
1106
+ * PoQueryBuilder.filter({ name: 'Marie', age: 24 });
1107
+ * ```
1108
+ * Retorna todos os registros que contenham a propriedade `name` igual a Marie e `age` igual a 24.
1109
+ *
1110
+ * @param {object} filter Objeto que contém os campos e valores a serem filtrados no *schema*.
1111
+ *
1112
+ * @returns {PoQueryBuilder} Objeto que possibilita encadear um novo método do `PoQueryBuilder`.
1113
+ */
1114
+ filter(filter) {
1115
+ if (filter && typeof filter === 'object') {
1116
+ this.filters = { ...this.filters, ...filter };
1117
+ }
1118
+ else {
1119
+ throw new Error('Filter must be an object');
1120
+ }
1121
+ return this;
1122
+ }
1123
+ /**
1124
+ * Limita o número de registros que serão retornados.
1125
+ *
1126
+ * @param {number} limit Número de registros retornados.
1127
+ * @returns {PoQueryBuilder} Objeto que possibilita encadear um novo método do `PoQueryBuilder`.
1128
+ */
1129
+ limit(limit) {
1130
+ this._limit = limit;
1131
+ return this;
1132
+ }
1133
+ /**
1134
+ * Especifica a página de registros que se deseja retornar.
1135
+ *
1136
+ * @param {number} page Número da página.
1137
+ * @returns {PoQueryBuilder} Objeto que possibilita encadear um novo método do `PoQueryBuilder`.
1138
+ */
1139
+ page(page) {
1140
+ validateParameter({ page });
1141
+ this._page = page;
1142
+ return this;
1143
+ }
1144
+ /**
1145
+ * Define quantos elementos serão retornados por página.
1146
+ *
1147
+ * @param {number} pageSize Número de registros por página.
1148
+ * @returns {PoQueryBuilder} Objeto que possibilita encadear um novo método do `PoQueryBuilder`.
1149
+ */
1150
+ pageSize(pageSize) {
1151
+ validateParameter({ pageSize });
1152
+ this._pageSize = pageSize;
1153
+ return this;
1154
+ }
1155
+ /**
1156
+ * Utilizado para definir quais campos do *schema* serão retornados na consulta.
1157
+ *
1158
+ * @param {string} fields Campos que serão retornados nos registros. Este campos devem estar dentro de
1159
+ * uma *string* separados por espaço podendo usar o caractere `-` para excluir campos.
1160
+ * Por exemplo, a definição abaixo:
1161
+ *
1162
+ * ```
1163
+ * PoQueryBuilder.select('name age address');
1164
+ * ```
1165
+ * Irá retornar apenas os campos `name`, `age` e `address`. Para não retornar um campo ou mais basta fazer:
1166
+ *
1167
+ * ```
1168
+ * PoQueryBuilder.select('-name -age');
1169
+ * ```
1170
+ *
1171
+ * @returns {PoQueryBuilder} Objeto que possibilita encadear um novo método do `PoQueryBuilder`.
1172
+ */
1173
+ select(fields) {
1174
+ validateParameter({ fields });
1175
+ this.fields = fields;
1176
+ return this;
1177
+ }
1178
+ /**
1179
+ * Ordena os registros por um campo.
1180
+ *
1181
+ * @param {string} field Campo a ser ordenado. Para ordenar de forma decrescente basta colocar o caractere `-`
1182
+ * na frente do campo. Por exemplo:
1183
+ * ```
1184
+ * PoQueryBuilder.sort('-name');
1185
+ * ```
1186
+ *
1187
+ * @returns {PoQueryBuilder} Objeto que possibilita encadear um novo método do `PoQueryBuilder`.
1188
+ */
1189
+ sort(field) {
1190
+ validateParameter({ field });
1191
+ this._sort = field;
1192
+ return this;
1193
+ }
1194
+ /**
1195
+ * Essa função serve como alias para o `PoQueryBuilder.filter()`. É utilizada somente para dar maior legibilidade ao código.
1196
+ *
1197
+ * @param {object} filter Objeto que contém os campos e valores a serem filtrados no *schema*.
1198
+ * @returns {PoQueryBuilder} Objeto que possibilita encadear um novo método do `PoQueryBuilder`.
1199
+ */
1200
+ where(filter) {
1201
+ return this.filter(filter);
1202
+ }
1203
+ applyFields(schemaFields, data) {
1204
+ const receivedFields = this.fields.split(' ');
1205
+ let restrictedFields = [];
1206
+ let selectedFields = [];
1207
+ [selectedFields, restrictedFields] = this.groupFields(receivedFields);
1208
+ if (!selectedFields.length && restrictedFields.length) {
1209
+ selectedFields = [...schemaFields];
1210
+ }
1211
+ if (restrictedFields.length) {
1212
+ selectedFields = this.removeRestrictedFields(restrictedFields, selectedFields);
1213
+ }
1214
+ selectedFields = this.removeDuplicate(selectedFields);
1215
+ return this.removeFieldsData(data, selectedFields);
1216
+ }
1217
+ applyFilters(data) {
1218
+ Object.keys(this.filters).forEach(filterKey => {
1219
+ data = data.filter(item => item[filterKey] === this.filters[filterKey]);
1220
+ });
1221
+ return data;
1222
+ }
1223
+ groupFields(receivedFields) {
1224
+ const restrictedFields = [];
1225
+ const selectedFields = [];
1226
+ receivedFields.forEach(fields => {
1227
+ if (fields.startsWith('-')) {
1228
+ restrictedFields.push(fields.substring(1));
1229
+ }
1230
+ else {
1231
+ selectedFields.push(fields);
1232
+ }
1233
+ });
1234
+ return [selectedFields, restrictedFields];
1235
+ }
1236
+ paginate(data) {
1237
+ const dataLength = data.length;
1238
+ const pageSize = this._pageSize || dataLength;
1239
+ const pages = Math.ceil(dataLength / pageSize);
1240
+ const begin = this._page * pageSize - pageSize;
1241
+ const end = begin + pageSize;
1242
+ return { hasNext: this._page < pages, items: data.slice(begin, end) };
1243
+ }
1244
+ order(data, sortingField) {
1245
+ const descendingOrder = sortingField.startsWith('-');
1246
+ sortingField = descendingOrder ? sortingField.substr(1) : sortingField;
1247
+ return data.sort((optionA, optionB) => {
1248
+ if (optionA[sortingField] > optionB[sortingField]) {
1249
+ return !descendingOrder ? 1 : -1;
1250
+ }
1251
+ if (optionA[sortingField] < optionB[sortingField]) {
1252
+ return !descendingOrder ? -1 : 1;
1253
+ }
1254
+ return 0;
1255
+ });
1256
+ }
1257
+ removeDuplicate(fields) {
1258
+ return fields.filter((item, position) => fields.indexOf(item) === position);
1259
+ }
1260
+ removeFieldsData(data, chosenFields) {
1261
+ data.forEach(item => {
1262
+ Object.keys(item).forEach(keyItem => {
1263
+ if (!chosenFields.includes(keyItem)) {
1264
+ delete item[keyItem];
1265
+ }
1266
+ });
1267
+ });
1268
+ return data;
1269
+ }
1270
+ removeRestrictedFields(restrictedFields, fields) {
1271
+ return fields.filter(field => !restrictedFields.includes(field));
1272
+ }
1273
+ }
1274
+
1275
+ /**
1276
+ * @description
1277
+ *
1278
+ * Uma instância `PoEntity` representa um *schema* e ela contém métodos que possibilitam manipular seus registros,
1279
+ * como por exemplo: buscar, criar e remover.
1280
+ *
1281
+ * Esta instância pode ser obtida a partir do retorno do método `PoSyncService.getModel('schema name')`.
1282
+ */
1283
+ class PoEntity {
1284
+ constructor(eventSourcing, schema, poSchemaService) {
1285
+ this.eventSourcing = eventSourcing;
1286
+ this.schema = schema;
1287
+ this.poSchemaService = poSchemaService;
1288
+ }
1289
+ /**
1290
+ * Busca os registros do *schema*, podendo filtrar o resultado a partir do filtro passado e retornando apenas
1291
+ * os campos definidos.
1292
+ *
1293
+ * Para que esta busca seja concluída é necessário utilizar o método `PoQueryBuilder.exec()`.
1294
+ * Veja mais em: [PoQueryBuilder](/documentation/po-query-builder).
1295
+ *
1296
+ * @param {object} filter Objeto que contém os campos e valores a serem filtrados no *schema*.
1297
+ * @param {string} fields Campos que serão retornados nos registros. Este campos devem estar dentro de
1298
+ * uma *string* separados por espaço podendo usar o caractere `-` para excluir campos.
1299
+ * Por exemplo, a definição abaixo:
1300
+ *
1301
+ * ```
1302
+ * PoQueryBuilder.select('name age address');
1303
+ * ```
1304
+ * Irá retornar apenas os campos `name`, `age` e `address`. E para não mostrar um campo ou mais basta fazer:
1305
+ *
1306
+ * ```
1307
+ * PoQueryBuilder.select('-name -age');
1308
+ * ```
1309
+ * @returns {PoQueryBuilder} Objeto que possibilita encadear um método do `PoQueryBuilder`.
1310
+ */
1311
+ find(filter, fields) {
1312
+ const query = new PoQueryBuilder(this.poSchemaService, this.schema);
1313
+ if (filter) {
1314
+ query.filter(filter);
1315
+ }
1316
+ if (fields) {
1317
+ query.select(fields);
1318
+ }
1319
+ return query;
1320
+ }
1321
+ /**
1322
+ * Busca um registro pelo seu *id*.
1323
+ *
1324
+ * Para que esta busca seja concluída é necessário utilizar o método `PoQueryBuilder.exec()`.
1325
+ * Veja mais em: [PoQueryBuilder](/documentation/po-query-builder).
1326
+ *
1327
+ * @param {any} id Identificador do registro.
1328
+ * @param {string} fields Campos que serão retornados nos registros. Este campos devem estar dentro de
1329
+ * uma *string* separados por espaço podendo usar o caractere `-` para excluir campos.
1330
+ * Por exemplo, a definição abaixo:
1331
+ *
1332
+ * ```
1333
+ * PoQueryBuilder.select('name age address');
1334
+ * ```
1335
+ * Irá retornar apenas os campos `name`, `age` e `address`. E para não mostrar um campo ou mais basta fazer:
1336
+ *
1337
+ * ```
1338
+ * PoQueryBuilder.select('-name -age');
1339
+ * ```
1340
+ * @returns {PoQueryBuilder} Objeto que possibilita encadear um método do `PoQueryBuilder`.
1341
+ */
1342
+ findById(id, fields) {
1343
+ return this.findOne({ [this.schema.idField]: id }, fields);
1344
+ }
1345
+ /**
1346
+ * Semelhante ao método `PoEntity.find()`, porém retorna apenas o primeiro registro encontrado na busca.
1347
+ *
1348
+ * Para que esta busca seja concluída é necessário utilizar o método `PoQueryBuilder.exec()`.
1349
+ * Veja mais em: [PoQueryBuilder](/documentation/po-query-builder).
1350
+ *
1351
+ * @param {any} filter Objeto que contém os campos e valores a serem filtrados no *schema*.
1352
+ * @param {string} fields Campos que serão retornados nos registros. Este campos devem estar dentro de
1353
+ * uma *string* separados por espaço podendo usar o caractere `-` para excluir campos.
1354
+ * Por exemplo, a definição abaixo:
1355
+ *
1356
+ * ```
1357
+ * PoQueryBuilder.select('name age address');
1358
+ * ```
1359
+ * Irá retornar apenas os campos `name`, `age` e `address`. E para não mostrar um campo ou mais basta fazer:
1360
+ *
1361
+ * ```
1362
+ * PoQueryBuilder.select('-name -age');
1363
+ * ```
1364
+ * @returns {PoQueryBuilder} Objeto que possibilita encadear um método do `PoQueryBuilder`.
1365
+ */
1366
+ findOne(filter, fields) {
1367
+ const query = this.find(filter, fields);
1368
+ query.limit(1);
1369
+ return query;
1370
+ }
1371
+ /**
1372
+ * Remove um registro.
1373
+ *
1374
+ * @param {object} record Registro que será removido.
1375
+ * @param {string} customRequestId Identificador customizado do comando.
1376
+ * @returns {Promise} Promessa que é concluída após o registro ser removido.
1377
+ */
1378
+ async remove(record, customRequestId) {
1379
+ validateParameter({ record });
1380
+ const remove = async () => {
1381
+ const idField = record[this.schema.idField] ? this.schema.idField : PoSchemaUtil.syncInternalIdFieldName;
1382
+ const serverRecord = PoSchemaUtil.separateSchemaFields(this.schema, record)['serverRecord'];
1383
+ await this.poSchemaService.remove(this.schema.name, record[idField]);
1384
+ await this.eventSourcing.remove(this.schema.name, serverRecord, customRequestId);
1385
+ };
1386
+ return this.poSchemaService.limitedCallWrap(remove);
1387
+ }
1388
+ /**
1389
+ * Altera ou inclui um registro.
1390
+ *
1391
+ * > O registro será alterado se ele possuir um *id*, caso contrário um novo registro será criado.
1392
+ *
1393
+ * @param {object} record Registro que será persistido.
1394
+ * @param {string} customRequestId Identificador customizado do comando.
1395
+ * @returns {Promise} Promessa que é concluída após o registro ser alterado ou incluído.
1396
+ */
1397
+ async save(record, customRequestId) {
1398
+ validateParameter({ record });
1399
+ return this.poSchemaService.limitedCallWrap(this.selectSaveType.bind(this, record, true, customRequestId));
1400
+ }
1401
+ /**
1402
+ * Salva uma lista de registros em lote.
1403
+ *
1404
+ * > Para cada registro da lista, será inserido um novo registro se o mesmo não tiver *id*, caso contrário
1405
+ * será contado como uma atualização de um registro existente.
1406
+ *
1407
+ * @param {Array<object>} records Lista de registros que serão persistidos.
1408
+ * @param {Array<string> | string} customRequestIds Identificador customizado do comando.
1409
+ *
1410
+ * Ao passar uma lista de identificadores, cada índice da lista de identificadores deverá
1411
+ * corresponder ao índice do registro na lista de registros.
1412
+ * @returns {Promise<any>} Promessa que é concluída após os registros serem alterados ou incluídos.
1413
+ */
1414
+ async saveAll(records, customRequestIds) {
1415
+ validateParameter({ records });
1416
+ const saveAll = async () => {
1417
+ const batchEvents = [];
1418
+ for (let index = 0; index < records.length; index++) {
1419
+ const record = records[index];
1420
+ const sendToEventSourcing = false;
1421
+ const isNonLocalRecordChanged = await this.isNonLocalRecordChanged(record);
1422
+ const updatedRecord = await this.selectSaveType(record, sendToEventSourcing);
1423
+ if (isNonLocalRecordChanged) {
1424
+ const customRequestId = customRequestIds instanceof Array ? customRequestIds[index] : customRequestIds;
1425
+ const eventOperation = this.createEventOperation(record, updatedRecord, customRequestId);
1426
+ batchEvents.push(eventOperation);
1427
+ }
1428
+ }
1429
+ await this.eventSourcing.createBatchEvents(this.schema.name, batchEvents);
1430
+ };
1431
+ return this.poSchemaService.limitedCallWrap(saveAll);
1432
+ }
1433
+ async create(newRecord, sendToEventSourcing, customRequestId) {
1434
+ const time = new Date().getTime();
1435
+ const syncProperties = {
1436
+ [PoSchemaUtil.syncInternalIdFieldName]: time,
1437
+ SyncInsertedDateTime: time,
1438
+ SyncUpdatedDateTime: null,
1439
+ SyncExclusionDateTime: null,
1440
+ SyncDeleted: false,
1441
+ SyncStatus: 0
1442
+ };
1443
+ const recordWithSyncProperties = { ...newRecord, ...syncProperties };
1444
+ const recordedData = await this.poSchemaService.create(this.schema, recordWithSyncProperties);
1445
+ if (sendToEventSourcing) {
1446
+ await this.eventSourcing.create(this.schema.name, recordWithSyncProperties, customRequestId);
1447
+ }
1448
+ return recordedData;
1449
+ }
1450
+ createEventOperation(record, updatedRecord, customRequestId) {
1451
+ const operation = PoSchemaUtil.getRecordId(record, this.schema)
1452
+ ? PoEventSourcingOperation.Update
1453
+ : PoEventSourcingOperation.Insert;
1454
+ const serverRecord = PoSchemaUtil.separateSchemaFields(this.schema, updatedRecord)['serverRecord'];
1455
+ return {
1456
+ record: serverRecord,
1457
+ customRequestId: customRequestId,
1458
+ operation: operation
1459
+ };
1460
+ }
1461
+ async isNonLocalRecordChanged(updatedRecord) {
1462
+ const nonLocalFieldNames = PoSchemaUtil.getNonLocalFieldNames(this.schema);
1463
+ const record = await this.poSchemaService.get(this.schema.name, updatedRecord[this.schema.idField]);
1464
+ return !PoSchemaUtil.isModelsEqual(nonLocalFieldNames, record, updatedRecord);
1465
+ }
1466
+ async selectSaveType(record, sendToEventSourcing, customRequestId) {
1467
+ const hasId = PoSchemaUtil.getRecordId(record, this.schema);
1468
+ return hasId
1469
+ ? await this.update(record, sendToEventSourcing, customRequestId)
1470
+ : await this.create(record, sendToEventSourcing, customRequestId);
1471
+ }
1472
+ async update(updatedRecord, sendToEventSourcing, customRequestId) {
1473
+ updatedRecord.SyncUpdatedDateTime = new Date().getTime();
1474
+ updatedRecord.SyncStatus = 0;
1475
+ const isNonLocalRecordChanged = await this.isNonLocalRecordChanged(updatedRecord);
1476
+ const recordedData = await this.poSchemaService.update(this.schema, updatedRecord);
1477
+ if (isNonLocalRecordChanged && sendToEventSourcing) {
1478
+ const serverRecord = PoSchemaUtil.separateSchemaFields(this.schema, updatedRecord)['serverRecord'];
1479
+ await this.eventSourcing.update(this.schema.name, serverRecord, customRequestId);
1480
+ }
1481
+ return recordedData;
1482
+ }
1483
+ }
1484
+
1485
+ /**
1486
+ * @usedBy PoSyncConfig, PoNetworkStatus
1487
+ *
1488
+ * @description
1489
+ *
1490
+ * Tipos de rede existentes no dispositivo.
1491
+ */
1492
+ var PoNetworkType;
1493
+ (function (PoNetworkType) {
1494
+ /** Define o tipo de rede como desconhecido (`unknown`). */
1495
+ PoNetworkType[PoNetworkType["unknown"] = 0] = "unknown";
1496
+ /** Define o tipo de rede como `Ethernet`. */
1497
+ PoNetworkType[PoNetworkType["ethernet"] = 1] = "ethernet";
1498
+ /** Define o tipo de rede como `WiFi`. */
1499
+ PoNetworkType[PoNetworkType["wifi"] = 2] = "wifi";
1500
+ /** Define o tipo de rede como `2G`. */
1501
+ PoNetworkType[PoNetworkType["_2g"] = 3] = "_2g";
1502
+ /** Define o tipo de rede como `3G`. */
1503
+ PoNetworkType[PoNetworkType["_3g"] = 4] = "_3g";
1504
+ /** Define o tipo de rede como `4G`. */
1505
+ PoNetworkType[PoNetworkType["_4g"] = 5] = "_4g";
1506
+ /**
1507
+ * Define o tipo de rede como `cellular`. Isso acontece na utilização dos navegadores
1508
+ * dentro do dispositvo móvel, com exceção do *web view*.
1509
+ */
1510
+ PoNetworkType[PoNetworkType["cellular"] = 6] = "cellular";
1511
+ /** Define o tipo de rede como `none`. */
1512
+ PoNetworkType[PoNetworkType["none"] = 7] = "none";
1513
+ })(PoNetworkType || (PoNetworkType = {}));
1514
+
1515
+ /**
1516
+ * @docsPrivate
1517
+ *
1518
+ * @description
1519
+ *
1520
+ * Classe responsável por implementar a classe `PoDataTransform` com os campos referentes ao padrão de
1521
+ * [API do PO UI](https://po-ui.io/guides/api).
1522
+ */
1523
+ class PoDataMessage extends PoDataTransform {
1524
+ /**
1525
+ * Retorna a propriedade `po_sync_date`, responsável por informar a data da última sincronização no guia de
1526
+ * [API do PO UI](https://po-ui.io/guides/api).
1527
+ *
1528
+ * @returns {string} Nome do campo que contém a data da última sincronização.
1529
+ */
1530
+ getDateFieldName() {
1531
+ return 'po_sync_date';
1532
+ }
1533
+ /**
1534
+ * Retorna a propriedade `items`, responsável por informar a lista de registros vindos da API no guia de
1535
+ * [API do PO UI](https://po-ui.io/guides/api).
1536
+ *
1537
+ * @returns {string} Nome da propriedade que contém a lista de registros.
1538
+ */
1539
+ getItemsFieldName() {
1540
+ return 'items';
1541
+ }
1542
+ /**
1543
+ * Retorna a propriedade `page`, responsável por informar o número da página de registros que a API retorna no guia de
1544
+ * [API do PO UI](https://po-ui.io/guides/api).
1545
+ *
1546
+ * @returns {string} Nome da propriedade responsável por informar o número da página de registros.
1547
+ */
1548
+ getPageParamName() {
1549
+ return 'page';
1550
+ }
1551
+ /**
1552
+ * Retorna a propriedade `pageSize`, responsável pela quantidade de registros que serão exibidos por página no guia de
1553
+ * [API do PO UI](https://po-ui.io/guides/api).
1554
+ *
1555
+ * @returns {string} Nome do parâmetro responsável pela quantidade de registros por página.
1556
+ */
1557
+ getPageSizeParamName() {
1558
+ return 'pageSize';
1559
+ }
1560
+ /**
1561
+ * Retorna um valor `boolean`, de acordo com a propriedade `hasNext` que é responsável por informar se há uma nova
1562
+ * página de registros disponível no guia de [API do PO UI](https://po-ui.io/guides/api).
1563
+ *
1564
+ * @returns {boolean} Informa se tem próxima página de registros.
1565
+ */
1566
+ hasNext() {
1567
+ return this.data.hasNext;
1568
+ }
1569
+ }
1570
+
1571
+ /**
1572
+ * @description
1573
+ *
1574
+ * Classe responsável por identificar a conexão de rede disponível no dispositivo.
1575
+ */
1576
+ class PoNetworkStatus {
1577
+ constructor(networtkType) {
1578
+ this.setNetworkConnection(networtkType);
1579
+ }
1580
+ /**
1581
+ * Retorna se o dispositivo está conectado na rede.
1582
+ *
1583
+ * @returns {boolean} Status da conexão com a rede.
1584
+ */
1585
+ get status() {
1586
+ return this.type !== PoNetworkType.none;
1587
+ }
1588
+ /**
1589
+ * Retorna o tipo de conexão do dispositivo.
1590
+ *
1591
+ * @returns {PoNetworkType} Tipo da conexão com a rede.
1592
+ */
1593
+ get type() {
1594
+ return this._type;
1595
+ }
1596
+ set type(type) {
1597
+ this._type = type;
1598
+ }
1599
+ /* istanbul ignore next */
1600
+ setDefaultTypeNavigation() {
1601
+ return navigator.onLine ? PoNetworkType['ethernet'] : PoNetworkType.none;
1602
+ }
1603
+ setNetworkConnection(networtkType) {
1604
+ if (!networtkType) {
1605
+ this.type = this.setDefaultTypeNavigation();
1606
+ }
1607
+ else {
1608
+ const isGenerationMobile = ['2g', '3g', '4g'].includes(networtkType);
1609
+ this.type = isGenerationMobile ? PoNetworkType['_' + networtkType] : PoNetworkType[String(networtkType)];
1610
+ }
1611
+ }
1612
+ }
1613
+
1614
+ /**
1615
+ * @description
1616
+ *
1617
+ * O `PoNetworkService` é utilizado para verificar o status e o tipo da conexão de rede do dispositivo.
1618
+ */
1619
+ class PoNetworkService {
1620
+ constructor(network) {
1621
+ this.initNetwork(network);
1622
+ }
1623
+ /**
1624
+ * Retorna as propriedades tipo e status da conexão do dispositivo no momento da chamada.
1625
+ *
1626
+ * @returns {PoNetworkStatus} Instância de [PoNetworkStatus](/documentation/po-network-status) com as
1627
+ * propriedades da conexão.
1628
+ */
1629
+ getConnectionStatus() {
1630
+ this.poNetworkStatus = new PoNetworkStatus(this.networkType);
1631
+ return this.poNetworkStatus;
1632
+ }
1633
+ /**
1634
+ * Notifica as mudanças no tipo de conexão de rede do dispositivo.
1635
+ *
1636
+ * @returns {Observable<{ status: boolean, type: string }>} Observable com as propriedades da conexão.
1637
+ */
1638
+ onChange() {
1639
+ return this.networkTypeNow.asObservable();
1640
+ }
1641
+ getNavigatorStatus() {
1642
+ return merge(fromEvent(window, 'offline').pipe(mapTo(false)), fromEvent(window, 'online').pipe(mapTo(true)), Observable.create(sub => {
1643
+ sub.next(navigator.onLine);
1644
+ sub.complete();
1645
+ }));
1646
+ }
1647
+ initNetwork(network) {
1648
+ this.networkTypeNow = new Subject();
1649
+ this.initSubscriber(network);
1650
+ }
1651
+ initSubscriber(network) {
1652
+ if (network) {
1653
+ this.getNavigatorStatus().subscribe(status => {
1654
+ this.networkType = network.type;
1655
+ this.networkTypeNow.next({ status: status, type: this.networkType });
1656
+ });
1657
+ }
1658
+ }
1659
+ }
1660
+ PoNetworkService.ɵfac = function PoNetworkService_Factory(t) { return new (t || PoNetworkService)(i0.ɵɵinject(i1$2.Network)); };
1661
+ PoNetworkService.ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: PoNetworkService, factory: PoNetworkService.ɵfac });
1662
+ (function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(PoNetworkService, [{
1663
+ type: Injectable
1664
+ }], function () { return [{ type: i1$2.Network }]; }, null); })();
1665
+
1666
+ /**
1667
+ * @description
1668
+ *
1669
+ * O `PoSyncService` é utilizado para configurar toda a base de dados que receberá as informações que serão
1670
+ * armazenadas *offline* vindas do servidor. Nele ocorre toda a preparação dos modelos de dados retornados por
1671
+ * cada consulta.
1672
+ */
1673
+ class PoSyncService {
1674
+ constructor(poEventSourcingService, poHttpClient, poNetworkService, poSchemaDefinitionService, poSchemaService) {
1675
+ this.poEventSourcingService = poEventSourcingService;
1676
+ this.poHttpClient = poHttpClient;
1677
+ this.poNetworkService = poNetworkService;
1678
+ this.poSchemaDefinitionService = poSchemaDefinitionService;
1679
+ this.poSchemaService = poSchemaService;
1680
+ this.models = [];
1681
+ this.finishSyncSubject = new Subject();
1682
+ this.isSyncEnabled = true;
1683
+ this.syncing = false;
1684
+ }
1685
+ /**
1686
+ * Destrói todas as chaves do *storage* referentes ao `po-sync`, ou seja,
1687
+ * as definições dos *schemas*, os registros de cada *schema* e a fila
1688
+ * de eventos que estão para ser enviados ao servidor *(EventSourcing)*.
1689
+ *
1690
+ * > Para que não venham ocorrer erros em ações que dependam das definições dos *schemas*,
1691
+ * recomenda-se utilizar o método `prepare()` em seguida.
1692
+ *
1693
+ * > Veja mais detalhes em [Fundamentos do PO Sync - Alterando as definições dos schemas](/guides/sync-fundamentals).
1694
+ *
1695
+ * @returns {Promise<any>} Promessa que é resolvida quando as chaves referentes ao `po-sync` forem destruídas.
1696
+ */
1697
+ async destroy() {
1698
+ const destroyFunction = async () => {
1699
+ await this.poSchemaService.destroySchemasRecords();
1700
+ await this.poSchemaDefinitionService.destroy();
1701
+ await this.poEventSourcingService.destroyEventSourcingQueue();
1702
+ };
1703
+ return this.poSchemaService.limitedCallWrap(destroyFunction);
1704
+ }
1705
+ /**
1706
+ * Desabilita todos os tipos de sincronização de dados (periódica, reativa e manual).
1707
+ *
1708
+ * > Para habilitar novamente a sincronização utilize o método [`PoSyncService.enableSync()`](documentation/po-sync#enable-sync).
1709
+ */
1710
+ disableSync() {
1711
+ this.isSyncEnabled = false;
1712
+ if (this.timer && this.subscription) {
1713
+ this.subscription.unsubscribe();
1714
+ }
1715
+ }
1716
+ /**
1717
+ * <a id="enable-sync"></a>
1718
+ * Habilita todos os tipos de sincronização de dados (periódica, reativa e manual).
1719
+ *
1720
+ * Por padrão, sempre que se inicializa uma aplicação com PO Sync as sincronizações já estão habilitadas.
1721
+ */
1722
+ enableSync() {
1723
+ this.isSyncEnabled = true;
1724
+ this.createSubscribe();
1725
+ }
1726
+ /**
1727
+ * Método que disponibiliza a partir de sua inscrição o evento de retorno das operações da fila de eventos que
1728
+ * foram enviadas ao servidor. A cada operação enviada para o servidor, será disparado um evento para a inscrição
1729
+ * deste método.
1730
+ *
1731
+ * > Veja mais detalhes em [Fundamentos do PO Sync - Capturando respostas da sincronização](/guides/sync-fundamentals).
1732
+ *
1733
+ * @returns {Observable<PoSyncResponse>} Observable com um objeto do tipo `PoSyncResponse`.
1734
+ */
1735
+ getResponses() {
1736
+ return this.poEventSourcingService.responsesSubject();
1737
+ }
1738
+ /**
1739
+ * Retorna uma instância de `PoEntity` para um determinado *schema*.
1740
+ *
1741
+ * > Veja mais detalhes em [Fundamentos do PO Sync - Manipulando os registros de um schema](/guides/sync-fundamentals).
1742
+ *
1743
+ * @param {string} schemaName Nome do *schema*.
1744
+ * @returns {PoEntity} Objeto para efetuar consultas e alterações nos dados.
1745
+ */
1746
+ getModel(schemaName) {
1747
+ const model = this.models[schemaName];
1748
+ if (!model) {
1749
+ throw new Error('Model not found: ' + schemaName);
1750
+ }
1751
+ return model;
1752
+ }
1753
+ /**
1754
+ * Insere uma requisição HTTP na fila de eventos do `po-sync`.
1755
+ *
1756
+ * > Veja mais detalhes em [Fundamentos do PO Sync - Inserindo requisições HTTP na fila de eventos](/guides/sync-fundamentals).
1757
+ *
1758
+ * @param {PoHttpRequestData} poHttpRequestData Dados da requisição HTTP.
1759
+ * @param {string} customRequestId Identificador customizado da requisição HTTP.
1760
+ * @returns {Promise<number>} Promessa com o identificador da requisição HTTP criada.
1761
+ */
1762
+ insertHttpCommand(requestData, customRequestId) {
1763
+ validateParameter({ requestData });
1764
+ return this.poEventSourcingService.httpCommand(requestData, customRequestId);
1765
+ }
1766
+ /**
1767
+ * Efetua uma chamada na API do servidor para realizar a carga inicial dos dados. Deve ser chamado apenas uma vez
1768
+ * na aplicação, após a preparação dos *schemas* realizada através do método `PoSyncService.prepare()`.
1769
+ *
1770
+ * > Veja mais detalhes em [Fundamentos do PO Sync - Carga inicial dos dados](/guides/sync-fundamentals).
1771
+ *
1772
+ * @returns {Observable<Array<{ entity: string, data: Array<any> }>>} Observable que notificará quando a
1773
+ * carga inicial for concluída.
1774
+ */
1775
+ loadData() {
1776
+ const loads = [];
1777
+ this.schemas.forEach(el => loads.push(this.loadEntityData(el)));
1778
+ return forkJoin(loads);
1779
+ }
1780
+ /**
1781
+ * Responsável por notificar sempre que houver sincronismo.
1782
+ *
1783
+ * > Veja mais detalhes em [Fundamentos do PO Sync - Notificação pós-sincronização](/guides/sync-fundamentals).
1784
+ *
1785
+ * @returns {Observable<any>} Observable que é disparado a cada sincronismo realizado.
1786
+ */
1787
+ onSync() {
1788
+ if (!this.eventSub) {
1789
+ this.eventSub = Observable.create(e => {
1790
+ this.emitter = e;
1791
+ });
1792
+ }
1793
+ return this.eventSub;
1794
+ }
1795
+ /**
1796
+ * Prepara a aplicação criando os schemas e aplica as configurações.
1797
+ *
1798
+ * > Veja mais detalhes em [Fundamentos do PO Sync - Preparando a aplicação](/guides/sync-fundamentals).
1799
+ *
1800
+ * @param {Array<PoSyncSchema>} schemas Lista de *schemas* a serem preparados.
1801
+ * @param {PoSyncConfig} config Configurações adicionais.
1802
+ * @returns {Promise<any>} Promessa que é resolvida quando a aplicação estiver preparada para a utilização do `po-sync`.
1803
+ */
1804
+ prepare(schemas, config) {
1805
+ validateArray({ schemas });
1806
+ const defaultSyncConfig = {
1807
+ type: this.poNetworkService.getConnectionStatus().type,
1808
+ period: 60,
1809
+ dataTransform: new PoDataMessage()
1810
+ };
1811
+ this.schemas = schemas;
1812
+ this.config = config || defaultSyncConfig;
1813
+ this.config.dataTransform = this.config.dataTransform || new PoDataMessage();
1814
+ this.poEventSourcingService.config = this.config;
1815
+ this.startTimer(this.config.period);
1816
+ this.reactiveSync();
1817
+ this.poEventSourcingService.onSaveData().subscribe(() => this.sync());
1818
+ return this.saveSchemas().then(() => {
1819
+ this.schemas.forEach(schema => {
1820
+ this.models[schema.name] = new PoEntity(this.poEventSourcingService, schema, this.poSchemaService);
1821
+ });
1822
+ return Promise.resolve();
1823
+ });
1824
+ }
1825
+ /**
1826
+ * Remove um item da fila de eventos que espera a sincronização.
1827
+ *
1828
+ * > Veja mais detalhes em [Fundamentos do PO Sync - Capturando respostas da sincronização](/guides/sync-fundamentals).
1829
+ *
1830
+ * @param {any} idEventSourcing Identificador do item da fila de eventos.
1831
+ * @returns {Promise<any>} Promessa que é resolvida quando o item da fila de eventos é removido.
1832
+ */
1833
+ removeItemOfSync(idEventSourcing) {
1834
+ return this.poEventSourcingService.removeEventSourcingItem(idEventSourcing);
1835
+ }
1836
+ /**
1837
+ * Reenvia os comandos pendentes na fila (inclusão, alteração e exclusão) e busca novos dados do servidor.
1838
+ *
1839
+ * > Veja mais detalhes em [Fundamentos do PO Sync - Capturando respostas da sincronização](/guides/sync-fundamentals).
1840
+ *
1841
+ * @returns {Promise<any>} Promessa que resolve o sincronismo disparado.
1842
+ */
1843
+ resumeSync() {
1844
+ if (!this.canSync()) {
1845
+ const finishSyncSubscription = this.finishSyncSubject.asObservable().subscribe(() => {
1846
+ finishSyncSubscription.unsubscribe();
1847
+ return this.sync();
1848
+ });
1849
+ return Promise.resolve();
1850
+ }
1851
+ return this.sync();
1852
+ }
1853
+ /**
1854
+ * Dispara o sincronismo enviando os eventos pendentes (inclusão, alteração e exclusão) e buscando novos dados do servidor.
1855
+ *
1856
+ * O sincronismo somente será executado depois que o acesso a base de dados local do dispositivo for liberada.
1857
+ *
1858
+ * > Veja mais detalhes em [Fundamentos do PO Sync - Sincronização manual](/guides/sync-fundamentals).
1859
+ *
1860
+ * @returns {Promise<any>} Promessa que é resolvida quando o sincronismo for finalizado.
1861
+ */
1862
+ async sync() {
1863
+ if (this.canSync()) {
1864
+ this.startSync();
1865
+ try {
1866
+ await this.poEventSourcingService.syncSend();
1867
+ await this.poEventSourcingService.syncGet();
1868
+ if (this.emitter) {
1869
+ this.emitter.next();
1870
+ }
1871
+ this.finishSync();
1872
+ }
1873
+ catch (error) {
1874
+ this.syncError();
1875
+ }
1876
+ }
1877
+ }
1878
+ canSync() {
1879
+ if (this.syncing || !this.isSyncEnabled) {
1880
+ return false;
1881
+ }
1882
+ else {
1883
+ const currentConnection = this.poNetworkService.getConnectionStatus();
1884
+ const isConfiguredConnection = this.config && currentConnection.type === this.config.type;
1885
+ const isConfigIncludesType = this.config && this.config.type instanceof Array && this.config.type.includes(currentConnection.type);
1886
+ return currentConnection.status && (!this.config || isConfiguredConnection || isConfigIncludesType);
1887
+ }
1888
+ }
1889
+ createSubscribe() {
1890
+ if (this.timer) {
1891
+ this.subscription = this.timer.subscribe(() => {
1892
+ this.sync().then(() => {
1893
+ this.subscription.unsubscribe();
1894
+ this.subscription = null;
1895
+ this.timer = null;
1896
+ this.startTimer(this.config.period);
1897
+ });
1898
+ });
1899
+ }
1900
+ }
1901
+ finishSync() {
1902
+ this.syncing = false;
1903
+ this.finishSyncSubject.next(null);
1904
+ }
1905
+ getOnePage(schema, page = 1) {
1906
+ const params = [];
1907
+ params.push(`${this.config.dataTransform.getPageSizeParamName()}=${schema.pageSize}`);
1908
+ params.push(`${this.config.dataTransform.getPageParamName()}=${page}`);
1909
+ const url = `${PoSchemaUtil.getUrl(schema, PoRequestType.GET)}?${params.join('&')}`;
1910
+ return this.poHttpClient.get(url).pipe(map(response => response.body), mergeMap(responseBody => {
1911
+ const now = new Date().getTime();
1912
+ responseBody[this.config.dataTransform.getItemsFieldName()].map(item => {
1913
+ item.SyncInsertedDateTime = now;
1914
+ item.SyncUpdatedDateTime = null;
1915
+ item.SyncExclusionDateTime = null;
1916
+ item.SyncDeleted = false;
1917
+ item.SyncStatus = 2;
1918
+ });
1919
+ return this.poSchemaService
1920
+ .updateAll(schema, responseBody[this.config.dataTransform.getItemsFieldName()])
1921
+ .then(() => responseBody);
1922
+ }));
1923
+ }
1924
+ loadEntityData(schema) {
1925
+ let page = 1;
1926
+ return this.getOnePage(schema, page).pipe(expand(data => {
1927
+ this.config.dataTransform.transform(data);
1928
+ const hasNext = this.config.dataTransform.hasNext();
1929
+ if (hasNext) {
1930
+ return this.getOnePage(schema, ++page);
1931
+ }
1932
+ else {
1933
+ return of();
1934
+ }
1935
+ }), reduce((acc, obj) => {
1936
+ acc.data = acc.data.concat(obj[this.config.dataTransform.getItemsFieldName()]);
1937
+ return acc;
1938
+ }, {
1939
+ entity: schema.name,
1940
+ data: []
1941
+ }));
1942
+ }
1943
+ reactiveSync() {
1944
+ this.poNetworkService.onChange().subscribe(networkStatus => {
1945
+ if (networkStatus.status) {
1946
+ this.startTimer(this.config.period);
1947
+ return this.sync();
1948
+ }
1949
+ if (this.subscription) {
1950
+ this.subscription.unsubscribe();
1951
+ }
1952
+ });
1953
+ }
1954
+ async saveSchemas() {
1955
+ const storageSchemas = await this.poSchemaDefinitionService.getAll();
1956
+ this.schemas.forEach(schema => (schema.lastSync = PoSchemaUtil.getLastSync(storageSchemas, schema.name)));
1957
+ return this.poSchemaDefinitionService.saveAll(this.schemas);
1958
+ }
1959
+ startSync() {
1960
+ this.syncing = true;
1961
+ }
1962
+ startTimer(period) {
1963
+ if (period && this.isSyncEnabled) {
1964
+ this.timer = timer(period * 1000);
1965
+ this.createSubscribe();
1966
+ }
1967
+ }
1968
+ syncError() {
1969
+ this.finishSync();
1970
+ }
1971
+ }
1972
+ PoSyncService.ɵfac = function PoSyncService_Factory(t) { return new (t || PoSyncService)(i0.ɵɵinject(PoEventSourcingService), i0.ɵɵinject(PoHttpClientService), i0.ɵɵinject(PoNetworkService), i0.ɵɵinject(PoSchemaDefinitionService), i0.ɵɵinject(PoSchemaService)); };
1973
+ PoSyncService.ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: PoSyncService, factory: PoSyncService.ɵfac });
1974
+ (function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(PoSyncService, [{
1975
+ type: Injectable
1976
+ }], function () { return [{ type: PoEventSourcingService }, { type: PoHttpClientService }, { type: PoNetworkService }, { type: PoSchemaDefinitionService }, { type: PoSchemaService }]; }, null); })();
1977
+
1978
+ /**
1979
+ * @description
1980
+ *
1981
+ * Módulo do componente PoSync responsável pela sincronia de dados com backends
1982
+ */
1983
+ class PoSyncModule {
1984
+ }
1985
+ PoSyncModule.ɵfac = function PoSyncModule_Factory(t) { return new (t || PoSyncModule)(); };
1986
+ PoSyncModule.ɵmod = /*@__PURE__*/ i0.ɵɵdefineNgModule({ type: PoSyncModule });
1987
+ PoSyncModule.ɵinj = /*@__PURE__*/ i0.ɵɵdefineInjector({ providers: [
1988
+ PoEventSourcingService,
1989
+ PoNetworkService,
1990
+ PoSchemaDefinitionService,
1991
+ PoSchemaService,
1992
+ PoSyncService,
1993
+ PoHttpClientService,
1994
+ Network
1995
+ ], imports: [[HttpClientModule]] });
1996
+ (function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(PoSyncModule, [{
1997
+ type: NgModule,
1998
+ args: [{
1999
+ providers: [
2000
+ PoEventSourcingService,
2001
+ PoNetworkService,
2002
+ PoSchemaDefinitionService,
2003
+ PoSchemaService,
2004
+ PoSyncService,
2005
+ PoHttpClientService,
2006
+ Network
2007
+ ],
2008
+ imports: [HttpClientModule]
2009
+ }]
2010
+ }], null, null); })();
2011
+ (function () { (typeof ngJitMode === "undefined" || ngJitMode) && i0.ɵɵsetNgModuleScope(PoSyncModule, { imports: [HttpClientModule] }); })();
2012
+
2013
+ /**
2014
+ * Generated bundle index. Do not edit.
2015
+ */
2016
+
2017
+ export { PoDataTransform, PoEntity, PoEventSourcingErrorResponse, PoEventSourcingService, PoHttpClientService, PoHttpRequestType, PoNetworkService, PoNetworkType, PoSyncModule, PoSyncService };
2018
+ //# sourceMappingURL=po-ui-ng-sync.mjs.map