@sincpro/mobile 0.4.4 → 1.0.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 (165) hide show
  1. package/README.md +3 -3
  2. package/dist/adapters/JsonSerializer.adapter.d.ts +1 -1
  3. package/dist/adapters/JsonSerializer.adapter.js +2 -2
  4. package/dist/adapters/repositories/database_table.repository.d.ts +3 -2
  5. package/dist/adapters/repositories/database_table.repository.js +1 -1
  6. package/dist/adapters/repositories/document.repository.d.ts +81 -0
  7. package/dist/adapters/repositories/document.repository.js +653 -0
  8. package/dist/adapters/repositories/domain_event.repository.d.ts +17 -17
  9. package/dist/adapters/repositories/domain_event.repository.js +25 -31
  10. package/dist/adapters/repositories/domain_event_dead_letter.repository.d.ts +10 -10
  11. package/dist/adapters/repositories/domain_event_dead_letter.repository.js +14 -13
  12. package/dist/adapters/repositories/event_row.d.ts +13 -0
  13. package/dist/adapters/repositories/event_row.js +22 -0
  14. package/dist/adapters/repositories/sqlite_document_store.d.ts +33 -0
  15. package/dist/adapters/repositories/sqlite_document_store.js +201 -0
  16. package/dist/domain/connectivity/events.d.ts +5 -5
  17. package/dist/domain/connectivity/events.js +3 -3
  18. package/dist/domain/database/criteria.d.ts +19 -0
  19. package/dist/domain/database/criteria.js +36 -0
  20. package/dist/domain/database/criteria_clock.d.ts +8 -0
  21. package/dist/domain/database/criteria_clock.js +305 -0
  22. package/dist/domain/database/criteria_sql.d.ts +61 -0
  23. package/dist/domain/database/criteria_sql.js +476 -0
  24. package/dist/domain/database/database.d.ts +1 -0
  25. package/dist/domain/database/index.d.ts +3 -1
  26. package/dist/domain/database/index.js +3 -1
  27. package/dist/domain/database/migration_plan.d.ts +14 -0
  28. package/dist/domain/database/migration_plan.js +44 -0
  29. package/dist/domain/entity/change_tracking.d.ts +21 -0
  30. package/dist/domain/entity/change_tracking.js +71 -0
  31. package/dist/domain/entity/checks.d.ts +8 -0
  32. package/dist/domain/entity/checks.js +82 -0
  33. package/dist/domain/entity/entity.d.ts +39 -32
  34. package/dist/domain/entity/entity.js +94 -105
  35. package/dist/domain/entity/entity_collection.d.ts +15 -30
  36. package/dist/domain/entity/entity_collection.js +30 -121
  37. package/dist/domain/entity/index.d.ts +5 -0
  38. package/dist/domain/entity/index.js +5 -0
  39. package/dist/domain/entity/reconcile.d.ts +7 -0
  40. package/dist/domain/entity/reconcile.js +12 -0
  41. package/dist/domain/entity/relations.d.ts +27 -0
  42. package/dist/domain/entity/relations.js +69 -0
  43. package/dist/domain/entity/remote_sync.d.ts +4 -0
  44. package/dist/domain/entity/remote_sync.js +19 -0
  45. package/dist/domain/entity/values.d.ts +6 -0
  46. package/dist/domain/entity/values.js +13 -0
  47. package/dist/domain/events/catalog.d.ts +29 -0
  48. package/dist/domain/{events.js → events/catalog.js} +7 -11
  49. package/dist/domain/events/chain.d.ts +5 -0
  50. package/dist/domain/events/chain.js +6 -0
  51. package/dist/domain/{event_sourcing → events}/domain_event.d.ts +20 -22
  52. package/dist/domain/events/domain_event.js +227 -0
  53. package/dist/domain/events/index.d.ts +8 -0
  54. package/dist/domain/events/index.js +8 -0
  55. package/dist/domain/events/integration_event.d.ts +103 -0
  56. package/dist/domain/events/integration_event.js +72 -0
  57. package/dist/domain/events/label.d.ts +2 -0
  58. package/dist/domain/events/label.js +26 -0
  59. package/dist/domain/index.d.ts +0 -1
  60. package/dist/domain/index.js +0 -1
  61. package/dist/domain/print/events.d.ts +8 -4
  62. package/dist/domain/print/events.js +9 -4
  63. package/dist/domain/repositories/document_store.d.ts +33 -0
  64. package/dist/domain/repositories/document_store.js +5 -0
  65. package/dist/domain/repositories/hooks.d.ts +23 -0
  66. package/dist/domain/repositories/hooks.js +32 -0
  67. package/dist/domain/repositories/index.d.ts +4 -0
  68. package/dist/domain/repositories/index.js +4 -0
  69. package/dist/domain/{database → repositories}/repository.d.ts +9 -3
  70. package/dist/domain/settings.d.ts +4 -1
  71. package/dist/domain/settings.js +3 -0
  72. package/dist/domain/webview/events.d.ts +2 -2
  73. package/dist/domain/webview/events.js +2 -2
  74. package/dist/entrypoints/db/migrations.js +10 -10
  75. package/dist/entrypoints/queue/QueueProcessor.d.ts +1 -1
  76. package/dist/entrypoints/queue/activateDomain.subscriber.d.ts +2 -2
  77. package/dist/entrypoints/queue/activateDomain.subscriber.js +2 -2
  78. package/dist/entrypoints/queue/newAppSettings.handler.d.ts +2 -2
  79. package/dist/entrypoints/queue/newAppSettings.handler.js +1 -1
  80. package/dist/entrypoints/queue/printImage.subscriber.d.ts +1 -1
  81. package/dist/entrypoints/queue/printImage.subscriber.js +2 -2
  82. package/dist/entrypoints/queue/processWebViewMessage.subscriber.d.ts +1 -1
  83. package/dist/entrypoints/queue/processWebViewMessage.subscriber.js +1 -1
  84. package/dist/entrypoints/ui/AppShell.js +2 -2
  85. package/dist/entrypoints/ui/common_provider.d.ts +0 -12
  86. package/dist/entrypoints/ui/common_provider.js +2 -131
  87. package/dist/event_driven/index.d.ts +1 -0
  88. package/dist/event_driven/index.js +1 -0
  89. package/dist/{domain/event_sourcing/event_handler.d.ts → event_driven/subscriber.d.ts} +1 -1
  90. package/dist/exceptions.d.ts +21 -0
  91. package/dist/exceptions.js +30 -0
  92. package/dist/framework/base_module.d.ts +1 -1
  93. package/dist/framework/createApp.d.ts +3 -3
  94. package/dist/framework/domain_module.d.ts +1 -1
  95. package/dist/framework/kernel.d.ts +1 -1
  96. package/dist/framework/kernel.js +17 -8
  97. package/dist/infrastructure/database/connector.d.ts +2 -0
  98. package/dist/infrastructure/database/connector.js +22 -0
  99. package/dist/infrastructure/database/index.d.ts +1 -0
  100. package/dist/infrastructure/database/index.js +1 -0
  101. package/dist/infrastructure/database/schema.d.ts +9 -0
  102. package/dist/infrastructure/database/schema.js +61 -0
  103. package/dist/infrastructure/database/utils.d.ts +2 -0
  104. package/dist/infrastructure/database/utils.js +12 -4
  105. package/dist/infrastructure/event_chain.d.ts +6 -0
  106. package/dist/infrastructure/event_chain.js +25 -0
  107. package/dist/infrastructure/telemetry/tracing/tracing_hooks.js +8 -5
  108. package/dist/infrastructure/ui/UIEventBus.d.ts +3 -1
  109. package/dist/infrastructure/ui/UIEventBus.js +8 -1
  110. package/dist/infrastructure/ui/activity.d.ts +37 -0
  111. package/dist/infrastructure/ui/activity.js +84 -0
  112. package/dist/infrastructure/workers/CronWorker.d.ts +6 -4
  113. package/dist/infrastructure/workers/CronWorker.js +24 -18
  114. package/dist/infrastructure/workers/EventBus.d.ts +9 -5
  115. package/dist/infrastructure/workers/EventBus.js +68 -33
  116. package/dist/services/bluetooth.service.js +16 -14
  117. package/dist/services/dead_letter_queue.service.d.ts +7 -7
  118. package/dist/services/dead_letter_queue.service.js +0 -2
  119. package/dist/services/event.service.d.ts +3 -3
  120. package/dist/services/event.service.js +1 -1
  121. package/dist/services/network.service.d.ts +1 -1
  122. package/dist/services/network.service.js +17 -15
  123. package/dist/services/printer.service.d.ts +1 -1
  124. package/dist/services/printer.service.js +50 -44
  125. package/dist/tools/utils/date.js +4 -3
  126. package/dist/tools/utils/monetary.d.ts +6 -3
  127. package/dist/tools/utils/monetary.js +33 -21
  128. package/dist/tools/utils/serializer.d.ts +1 -1
  129. package/dist/tools/utils/serializer.js +32 -35
  130. package/dist/ui/activity/DeviceNotices.d.ts +1 -0
  131. package/dist/ui/activity/DeviceNotices.js +29 -0
  132. package/dist/ui/activity/ProcessToast.d.ts +2 -0
  133. package/dist/ui/activity/ProcessToast.js +71 -0
  134. package/dist/ui/activity/index.d.ts +4 -0
  135. package/dist/ui/activity/index.js +4 -0
  136. package/dist/ui/activity/useActivity.d.ts +9 -0
  137. package/dist/ui/activity/useActivity.js +48 -0
  138. package/dist/ui/components/molecules/EventTimelineItem.d.ts +2 -2
  139. package/dist/ui/components/molecules/EventTimelineItem.js +1 -1
  140. package/dist/ui/components/molecules/index.d.ts +1 -2
  141. package/dist/ui/components/molecules/index.js +1 -2
  142. package/dist/ui/components/organisms/DeadLetterQueueRow.d.ts +3 -3
  143. package/dist/ui/components/organisms/EventRow.d.ts +3 -3
  144. package/dist/ui/components/organisms/EventRow.js +1 -1
  145. package/dist/ui/screens/dead_letter_queue/dead_letter_queue.context.d.ts +5 -5
  146. package/dist/ui/screens/events/events.context.d.ts +4 -4
  147. package/package.json +13 -8
  148. package/dist/domain/event_sourcing/domain_event.js +0 -164
  149. package/dist/domain/event_sourcing/event.d.ts +0 -25
  150. package/dist/domain/event_sourcing/event.js +0 -25
  151. package/dist/domain/event_sourcing/index.d.ts +0 -2
  152. package/dist/domain/event_sourcing/index.js +0 -2
  153. package/dist/domain/events.d.ts +0 -33
  154. package/dist/infrastructure/ui/ToastHost.d.ts +0 -6
  155. package/dist/infrastructure/ui/ToastHost.js +0 -28
  156. package/dist/infrastructure/ui/events.d.ts +0 -1
  157. package/dist/infrastructure/ui/events.js +0 -1
  158. package/dist/ui/components/molecules/ProcessToast.d.ts +0 -8
  159. package/dist/ui/components/molecules/ProcessToast.js +0 -52
  160. /package/dist/domain/{repositories.d.ts → repositories/catalog.d.ts} +0 -0
  161. /package/dist/domain/{repositories.js → repositories/catalog.js} +0 -0
  162. /package/dist/domain/{database → repositories}/repository.js +0 -0
  163. /package/dist/{domain/event_sourcing/event_handler.js → event_driven/subscriber.js} +0 -0
  164. /package/dist/ui/{components/molecules → activity}/ProcessToastProvider.d.ts +0 -0
  165. /package/dist/ui/{components/molecules → activity}/ProcessToastProvider.js +0 -0
@@ -1,8 +1,10 @@
1
1
  import { DomainEventRepository } from "../../adapters/repositories/domain_event.repository";
2
2
  import { DomainEventDeadLetterRepository } from "../../adapters/repositories/domain_event_dead_letter.repository";
3
- import { InternetIsDownEvent, InternetIsUpEvent, QueueEndEvent, QueueStartEvent, } from "../../domain/events";
4
- import { DomainNetworkError } from "../../exceptions";
3
+ import { InternetIsDownEvent, InternetIsUpEvent } from "../../domain/events";
4
+ import { DomainNetworkError, RepeatableFailure } from "../../exceptions";
5
+ import { runWithChain } from "../../infrastructure/event_chain";
5
6
  import { loggerQueueProcessor } from "../../infrastructure/logger";
7
+ import { declaresUi, publishActivity } from "../../infrastructure/ui/activity";
6
8
  import { UIEventBus } from "../../infrastructure/ui/UIEventBus";
7
9
  export const PROCESS_WORKER_MAX_ATTEMPTS = 1;
8
10
  export class EventBus {
@@ -12,11 +14,15 @@ export class EventBus {
12
14
  static BACKOFF_MULTIPLIER = 1.5;
13
15
  static subscribers = new Map();
14
16
  static isDraining = false;
17
+ static connectivityReady = false;
15
18
  static intervalId = null;
16
19
  static internetConnected = true;
17
20
  static consecutiveFailures = 0;
18
21
  static currentInterval = EventBus.INTERVAL_MS;
19
22
  static initConnectivityListeners() {
23
+ if (this.connectivityReady)
24
+ return;
25
+ this.connectivityReady = true;
20
26
  UIEventBus.on(InternetIsDownEvent.name, () => {
21
27
  this.internetConnected = false;
22
28
  this.consecutiveFailures++;
@@ -102,27 +108,22 @@ export class EventBus {
102
108
  }
103
109
  }
104
110
  /**
105
- * Validates event, logs start, emits START.
111
+ * Logs the start and publishes a running activity when a subscriber exists.
106
112
  * Returns false if no subscribers (caller should return early).
107
113
  */
108
114
  static preProcess(event) {
109
115
  const hasSubscribers = this.subscribers.has(event.name);
110
116
  loggerQueueProcessor.info(`EVENT=${event.name} [${event.label}] (attempt ${event.attempts}/${EventBus.MAX_ATTEMPTS}) - STARTED`);
111
117
  loggerQueueProcessor.debug(`EVENT=${event.name} uuid=${event.uuid} payload=${event.asJSON()}`);
112
- const queueStartEvent = QueueStartEvent.create();
113
- UIEventBus.emit(queueStartEvent.name, {
114
- event: event.name,
115
- label: event.label,
116
- attempts: event.attempts,
117
- attemptLimit: EventBus.MAX_ATTEMPTS,
118
- });
118
+ if (hasSubscribers)
119
+ this.publishQueue(event, "running");
119
120
  if (!hasSubscribers) {
120
121
  loggerQueueProcessor.warn(`EVENT=${event.name} [${event.label}] - No subscribers registered`);
121
122
  }
122
123
  return hasSubscribers;
123
124
  }
124
125
  /**
125
- * Handles persistence, emits event and END, logs result.
126
+ * Handles persistence, emits the event for screens, publishes the activity, logs result.
126
127
  * If errors is empty -> success, otherwise -> failure + dead letter + throws.
127
128
  * @throws Error if there are any errors
128
129
  */
@@ -141,14 +142,7 @@ export class EventBus {
141
142
  loggerQueueProcessor.warn(`EVENT=${event.name} [${event.label}] (attempt ${event.attempts}/${EventBus.MAX_ATTEMPTS}) - FAILED: ${errorMessage}`);
142
143
  }
143
144
  UIEventBus.emit(event.name, event);
144
- UIEventBus.emit(QueueEndEvent.name, {
145
- event: event.name,
146
- label: event.label,
147
- success,
148
- attempts: event.attempts,
149
- attemptLimit: EventBus.MAX_ATTEMPTS,
150
- error: errorMessage,
151
- });
145
+ this.publishQueue(event, success ? "succeeded" : "failed", errorMessage);
152
146
  if (!success) {
153
147
  throw new Error(errorMessage);
154
148
  }
@@ -162,12 +156,15 @@ export class EventBus {
162
156
  }
163
157
  catch (err) {
164
158
  const errorMessage = err instanceof Error ? err.message : String(err);
165
- errors.push(errorMessage);
166
159
  loggerQueueProcessor.warn(`EVENT=${event.name} - Subscriber failed: ${errorMessage}`);
167
- if (err instanceof DomainNetworkError) {
168
- this.internetConnected = false;
169
- UIEventBus.emit(InternetIsDownEvent.name);
160
+ if (err instanceof DomainNetworkError || err instanceof RepeatableFailure) {
161
+ if (err instanceof DomainNetworkError) {
162
+ this.internetConnected = false;
163
+ UIEventBus.emit(InternetIsDownEvent.name);
164
+ }
165
+ throw new RepeatableFailure(errorMessage);
170
166
  }
167
+ errors.push(errorMessage);
171
168
  }
172
169
  }
173
170
  return errors;
@@ -220,7 +217,12 @@ export class EventBus {
220
217
  /**
221
218
  * Publishes a DomainEvent asynchronously - enqueues for later processing.
222
219
  */
220
+ static schedule() {
221
+ this.triggerProcessing();
222
+ }
223
223
  static async publish(event) {
224
+ if (!event.correlationId)
225
+ event.applyChain(event.uuid);
224
226
  loggerQueueProcessor.info(`EVENT=${event.name} [${event.label}] - Published ASYNC`);
225
227
  await DomainEventRepository.save(event);
226
228
  this.triggerProcessing();
@@ -231,6 +233,8 @@ export class EventBus {
231
233
  * @throws Error if any subscriber fails or no subscribers registered
232
234
  */
233
235
  static async publishSync(event) {
236
+ if (!event.correlationId)
237
+ event.applyChain(event.uuid);
234
238
  loggerQueueProcessor.info(`EVENT=${event.name} [${event.label}] - Published SYNC`);
235
239
  event.markAsProcessing();
236
240
  await DomainEventRepository.save(event);
@@ -239,8 +243,18 @@ export class EventBus {
239
243
  return;
240
244
  }
241
245
  const subscriberList = this.subscribers.get(event.name);
242
- const errors = await this.executeSubscribers(event, subscriberList);
243
- await this.postProcess(event, errors);
246
+ try {
247
+ const errors = await this.executeSubscribers(event, subscriberList);
248
+ await this.postProcess(event, errors);
249
+ }
250
+ catch (err) {
251
+ if (err instanceof RepeatableFailure) {
252
+ event.retry();
253
+ await DomainEventRepository.save(event);
254
+ this.publishQueue(event, "idle");
255
+ }
256
+ throw err;
257
+ }
244
258
  }
245
259
  /**
246
260
  * Processes all pending DomainEvents from the domain_events table.
@@ -250,18 +264,29 @@ export class EventBus {
250
264
  static async drainAll() {
251
265
  let event;
252
266
  while ((event = await DomainEventRepository.findNextPending(this.internetConnected))) {
267
+ const current = event;
253
268
  try {
254
- event.markAsProcessing();
255
- await DomainEventRepository.save(event);
256
- if (!this.preProcess(event)) {
257
- await this.postProcess(event, ["No subscribers registered"]);
269
+ current.markAsProcessing();
270
+ await DomainEventRepository.save(current);
271
+ if (!this.preProcess(current)) {
272
+ await this.postProcess(current, ["No subscribers registered"]);
258
273
  continue;
259
274
  }
260
- const subscriberList = this.subscribers.get(event.name);
261
- const errors = await this.executeSubscribers(event, subscriberList);
262
- await this.postProcess(event, errors);
275
+ const subscriberList = this.subscribers.get(current.name);
276
+ const errors = await runWithChain({
277
+ causationId: current.uuid,
278
+ correlationId: current.correlationId ?? current.uuid,
279
+ }, () => this.executeSubscribers(current, subscriberList));
280
+ await this.postProcess(current, errors);
281
+ }
282
+ catch (err) {
283
+ if (err instanceof RepeatableFailure) {
284
+ current.retry();
285
+ await DomainEventRepository.save(current);
286
+ this.publishQueue(current, "idle");
287
+ break;
288
+ }
263
289
  }
264
- catch { }
265
290
  }
266
291
  }
267
292
  /**
@@ -276,4 +301,14 @@ export class EventBus {
276
301
  loggerQueueProcessor.warn("Failed to clear ProcessWorker queue:", error);
277
302
  }
278
303
  }
304
+ static publishQueue(event, status, detail) {
305
+ publishActivity({
306
+ channel: "queue",
307
+ name: event.name,
308
+ label: event.labelText(),
309
+ detail,
310
+ status,
311
+ ui: declaresUi(event),
312
+ });
313
+ }
279
314
  }
@@ -1,7 +1,6 @@
1
1
  import { BluetoothAdapter } from "../adapters/Bluetooth.adapter";
2
2
  import { loggerUseCases } from "../infrastructure/logger";
3
- import { UI_NOTIFICATION_EVENT } from "../infrastructure/ui/events";
4
- import { UIEventBus } from "../infrastructure/ui/UIEventBus";
3
+ import { notifyDevice } from "../infrastructure/ui/activity";
5
4
  class BluetoothService {
6
5
  permissionStatus = null;
7
6
  async requestPermissions() {
@@ -36,10 +35,11 @@ class BluetoothService {
36
35
  loggerUseCases.info("Ensuring Bluetooth permissions for printer connection");
37
36
  const permissions = await this.ensurePermissions();
38
37
  if (!permissions) {
39
- UIEventBus.emit(UI_NOTIFICATION_EVENT, {
40
- type: "error",
41
- text1: "Permisos de Bluetooth requeridos",
42
- text2: "Habilita los permisos de Bluetooth en configuración",
38
+ notifyDevice({
39
+ name: "bluetooth.required",
40
+ title: "Permisos de Bluetooth requeridos",
41
+ message: "Habilita los permisos de Bluetooth en configuración",
42
+ variant: "danger",
43
43
  });
44
44
  }
45
45
  return permissions;
@@ -52,18 +52,20 @@ class BluetoothService {
52
52
  }
53
53
  showPermissionToast(permissions) {
54
54
  if (permissions.isGranted) {
55
- UIEventBus.emit(UI_NOTIFICATION_EVENT, {
56
- type: "success",
57
- text1: "Bluetooth habilitado",
58
- text2: "Permisos de Bluetooth concedidos",
55
+ notifyDevice({
56
+ name: "bluetooth.enabled",
57
+ title: "Bluetooth habilitado",
58
+ message: "Permisos de Bluetooth concedidos",
59
+ variant: "success",
59
60
  });
60
61
  loggerUseCases.info("Bluetooth permissions granted");
61
62
  }
62
63
  else {
63
- UIEventBus.emit(UI_NOTIFICATION_EVENT, {
64
- type: "error",
65
- text1: "Bluetooth no disponible",
66
- text2: "Los permisos de Bluetooth fueron denegados",
64
+ notifyDevice({
65
+ name: "bluetooth.denied",
66
+ title: "Bluetooth no disponible",
67
+ message: "Los permisos de Bluetooth fueron denegados",
68
+ variant: "danger",
67
69
  });
68
70
  loggerUseCases.warn("Bluetooth permissions denied", { permissions });
69
71
  }
@@ -1,23 +1,23 @@
1
- import { DomainEvent } from "../domain/event_sourcing";
1
+ import { IntegrationEvent } from "../domain/events";
2
2
  declare class DeadLetterQueueUseCases {
3
3
  private get repository();
4
4
  /**
5
5
  * Retrieves all failed events from the dead letter queue.
6
6
  */
7
- getFailedEvents(): Promise<DomainEvent[]>;
7
+ getFailedEvents(): Promise<IntegrationEvent[]>;
8
8
  /**
9
9
  * Retrieves a specific failed event by uuid.
10
10
  */
11
- getFailedEventById(uuid: string): Promise<DomainEvent | null>;
11
+ getFailedEventById(uuid: string): Promise<IntegrationEvent | null>;
12
12
  /**
13
13
  * Manually retries a failed event by re-queuing it for processing.
14
14
  * This removes the event from the dead letter queue and adds it back to the processing queue.
15
15
  */
16
- retryFailedEvent(event: DomainEvent): Promise<void>;
16
+ retryFailedEvent(event: IntegrationEvent): Promise<void>;
17
17
  /**
18
18
  * Retries multiple failed events in batch.
19
19
  */
20
- retryMultipleFailedEvents(events: DomainEvent[]): Promise<{
20
+ retryMultipleFailedEvents(events: IntegrationEvent[]): Promise<{
21
21
  success: number;
22
22
  failed: number;
23
23
  }>;
@@ -25,11 +25,11 @@ declare class DeadLetterQueueUseCases {
25
25
  * Permanently deletes a failed event from the dead letter queue.
26
26
  * Use with caution as this action cannot be undone.
27
27
  */
28
- deleteFailedEvent(event: DomainEvent): Promise<void>;
28
+ deleteFailedEvent(event: IntegrationEvent): Promise<void>;
29
29
  /**
30
30
  * Deletes multiple failed events in batch.
31
31
  */
32
- deleteMultipleFailedEvents(events: DomainEvent[]): Promise<{
32
+ deleteMultipleFailedEvents(events: IntegrationEvent[]): Promise<{
33
33
  success: number;
34
34
  failed: number;
35
35
  }>;
@@ -27,9 +27,7 @@ class DeadLetterQueueUseCases {
27
27
  async retryFailedEvent(event) {
28
28
  loggerUseCases.info(`Manually retrying failed event: ${event.name} (uuid: ${event.uuid})`);
29
29
  try {
30
- // Reset the event for retry
31
30
  event.retry();
32
- // Re-queue the event using V2 API
33
31
  await EventBus.publish(event);
34
32
  // Remove from dead letter queue only after successful re-queuing
35
33
  await this.repository.remove(event.uuid);
@@ -1,7 +1,7 @@
1
- import { DomainEvent } from "../domain/event_sourcing";
1
+ import { type IntegrationEvent } from "../domain/events";
2
2
  declare class EventService {
3
- listAllEvents(): Promise<DomainEvent[]>;
4
- republishSync(event: DomainEvent): Promise<void>;
3
+ listAllEvents(): Promise<IntegrationEvent[]>;
4
+ republishSync(event: IntegrationEvent): Promise<void>;
5
5
  }
6
6
  export declare const eventService: EventService;
7
7
  export {};
@@ -1,5 +1,5 @@
1
1
  import { DomainEventRepository } from "../adapters/repositories/domain_event.repository";
2
- import { EEventStatus } from "../domain/event_sourcing";
2
+ import { EEventStatus } from "../domain/events";
3
3
  import { loggerUseCases } from "../infrastructure/logger";
4
4
  import { EventBus } from "../infrastructure/workers/EventBus";
5
5
  class EventService {
@@ -2,6 +2,6 @@ import { NetworkStatus } from "../domain/connectivity";
2
2
  export declare class NetworkUseCases {
3
3
  private networkStatus;
4
4
  getNetworkStatus(): Promise<NetworkStatus>;
5
- showToastNotification(networkStatus: NetworkStatus): Promise<void>;
5
+ private notifyOnChange;
6
6
  }
7
7
  export declare const networkUseCases: NetworkUseCases;
@@ -1,7 +1,7 @@
1
1
  import { NetworkAdapter } from "../adapters/Network.adapter";
2
2
  import { InternetIsDownEvent, InternetIsUpEvent } from "../domain/events";
3
3
  import { loggerUseCases } from "../infrastructure/logger";
4
- import { UI_NOTIFICATION_EVENT } from "../infrastructure/ui/events";
4
+ import { notifyDevice } from "../infrastructure/ui/activity";
5
5
  import { UIEventBus } from "../infrastructure/ui/UIEventBus";
6
6
  export class NetworkUseCases {
7
7
  networkStatus = null;
@@ -13,29 +13,31 @@ export class NetworkUseCases {
13
13
  else {
14
14
  UIEventBus.emit(InternetIsDownEvent.name, false);
15
15
  }
16
- this.showToastNotification(networkStatus);
16
+ this.notifyOnChange(networkStatus);
17
17
  this.networkStatus = networkStatus;
18
18
  return this.networkStatus;
19
19
  }
20
- async showToastNotification(networkStatus) {
21
- const showToast = networkStatus.isConnected !== this.networkStatus?.isConnected;
22
- if (!showToast) {
20
+ notifyOnChange(networkStatus) {
21
+ const changed = networkStatus.isConnected !== this.networkStatus?.isConnected;
22
+ if (!changed) {
23
23
  return;
24
24
  }
25
25
  if (!networkStatus.isConnected) {
26
- loggerUseCases.info(`Network is up: ${networkStatus.type}`);
27
- UIEventBus.emit(UI_NOTIFICATION_EVENT, {
28
- type: "error",
29
- text1: "Estas desconectado",
30
- text2: "Sin conexión a internet",
26
+ loggerUseCases.warn(`Network is down: ${networkStatus.type}`);
27
+ notifyDevice({
28
+ name: "network.offline",
29
+ title: "Estas desconectado",
30
+ message: "Sin conexión a internet",
31
+ variant: "danger",
31
32
  });
32
33
  }
33
34
  else {
34
- loggerUseCases.warn(`Network is down: ${networkStatus.type}`);
35
- UIEventBus.emit(UI_NOTIFICATION_EVENT, {
36
- type: "success",
37
- text1: "Conectado",
38
- text2: `Conexión a través de ${networkStatus.type}`,
35
+ loggerUseCases.info(`Network is up: ${networkStatus.type}`);
36
+ notifyDevice({
37
+ name: "network.online",
38
+ title: "Conectado",
39
+ message: `Conexión a través de ${networkStatus.type}`,
40
+ variant: "success",
39
41
  });
40
42
  }
41
43
  }
@@ -9,7 +9,7 @@ declare class PrinterService {
9
9
  getPairedDevices(): BluetoothDevice[];
10
10
  getPairedPrinters(): PairedPrinter[];
11
11
  isConnected(): boolean;
12
- connect(address: string, name: string): Promise<boolean>;
12
+ connect(address: string, name: string, notify?: boolean): Promise<boolean>;
13
13
  disconnect(): Promise<void>;
14
14
  getSelectedPrinter(): Promise<ISelectedPrinter | null>;
15
15
  saveSelectedPrinter(printer: ISelectedPrinter): Promise<void>;
@@ -3,8 +3,7 @@ import { SettingsRepository } from "../adapters/repositories/setting.repository"
3
3
  import { getPrinterDriver, hasPrinterDriver, setPrinterDriver, } from "../domain/print";
4
4
  import { ECommonSetting } from "../domain/settings";
5
5
  import { loggerUseCases } from "../infrastructure/logger";
6
- import { UI_NOTIFICATION_EVENT } from "../infrastructure/ui/events";
7
- import { UIEventBus } from "../infrastructure/ui/UIEventBus";
6
+ import { notifyDevice } from "../infrastructure/ui/activity";
8
7
  import { File } from "expo-file-system";
9
8
  import * as Print from "expo-print";
10
9
  import { bluetoothService } from "./bluetooth.service";
@@ -26,7 +25,7 @@ class PrinterService {
26
25
  isConnected() {
27
26
  return getPrinterDriver().isConnected();
28
27
  }
29
- async connect(address, name) {
28
+ async connect(address, name, notify = true) {
30
29
  const hasPermissions = await this.bluetooth.ensurePermissionsForPrinter();
31
30
  if (!hasPermissions) {
32
31
  return false;
@@ -39,30 +38,37 @@ class PrinterService {
39
38
  selectedAt: new Date().toISOString(),
40
39
  };
41
40
  await this.saveSelectedPrinter(printer);
42
- UIEventBus.emit(UI_NOTIFICATION_EVENT, {
43
- type: "success",
44
- text1: "Impresora conectada",
45
- text2: `Conectado a ${name}`,
46
- });
41
+ if (notify) {
42
+ notifyDevice({
43
+ name: "printer.connected",
44
+ title: "Impresora conectada",
45
+ message: `Conectado a ${name}`,
46
+ variant: "success",
47
+ });
48
+ }
47
49
  return true;
48
50
  }
49
51
  catch (error) {
50
52
  loggerUseCases.error(`Failed to connect to printer: ${name}`, error);
51
- UIEventBus.emit(UI_NOTIFICATION_EVENT, {
52
- type: "error",
53
- text1: "Error de conexión",
54
- text2: `No se pudo conectar a ${name}`,
55
- });
53
+ if (notify) {
54
+ notifyDevice({
55
+ name: "printer.connect_failed",
56
+ title: "Error de conexión",
57
+ message: `No se pudo conectar a ${name}`,
58
+ variant: "danger",
59
+ });
60
+ }
56
61
  return false;
57
62
  }
58
63
  }
59
64
  async disconnect() {
60
65
  try {
61
66
  await getPrinterDriver().disconnect();
62
- UIEventBus.emit(UI_NOTIFICATION_EVENT, {
63
- type: "info",
64
- text1: "Desconectado",
65
- text2: "Impresora desconectada",
67
+ notifyDevice({
68
+ name: "printer.disconnected",
69
+ title: "Desconectado",
70
+ message: "Impresora desconectada",
71
+ variant: "info",
66
72
  });
67
73
  }
68
74
  catch (error) {
@@ -87,10 +93,11 @@ class PrinterService {
87
93
  }
88
94
  async printTestPage() {
89
95
  if (!this.isConnected()) {
90
- UIEventBus.emit(UI_NOTIFICATION_EVENT, {
91
- type: "error",
92
- text1: "Sin conexión",
93
- text2: "Conecta una impresora primero",
96
+ notifyDevice({
97
+ name: "printer.not_connected",
98
+ title: "Sin conexión",
99
+ message: "Conecta una impresora primero",
100
+ variant: "danger",
94
101
  });
95
102
  return false;
96
103
  }
@@ -108,19 +115,21 @@ class PrinterService {
108
115
  alignment: "center",
109
116
  fontSize: "small",
110
117
  });
111
- UIEventBus.emit(UI_NOTIFICATION_EVENT, {
112
- type: "success",
113
- text1: "Impresión exitosa",
114
- text2: "Página de prueba impresa",
118
+ notifyDevice({
119
+ name: "printer.test_ok",
120
+ title: "Impresión exitosa",
121
+ message: "Página de prueba impresa",
122
+ variant: "success",
115
123
  });
116
124
  return true;
117
125
  }
118
126
  catch (error) {
119
127
  loggerUseCases.error("Error printing test page", error);
120
- UIEventBus.emit(UI_NOTIFICATION_EVENT, {
121
- type: "error",
122
- text1: "Error de impresión",
123
- text2: "No se pudo imprimir la página de prueba",
128
+ notifyDevice({
129
+ name: "printer.test_failed",
130
+ title: "Error de impresión",
131
+ message: "No se pudo imprimir la página de prueba",
132
+ variant: "danger",
124
133
  });
125
134
  return false;
126
135
  }
@@ -137,18 +146,13 @@ class PrinterService {
137
146
  loggerUseCases.warn("Print failed — attempting grace reconnect", firstError);
138
147
  const reconnected = await this.forceReconnect();
139
148
  if (!reconnected)
140
- return false; // connect() ya notificó al usuario
149
+ return false;
141
150
  try {
142
151
  await getPrinterDriver().printImageBase64(base64Data);
143
152
  return true;
144
153
  }
145
154
  catch (retryError) {
146
155
  loggerUseCases.error("Print retry after reconnect also failed", retryError);
147
- UIEventBus.emit(UI_NOTIFICATION_EVENT, {
148
- type: "error",
149
- text1: "Error de impresión",
150
- text2: "No se pudo imprimir incluso tras reconectar la impresora",
151
- });
152
156
  return false;
153
157
  }
154
158
  }
@@ -164,10 +168,11 @@ class PrinterService {
164
168
  return false;
165
169
  }
166
170
  await getPrinterDriver().printImageBase64(imageBase64);
167
- UIEventBus.emit(UI_NOTIFICATION_EVENT, {
168
- type: "success",
169
- text1: "Impresión enviada",
170
- text2: "Documento enviado a la impresora",
171
+ notifyDevice({
172
+ name: "printer.sent",
173
+ title: "Impresión enviada",
174
+ message: "Documento enviado a la impresora",
175
+ variant: "success",
171
176
  });
172
177
  return true;
173
178
  }
@@ -233,7 +238,7 @@ class PrinterService {
233
238
  if (!printer)
234
239
  return false;
235
240
  loggerUseCases.info(`Grace reconnect: reconnecting to ${printer.name} (${printer.address})`);
236
- return this.connect(printer.address, printer.name);
241
+ return this.connect(printer.address, printer.name, false);
237
242
  }
238
243
  async ensureConnected() {
239
244
  if (this.isConnected()) {
@@ -241,10 +246,11 @@ class PrinterService {
241
246
  }
242
247
  const printer = await this.getSelectedPrinter();
243
248
  if (!printer) {
244
- UIEventBus.emit(UI_NOTIFICATION_EVENT, {
245
- type: "error",
246
- text1: "Sin impresora",
247
- text2: "Selecciona una impresora primero",
249
+ notifyDevice({
250
+ name: "printer.missing",
251
+ title: "Sin impresora",
252
+ message: "Selecciona una impresora primero",
253
+ variant: "danger",
248
254
  });
249
255
  return false;
250
256
  }
@@ -1,3 +1,4 @@
1
+ import { dayOf, isDay } from "@sincpro/client-framework";
1
2
  import dayjs from "dayjs";
2
3
  import timezone from "dayjs/plugin/timezone";
3
4
  import utc from "dayjs/plugin/utc";
@@ -53,7 +54,7 @@ export function formatDate(input, timezone, options) {
53
54
  const usedLocale = options?.locale ?? deviceLocale;
54
55
  try {
55
56
  const rawStr = typeof input === "string" ? input : input.toISOString();
56
- const isDateOnly = /^\d{4}-\d{2}-\d{2}$/.test(rawStr);
57
+ const isDateOnly = typeof input === "string" && isDay(input);
57
58
  // Auto-detect showTime si no se pasa explicitamente
58
59
  const effectiveShowTime = options?.showTime !== undefined
59
60
  ? options.showTime
@@ -100,11 +101,11 @@ export function formatDateWithDefaultTimezone(input, options) {
100
101
  export function getCurrentDateInTimezone(timezone) {
101
102
  const effectiveTimezone = timezone || DEFAULT_TIMEZONE;
102
103
  try {
103
- return dayjs().tz(effectiveTimezone).format("YYYY-MM-DD");
104
+ return dayOf(new Date().toISOString(), effectiveTimezone) ?? dayjs().format("YYYY-MM-DD");
104
105
  }
105
106
  catch (error) {
106
107
  console.warn("Error obteniendo fecha actual en timezone:", error);
107
- return dayjs().format("YYYY-MM-DD"); // Fallback to local
108
+ return dayjs().format("YYYY-MM-DD");
108
109
  }
109
110
  }
110
111
  /**
@@ -1,3 +1,6 @@
1
- export declare function parseToMonetaryNumber(input?: string | number | null): number;
2
- export declare function formatTwoDecimals(value?: number | string | null): string;
3
- export declare function calculateDiscountedTotal(total: number, discount: number): number;
1
+ import { Decimal, type DecimalLike } from "@sincpro/client-framework";
2
+ export declare function toDecimal(input?: DecimalLike | null): Decimal;
3
+ export declare function parseToMonetaryNumber(input?: DecimalLike | null): Decimal;
4
+ export declare function formatTwoDecimals(value?: DecimalLike | null): string;
5
+ export declare function discountOf(total: DecimalLike, discount: DecimalLike): Decimal;
6
+ export declare function calculateDiscountedTotal(total: DecimalLike, discount: DecimalLike): Decimal;