@sincpro/mobile 0.1.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 (232) hide show
  1. package/README.md +74 -0
  2. package/dist/adapters/Bluetooth.adapter.d.ts +14 -0
  3. package/dist/adapters/Bluetooth.adapter.js +100 -0
  4. package/dist/adapters/Geo.adapter.d.ts +8 -0
  5. package/dist/adapters/Geo.adapter.js +30 -0
  6. package/dist/adapters/JsonSerializer.adapter.d.ts +28 -0
  7. package/dist/adapters/JsonSerializer.adapter.js +47 -0
  8. package/dist/adapters/Network.adapter.d.ts +4 -0
  9. package/dist/adapters/Network.adapter.js +13 -0
  10. package/dist/adapters/ReceiptExporter.adapter.d.ts +19 -0
  11. package/dist/adapters/ReceiptExporter.adapter.js +142 -0
  12. package/dist/adapters/repositories/database_table.repository.d.ts +13 -0
  13. package/dist/adapters/repositories/database_table.repository.js +29 -0
  14. package/dist/adapters/repositories/domain_event.repository.d.ts +32 -0
  15. package/dist/adapters/repositories/domain_event.repository.js +147 -0
  16. package/dist/adapters/repositories/domain_event_dead_letter.repository.d.ts +23 -0
  17. package/dist/adapters/repositories/domain_event_dead_letter.repository.js +81 -0
  18. package/dist/adapters/repositories/setting.repository.d.ts +10 -0
  19. package/dist/adapters/repositories/setting.repository.js +21 -0
  20. package/dist/adapters/webview.adapter.d.ts +10 -0
  21. package/dist/adapters/webview.adapter.js +166 -0
  22. package/dist/domain/connectivity/bluetooth.d.ts +19 -0
  23. package/dist/domain/connectivity/bluetooth.js +1 -0
  24. package/dist/domain/connectivity/events.d.ts +17 -0
  25. package/dist/domain/connectivity/events.js +17 -0
  26. package/dist/domain/connectivity/geo.d.ts +4 -0
  27. package/dist/domain/connectivity/geo.js +1 -0
  28. package/dist/domain/connectivity/index.d.ts +3 -0
  29. package/dist/domain/connectivity/index.js +3 -0
  30. package/dist/domain/connectivity/network.d.ts +7 -0
  31. package/dist/domain/connectivity/network.js +1 -0
  32. package/dist/domain/database/database.d.ts +16 -0
  33. package/dist/domain/database/database.js +1 -0
  34. package/dist/domain/database/index.d.ts +2 -0
  35. package/dist/domain/database/index.js +2 -0
  36. package/dist/domain/database/repository.d.ts +19 -0
  37. package/dist/domain/database/repository.js +1 -0
  38. package/dist/domain/entity/entity.d.ts +109 -0
  39. package/dist/domain/entity/entity.js +246 -0
  40. package/dist/domain/entity/entity_collection.d.ts +396 -0
  41. package/dist/domain/entity/entity_collection.js +824 -0
  42. package/dist/domain/entity/index.d.ts +3 -0
  43. package/dist/domain/entity/index.js +3 -0
  44. package/dist/domain/entity/value_object.d.ts +12 -0
  45. package/dist/domain/entity/value_object.js +39 -0
  46. package/dist/domain/event_sourcing/domain_event.d.ts +58 -0
  47. package/dist/domain/event_sourcing/domain_event.js +164 -0
  48. package/dist/domain/event_sourcing/event.d.ts +25 -0
  49. package/dist/domain/event_sourcing/event.js +25 -0
  50. package/dist/domain/event_sourcing/event_handler.d.ts +7 -0
  51. package/dist/domain/event_sourcing/event_handler.js +13 -0
  52. package/dist/domain/event_sourcing/index.d.ts +2 -0
  53. package/dist/domain/event_sourcing/index.js +2 -0
  54. package/dist/domain/events.d.ts +33 -0
  55. package/dist/domain/events.js +32 -0
  56. package/dist/domain/icon.d.ts +1 -0
  57. package/dist/domain/icon.js +1 -0
  58. package/dist/domain/index.d.ts +9 -0
  59. package/dist/domain/index.js +9 -0
  60. package/dist/domain/print/driver_registry.d.ts +4 -0
  61. package/dist/domain/print/driver_registry.js +29 -0
  62. package/dist/domain/print/events.d.ts +13 -0
  63. package/dist/domain/print/events.js +13 -0
  64. package/dist/domain/print/index.d.ts +2 -0
  65. package/dist/domain/print/index.js +1 -0
  66. package/dist/domain/print/printer.d.ts +35 -0
  67. package/dist/domain/print/printer.js +1 -0
  68. package/dist/domain/receipt.d.ts +31 -0
  69. package/dist/domain/receipt.js +1 -0
  70. package/dist/domain/repositories.d.ts +6 -0
  71. package/dist/domain/repositories.js +7 -0
  72. package/dist/domain/settings.d.ts +7 -0
  73. package/dist/domain/settings.js +1 -0
  74. package/dist/domain/webview/events.d.ts +11 -0
  75. package/dist/domain/webview/events.js +11 -0
  76. package/dist/domain/webview/index.d.ts +1 -0
  77. package/dist/domain/webview/index.js +1 -0
  78. package/dist/domain/webview/webview.d.ts +57 -0
  79. package/dist/domain/webview/webview.js +9 -0
  80. package/dist/entrypoints/cron/Cron.d.ts +13 -0
  81. package/dist/entrypoints/cron/Cron.js +57 -0
  82. package/dist/entrypoints/cron/checkNetworkStatus.cron.d.ts +3 -0
  83. package/dist/entrypoints/cron/checkNetworkStatus.cron.js +10 -0
  84. package/dist/entrypoints/db/index.d.ts +2 -0
  85. package/dist/entrypoints/db/index.js +2 -0
  86. package/dist/entrypoints/db/migrations.d.ts +10 -0
  87. package/dist/entrypoints/db/migrations.js +115 -0
  88. package/dist/entrypoints/db/repositories.d.ts +8 -0
  89. package/dist/entrypoints/db/repositories.js +34 -0
  90. package/dist/entrypoints/queue/QueueProcessor.d.ts +12 -0
  91. package/dist/entrypoints/queue/QueueProcessor.js +75 -0
  92. package/dist/entrypoints/queue/activateDomain.subscriber.d.ts +7 -0
  93. package/dist/entrypoints/queue/activateDomain.subscriber.js +15 -0
  94. package/dist/entrypoints/queue/newAppSettings.handler.d.ts +7 -0
  95. package/dist/entrypoints/queue/newAppSettings.handler.js +17 -0
  96. package/dist/entrypoints/queue/printImage.subscriber.d.ts +7 -0
  97. package/dist/entrypoints/queue/printImage.subscriber.js +14 -0
  98. package/dist/entrypoints/queue/processWebViewMessage.subscriber.d.ts +7 -0
  99. package/dist/entrypoints/queue/processWebViewMessage.subscriber.js +23 -0
  100. package/dist/entrypoints/ui/AppShell.d.ts +15 -0
  101. package/dist/entrypoints/ui/AppShell.js +58 -0
  102. package/dist/entrypoints/ui/common_provider.d.ts +35 -0
  103. package/dist/entrypoints/ui/common_provider.js +244 -0
  104. package/dist/entrypoints/ui/domain_switcher.d.ts +19 -0
  105. package/dist/entrypoints/ui/domain_switcher.js +22 -0
  106. package/dist/entrypoints/ui/theme.d.ts +15 -0
  107. package/dist/entrypoints/ui/theme.js +16 -0
  108. package/dist/exceptions.d.ts +22 -0
  109. package/dist/exceptions.js +60 -0
  110. package/dist/framework/base_module.d.ts +14 -0
  111. package/dist/framework/base_module.js +40 -0
  112. package/dist/framework/createApp.d.ts +6 -0
  113. package/dist/framework/createApp.js +9 -0
  114. package/dist/framework/domain_module.d.ts +13 -0
  115. package/dist/framework/domain_module.js +18 -0
  116. package/dist/framework/kernel.d.ts +18 -0
  117. package/dist/framework/kernel.js +60 -0
  118. package/dist/framework/orchestrator.d.ts +29 -0
  119. package/dist/framework/orchestrator.js +118 -0
  120. package/dist/index.d.ts +16 -0
  121. package/dist/index.js +11 -0
  122. package/dist/infrastructure/database/connector.d.ts +13 -0
  123. package/dist/infrastructure/database/connector.js +165 -0
  124. package/dist/infrastructure/database/index.d.ts +2 -0
  125. package/dist/infrastructure/database/index.js +2 -0
  126. package/dist/infrastructure/database/mapped.d.ts +128 -0
  127. package/dist/infrastructure/database/mapped.js +174 -0
  128. package/dist/infrastructure/database/utils.d.ts +10 -0
  129. package/dist/infrastructure/database/utils.js +35 -0
  130. package/dist/infrastructure/logger.d.ts +45 -0
  131. package/dist/infrastructure/logger.js +125 -0
  132. package/dist/infrastructure/ui/ToastHost.d.ts +1 -0
  133. package/dist/infrastructure/ui/ToastHost.js +19 -0
  134. package/dist/infrastructure/ui/UIEventBus.d.ts +12 -0
  135. package/dist/infrastructure/ui/UIEventBus.js +65 -0
  136. package/dist/infrastructure/ui/errorHandler.d.ts +1 -0
  137. package/dist/infrastructure/ui/errorHandler.js +20 -0
  138. package/dist/infrastructure/ui/events.d.ts +1 -0
  139. package/dist/infrastructure/ui/events.js +1 -0
  140. package/dist/infrastructure/workers/CronWorker.d.ts +42 -0
  141. package/dist/infrastructure/workers/CronWorker.js +143 -0
  142. package/dist/infrastructure/workers/EventBus.d.ts +67 -0
  143. package/dist/infrastructure/workers/EventBus.js +279 -0
  144. package/dist/infrastructure/workers/index.d.ts +2 -0
  145. package/dist/infrastructure/workers/index.js +2 -0
  146. package/dist/services/bluetooth.service.d.ts +14 -0
  147. package/dist/services/bluetooth.service.js +72 -0
  148. package/dist/services/database_table.service.d.ts +8 -0
  149. package/dist/services/database_table.service.js +19 -0
  150. package/dist/services/dead_letter_queue.service.d.ts +38 -0
  151. package/dist/services/dead_letter_queue.service.js +99 -0
  152. package/dist/services/event.service.d.ts +7 -0
  153. package/dist/services/event.service.js +24 -0
  154. package/dist/services/network.service.d.ts +7 -0
  155. package/dist/services/network.service.js +43 -0
  156. package/dist/services/printer.service.d.ts +25 -0
  157. package/dist/services/printer.service.js +220 -0
  158. package/dist/services/webview.service.d.ts +17 -0
  159. package/dist/services/webview.service.js +59 -0
  160. package/dist/tools/utils/Initials.d.ts +1 -0
  161. package/dist/tools/utils/Initials.js +12 -0
  162. package/dist/tools/utils/collections.d.ts +120 -0
  163. package/dist/tools/utils/collections.js +158 -0
  164. package/dist/tools/utils/date.d.ts +70 -0
  165. package/dist/tools/utils/date.js +126 -0
  166. package/dist/tools/utils/maps.d.ts +4 -0
  167. package/dist/tools/utils/maps.js +20 -0
  168. package/dist/tools/utils/monetary.d.ts +3 -0
  169. package/dist/tools/utils/monetary.js +31 -0
  170. package/dist/tools/utils/quantity.d.ts +11 -0
  171. package/dist/tools/utils/quantity.js +44 -0
  172. package/dist/tools/utils/searchTools.d.ts +39 -0
  173. package/dist/tools/utils/searchTools.js +56 -0
  174. package/dist/tools/utils/serializer.d.ts +2 -0
  175. package/dist/tools/utils/serializer.js +44 -0
  176. package/dist/ui/components/atoms/DebugBanner.d.ts +2 -0
  177. package/dist/ui/components/atoms/DebugBanner.js +15 -0
  178. package/dist/ui/components/atoms/index.d.ts +1 -0
  179. package/dist/ui/components/atoms/index.js +1 -0
  180. package/dist/ui/components/molecules/BluetoothDeviceSelectorModal.d.ts +8 -0
  181. package/dist/ui/components/molecules/BluetoothDeviceSelectorModal.js +61 -0
  182. package/dist/ui/components/molecules/DeadLetterErrorBlock.d.ts +8 -0
  183. package/dist/ui/components/molecules/DeadLetterErrorBlock.js +14 -0
  184. package/dist/ui/components/molecules/EventTimelineItem.d.ts +7 -0
  185. package/dist/ui/components/molecules/EventTimelineItem.js +65 -0
  186. package/dist/ui/components/molecules/ProcessToast.d.ts +5 -0
  187. package/dist/ui/components/molecules/ProcessToast.js +51 -0
  188. package/dist/ui/components/molecules/ProcessToastProvider.d.ts +4 -0
  189. package/dist/ui/components/molecules/ProcessToastProvider.js +5 -0
  190. package/dist/ui/components/molecules/index.d.ts +5 -0
  191. package/dist/ui/components/molecules/index.js +5 -0
  192. package/dist/ui/components/organisms/BluetoothPrinterSelector.d.ts +7 -0
  193. package/dist/ui/components/organisms/BluetoothPrinterSelector.js +92 -0
  194. package/dist/ui/components/organisms/DatabaseInfoRow.d.ts +11 -0
  195. package/dist/ui/components/organisms/DatabaseInfoRow.js +8 -0
  196. package/dist/ui/components/organisms/DeadLetterQueueRow.d.ts +7 -0
  197. package/dist/ui/components/organisms/DeadLetterQueueRow.js +72 -0
  198. package/dist/ui/components/organisms/EventRow.d.ts +7 -0
  199. package/dist/ui/components/organisms/EventRow.js +90 -0
  200. package/dist/ui/components/organisms/InjectableWebView.d.ts +35 -0
  201. package/dist/ui/components/organisms/InjectableWebView.js +169 -0
  202. package/dist/ui/components/organisms/Receipt.d.ts +11 -0
  203. package/dist/ui/components/organisms/Receipt.js +207 -0
  204. package/dist/ui/components/organisms/TableInfoInfoRow.d.ts +9 -0
  205. package/dist/ui/components/organisms/TableInfoInfoRow.js +19 -0
  206. package/dist/ui/components/organisms/index.d.ts +7 -0
  207. package/dist/ui/components/organisms/index.js +7 -0
  208. package/dist/ui/index.d.ts +4 -0
  209. package/dist/ui/index.js +4 -0
  210. package/dist/ui/layouts/router_layouts.d.ts +17 -0
  211. package/dist/ui/layouts/router_layouts.js +20 -0
  212. package/dist/ui/screens/database/database.context.d.ts +32 -0
  213. package/dist/ui/screens/database/database.context.js +158 -0
  214. package/dist/ui/screens/database/database.json_detail.d.ts +2 -0
  215. package/dist/ui/screens/database/database.json_detail.js +19 -0
  216. package/dist/ui/screens/database/database.list.d.ts +1 -0
  217. package/dist/ui/screens/database/database.list.js +41 -0
  218. package/dist/ui/screens/database/database.table_rows.d.ts +2 -0
  219. package/dist/ui/screens/database/database.table_rows.js +10 -0
  220. package/dist/ui/screens/dead_letter_queue/dead_letter_queue.context.d.ts +34 -0
  221. package/dist/ui/screens/dead_letter_queue/dead_letter_queue.context.js +166 -0
  222. package/dist/ui/screens/dead_letter_queue/dead_letter_queue.list.d.ts +2 -0
  223. package/dist/ui/screens/dead_letter_queue/dead_letter_queue.list.js +24 -0
  224. package/dist/ui/screens/events/events.context.d.ts +25 -0
  225. package/dist/ui/screens/events/events.context.js +113 -0
  226. package/dist/ui/screens/events/events.list.d.ts +1 -0
  227. package/dist/ui/screens/events/events.list.js +26 -0
  228. package/dist/ui/screens/events/index.d.ts +1 -0
  229. package/dist/ui/screens/events/index.js +1 -0
  230. package/dist/ui/screens/index.d.ts +3 -0
  231. package/dist/ui/screens/index.js +3 -0
  232. package/package.json +125 -0
@@ -0,0 +1,279 @@
1
+ import { DomainEventRepository } from "../../adapters/repositories/domain_event.repository";
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";
5
+ import { loggerQueueProcessor } from "../../infrastructure/logger";
6
+ import { UIEventBus } from "../../infrastructure/ui/UIEventBus";
7
+ export const PROCESS_WORKER_MAX_ATTEMPTS = 1;
8
+ export class EventBus {
9
+ static MAX_ATTEMPTS = PROCESS_WORKER_MAX_ATTEMPTS;
10
+ static INTERVAL_MS = 800;
11
+ static MAX_INTERVAL_MS = 30000;
12
+ static BACKOFF_MULTIPLIER = 1.5;
13
+ static subscribers = new Map();
14
+ static isDraining = false;
15
+ static intervalId = null;
16
+ static internetConnected = true;
17
+ static consecutiveFailures = 0;
18
+ static currentInterval = EventBus.INTERVAL_MS;
19
+ static initConnectivityListeners() {
20
+ UIEventBus.on(InternetIsDownEvent.name, () => {
21
+ this.internetConnected = false;
22
+ this.consecutiveFailures++;
23
+ this.adjustInterval();
24
+ loggerQueueProcessor.warn("[NET] offline – Solo eventos locales");
25
+ });
26
+ UIEventBus.on(InternetIsUpEvent.name, () => {
27
+ if (!this.internetConnected) {
28
+ this.internetConnected = true;
29
+ this.consecutiveFailures = 0;
30
+ this.currentInterval = this.INTERVAL_MS;
31
+ this.restartPolling();
32
+ loggerQueueProcessor.info("[NET] online – Reanudando eventos de red");
33
+ }
34
+ });
35
+ }
36
+ static adjustInterval() {
37
+ if (this.consecutiveFailures > 0) {
38
+ this.currentInterval = Math.min(this.INTERVAL_MS * Math.pow(this.BACKOFF_MULTIPLIER, this.consecutiveFailures), this.MAX_INTERVAL_MS);
39
+ loggerQueueProcessor.debug(`Adjusted polling interval to ${this.currentInterval}ms due to ${this.consecutiveFailures} failures`);
40
+ }
41
+ }
42
+ static restartPolling() {
43
+ if (this.intervalId) {
44
+ clearInterval(this.intervalId);
45
+ }
46
+ this.intervalId = setInterval(() => this.triggerProcessing(), this.currentInterval);
47
+ }
48
+ static async triggerProcessing() {
49
+ if (this.isDraining)
50
+ return;
51
+ this.isDraining = true;
52
+ try {
53
+ await this.drainAll();
54
+ if (this.consecutiveFailures > 0) {
55
+ this.consecutiveFailures = 0;
56
+ this.currentInterval = this.INTERVAL_MS;
57
+ this.restartPolling();
58
+ }
59
+ }
60
+ catch (error) {
61
+ this.consecutiveFailures++;
62
+ this.adjustInterval();
63
+ this.restartPolling();
64
+ loggerQueueProcessor.warn("Error in processing cycle:", error);
65
+ }
66
+ finally {
67
+ this.isDraining = false;
68
+ }
69
+ }
70
+ static start() {
71
+ this.initConnectivityListeners();
72
+ if (this.intervalId)
73
+ return;
74
+ this.currentInterval = this.INTERVAL_MS;
75
+ this.consecutiveFailures = 0;
76
+ this.intervalId = setInterval(() => this.triggerProcessing(), this.currentInterval);
77
+ loggerQueueProcessor.info("ProcessWorker polling started");
78
+ }
79
+ static stop() {
80
+ if (this.intervalId)
81
+ clearInterval(this.intervalId);
82
+ this.intervalId = null;
83
+ loggerQueueProcessor.info("ProcessWorker polling stopped");
84
+ }
85
+ /**
86
+ * Waits for current processing cycle to complete (if any).
87
+ * Use before clean() to ensure graceful shutdown.
88
+ * Timeout after 5 seconds to prevent infinite wait.
89
+ */
90
+ static async waitForIdle() {
91
+ if (!this.isDraining)
92
+ return;
93
+ const maxWait = 5000;
94
+ const checkInterval = 100;
95
+ let waited = 0;
96
+ while (this.isDraining && waited < maxWait) {
97
+ await new Promise((resolve) => setTimeout(resolve, checkInterval));
98
+ waited += checkInterval;
99
+ }
100
+ if (this.isDraining) {
101
+ loggerQueueProcessor.warn("EventBus waitForIdle timed out after 5s");
102
+ }
103
+ }
104
+ /**
105
+ * Validates event, logs start, emits START.
106
+ * Returns false if no subscribers (caller should return early).
107
+ */
108
+ static preProcess(event) {
109
+ const hasSubscribers = this.subscribers.has(event.name);
110
+ loggerQueueProcessor.info(`EVENT=${event.name} [${event.label}] (attempt ${event.attempts}/${EventBus.MAX_ATTEMPTS}) - STARTED`);
111
+ 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
+ });
119
+ if (!hasSubscribers) {
120
+ loggerQueueProcessor.warn(`EVENT=${event.name} [${event.label}] - No subscribers registered`);
121
+ }
122
+ return hasSubscribers;
123
+ }
124
+ /**
125
+ * Handles persistence, emits event and END, logs result.
126
+ * If errors is empty -> success, otherwise -> failure + dead letter + throws.
127
+ * @throws Error if there are any errors
128
+ */
129
+ static async postProcess(event, errors) {
130
+ const success = errors.length === 0;
131
+ const errorMessage = errors.join("; ") || undefined;
132
+ if (success) {
133
+ event.markAsAcknowledged();
134
+ await DomainEventRepository.save(event);
135
+ loggerQueueProcessor.info(`EVENT=${event.name} [${event.label}] (attempt ${event.attempts}/${EventBus.MAX_ATTEMPTS}) - FINISHED`);
136
+ }
137
+ else {
138
+ event.markAsFailed(errorMessage);
139
+ await DomainEventRepository.save(event);
140
+ await DomainEventDeadLetterRepository.save(event, errorMessage);
141
+ loggerQueueProcessor.warn(`EVENT=${event.name} [${event.label}] (attempt ${event.attempts}/${EventBus.MAX_ATTEMPTS}) - FAILED: ${errorMessage}`);
142
+ }
143
+ 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
+ });
152
+ if (!success) {
153
+ throw new Error(errorMessage);
154
+ }
155
+ }
156
+ static async executeSubscribers(event, subscriberList) {
157
+ const errors = [];
158
+ for (const subscriber of subscriberList) {
159
+ try {
160
+ const typedEvent = subscriber.getEvent(event);
161
+ await subscriber.process(typedEvent);
162
+ }
163
+ catch (err) {
164
+ const errorMessage = err instanceof Error ? err.message : String(err);
165
+ errors.push(errorMessage);
166
+ loggerQueueProcessor.warn(`EVENT=${event.name} - Subscriber failed: ${errorMessage}`);
167
+ if (err instanceof DomainNetworkError) {
168
+ this.internetConnected = false;
169
+ UIEventBus.emit(InternetIsDownEvent.name);
170
+ }
171
+ }
172
+ }
173
+ return errors;
174
+ }
175
+ /**
176
+ * Registers a subscriber for DomainEvent classes.
177
+ * A subscriber can listen to multiple events.
178
+ * Multiple subscribers can listen to the same event.
179
+ * Prevents duplicate registration of the same subscriber instance.
180
+ */
181
+ static on(subscriber) {
182
+ for (const EventClass of subscriber.listen) {
183
+ if (!EventClass) {
184
+ loggerQueueProcessor.error(`Undefined event class in subscriber: ${subscriber.constructor.name}`);
185
+ continue;
186
+ }
187
+ const staticName = EventClass.name;
188
+ const eventName = staticName && staticName !== "DomainEvent" ? staticName : new EventClass().name;
189
+ if (!this.subscribers.has(eventName)) {
190
+ this.subscribers.set(eventName, []);
191
+ }
192
+ const subscriberList = this.subscribers.get(eventName);
193
+ if (subscriberList.includes(subscriber)) {
194
+ loggerQueueProcessor.info(`Subscriber already registered for [${eventName}] - skipping`);
195
+ continue;
196
+ }
197
+ subscriberList.push(subscriber);
198
+ loggerQueueProcessor.info(`Subscriber registered for [${eventName}]`);
199
+ }
200
+ }
201
+ static off(subscriber) {
202
+ for (const EventClass of subscriber.listen) {
203
+ if (!EventClass)
204
+ continue;
205
+ const staticName = EventClass.name;
206
+ const eventName = staticName && staticName !== "DomainEvent" ? staticName : new EventClass().name;
207
+ const subscriberList = this.subscribers.get(eventName);
208
+ if (!subscriberList)
209
+ continue;
210
+ const index = subscriberList.indexOf(subscriber);
211
+ if (index > -1) {
212
+ subscriberList.splice(index, 1);
213
+ loggerQueueProcessor.info(`Subscriber unregistered for [${eventName}]`);
214
+ }
215
+ if (subscriberList.length === 0) {
216
+ this.subscribers.delete(eventName);
217
+ }
218
+ }
219
+ }
220
+ /**
221
+ * Publishes a DomainEvent asynchronously - enqueues for later processing.
222
+ */
223
+ static async publish(event) {
224
+ loggerQueueProcessor.info(`EVENT=${event.name} [${event.label}] - Published ASYNC`);
225
+ await DomainEventRepository.save(event);
226
+ this.triggerProcessing();
227
+ }
228
+ /**
229
+ * Publishes a DomainEvent synchronously - executes all subscribers immediately.
230
+ * Saves event to DB for traceability. Moves to dead letter on failure.
231
+ * @throws Error if any subscriber fails or no subscribers registered
232
+ */
233
+ static async publishSync(event) {
234
+ loggerQueueProcessor.info(`EVENT=${event.name} [${event.label}] - Published SYNC`);
235
+ event.markAsProcessing();
236
+ await DomainEventRepository.save(event);
237
+ if (!this.preProcess(event)) {
238
+ await this.postProcess(event, ["No subscribers registered"]);
239
+ return;
240
+ }
241
+ const subscriberList = this.subscribers.get(event.name);
242
+ const errors = await this.executeSubscribers(event, subscriberList);
243
+ await this.postProcess(event, errors);
244
+ }
245
+ /**
246
+ * Processes all pending DomainEvents from the domain_events table.
247
+ * Executes ALL subscribers registered for each event.
248
+ * Moves to dead letter queue on failure.
249
+ */
250
+ static async drainAll() {
251
+ let event;
252
+ while ((event = await DomainEventRepository.findNextPending(this.internetConnected))) {
253
+ try {
254
+ event.markAsProcessing();
255
+ await DomainEventRepository.save(event);
256
+ if (!this.preProcess(event)) {
257
+ await this.postProcess(event, ["No subscribers registered"]);
258
+ continue;
259
+ }
260
+ const subscriberList = this.subscribers.get(event.name);
261
+ const errors = await this.executeSubscribers(event, subscriberList);
262
+ await this.postProcess(event, errors);
263
+ }
264
+ catch { }
265
+ }
266
+ }
267
+ /**
268
+ * Clears the event queue (domain_events table).
269
+ */
270
+ static async clearQueue() {
271
+ try {
272
+ await DomainEventRepository.clearAll();
273
+ loggerQueueProcessor.info("ProcessWorker queue cleared");
274
+ }
275
+ catch (error) {
276
+ loggerQueueProcessor.warn("Failed to clear ProcessWorker queue:", error);
277
+ }
278
+ }
279
+ }
@@ -0,0 +1,2 @@
1
+ export { CronJob, CronWorker } from "./CronWorker";
2
+ export { EventBus, EventName } from "./EventBus";
@@ -0,0 +1,2 @@
1
+ export { CronWorker } from "./CronWorker";
2
+ export { EventBus } from "./EventBus";
@@ -0,0 +1,14 @@
1
+ import { BluetoothPermissionStatus, BluetoothStatus } from "../domain/connectivity";
2
+ declare class BluetoothService {
3
+ private permissionStatus;
4
+ requestPermissions(): Promise<BluetoothPermissionStatus>;
5
+ checkPermissions(): Promise<BluetoothPermissionStatus>;
6
+ getStatus(): Promise<BluetoothStatus>;
7
+ ensurePermissions(): Promise<boolean>;
8
+ ensurePermissionsForPrinter(): Promise<boolean>;
9
+ getCachedPermissions(): BluetoothPermissionStatus | null;
10
+ isPermissionGranted(): boolean;
11
+ private showPermissionToast;
12
+ }
13
+ export declare const bluetoothService: BluetoothService;
14
+ export {};
@@ -0,0 +1,72 @@
1
+ import { BluetoothAdapter } from "../adapters/Bluetooth.adapter";
2
+ import { loggerUseCases } from "../infrastructure/logger";
3
+ import { UI_NOTIFICATION_EVENT } from "../infrastructure/ui/events";
4
+ import { UIEventBus } from "../infrastructure/ui/UIEventBus";
5
+ class BluetoothService {
6
+ permissionStatus = null;
7
+ async requestPermissions() {
8
+ loggerUseCases.info("Requesting Bluetooth permissions");
9
+ const permissions = await BluetoothAdapter.requestPermissions();
10
+ this.permissionStatus = permissions;
11
+ this.showPermissionToast(permissions);
12
+ return permissions;
13
+ }
14
+ async checkPermissions() {
15
+ loggerUseCases.info("Checking Bluetooth permissions");
16
+ const permissions = await BluetoothAdapter.hasPermissions();
17
+ this.permissionStatus = permissions;
18
+ return permissions;
19
+ }
20
+ async getStatus() {
21
+ loggerUseCases.info("Getting Bluetooth status");
22
+ return BluetoothAdapter.getStatus();
23
+ }
24
+ async ensurePermissions() {
25
+ loggerUseCases.info("Ensuring Bluetooth permissions are granted");
26
+ const currentPermissions = await this.checkPermissions();
27
+ if (currentPermissions.isGranted) {
28
+ loggerUseCases.info("Bluetooth permissions already granted");
29
+ return true;
30
+ }
31
+ loggerUseCases.info("Bluetooth permissions not granted, requesting...");
32
+ const requestedPermissions = await this.requestPermissions();
33
+ return requestedPermissions.isGranted;
34
+ }
35
+ async ensurePermissionsForPrinter() {
36
+ loggerUseCases.info("Ensuring Bluetooth permissions for printer connection");
37
+ const permissions = await this.ensurePermissions();
38
+ 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",
43
+ });
44
+ }
45
+ return permissions;
46
+ }
47
+ getCachedPermissions() {
48
+ return this.permissionStatus;
49
+ }
50
+ isPermissionGranted() {
51
+ return this.permissionStatus?.isGranted ?? false;
52
+ }
53
+ showPermissionToast(permissions) {
54
+ if (permissions.isGranted) {
55
+ UIEventBus.emit(UI_NOTIFICATION_EVENT, {
56
+ type: "success",
57
+ text1: "Bluetooth habilitado",
58
+ text2: "Permisos de Bluetooth concedidos",
59
+ });
60
+ loggerUseCases.info("Bluetooth permissions granted");
61
+ }
62
+ else {
63
+ UIEventBus.emit(UI_NOTIFICATION_EVENT, {
64
+ type: "error",
65
+ text1: "Bluetooth no disponible",
66
+ text2: "Los permisos de Bluetooth fueron denegados",
67
+ });
68
+ loggerUseCases.warn("Bluetooth permissions denied", { permissions });
69
+ }
70
+ }
71
+ }
72
+ export const bluetoothService = new BluetoothService();
@@ -0,0 +1,8 @@
1
+ import { IDatabaseTable } from "../domain/database";
2
+ declare class DatabaseTablesUseCase {
3
+ private get repository();
4
+ getAllTables(): Promise<IDatabaseTable[]>;
5
+ getTableData(tableName: string): Promise<any[]>;
6
+ }
7
+ export declare const databaseTablesUseCase: DatabaseTablesUseCase;
8
+ export {};
@@ -0,0 +1,19 @@
1
+ import { ECommonRepository, repos } from "../entrypoints/db";
2
+ import { loggerUseCases } from "../infrastructure/logger";
3
+ class DatabaseTablesUseCase {
4
+ get repository() {
5
+ return repos.get(ECommonRepository.DATABASE_TABLE);
6
+ }
7
+ async getAllTables() {
8
+ loggerUseCases.info("Getting all database tables");
9
+ const tables = await this.repository.findAll();
10
+ return tables.toArray();
11
+ }
12
+ async getTableData(tableName) {
13
+ loggerUseCases.info(`Getting data for ${tableName}`);
14
+ const result = await this.repository.getTableData(tableName);
15
+ loggerUseCases.info(`Retrieved ${result.length} records from ${tableName}`);
16
+ return result;
17
+ }
18
+ }
19
+ export const databaseTablesUseCase = new DatabaseTablesUseCase();
@@ -0,0 +1,38 @@
1
+ import { DomainEvent } from "../domain/event_sourcing";
2
+ declare class DeadLetterQueueUseCases {
3
+ private get repository();
4
+ /**
5
+ * Retrieves all failed events from the dead letter queue.
6
+ */
7
+ getFailedEvents(): Promise<DomainEvent[]>;
8
+ /**
9
+ * Retrieves a specific failed event by uuid.
10
+ */
11
+ getFailedEventById(uuid: string): Promise<DomainEvent | null>;
12
+ /**
13
+ * Manually retries a failed event by re-queuing it for processing.
14
+ * This removes the event from the dead letter queue and adds it back to the processing queue.
15
+ */
16
+ retryFailedEvent(event: DomainEvent): Promise<void>;
17
+ /**
18
+ * Retries multiple failed events in batch.
19
+ */
20
+ retryMultipleFailedEvents(events: DomainEvent[]): Promise<{
21
+ success: number;
22
+ failed: number;
23
+ }>;
24
+ /**
25
+ * Permanently deletes a failed event from the dead letter queue.
26
+ * Use with caution as this action cannot be undone.
27
+ */
28
+ deleteFailedEvent(event: DomainEvent): Promise<void>;
29
+ /**
30
+ * Deletes multiple failed events in batch.
31
+ */
32
+ deleteMultipleFailedEvents(events: DomainEvent[]): Promise<{
33
+ success: number;
34
+ failed: number;
35
+ }>;
36
+ }
37
+ export declare const deadLetterQueueUseCases: DeadLetterQueueUseCases;
38
+ export {};
@@ -0,0 +1,99 @@
1
+ import { ECommonRepository, repos } from "../entrypoints/db";
2
+ import { loggerUseCases } from "../infrastructure/logger";
3
+ import { EventBus } from "../infrastructure/workers/EventBus";
4
+ class DeadLetterQueueUseCases {
5
+ get repository() {
6
+ return repos.get(ECommonRepository.DOMAIN_EVENT_DEAD_LETTER);
7
+ }
8
+ /**
9
+ * Retrieves all failed events from the dead letter queue.
10
+ */
11
+ async getFailedEvents() {
12
+ loggerUseCases.info("Fetching all failed events from dead letter queue");
13
+ const deadLetterEvents = await this.repository.findAll();
14
+ return deadLetterEvents;
15
+ }
16
+ /**
17
+ * Retrieves a specific failed event by uuid.
18
+ */
19
+ async getFailedEventById(uuid) {
20
+ loggerUseCases.info(`Fetching failed event with uuid: ${uuid}`);
21
+ return await this.repository.findById(uuid);
22
+ }
23
+ /**
24
+ * Manually retries a failed event by re-queuing it for processing.
25
+ * This removes the event from the dead letter queue and adds it back to the processing queue.
26
+ */
27
+ async retryFailedEvent(event) {
28
+ loggerUseCases.info(`Manually retrying failed event: ${event.name} (uuid: ${event.uuid})`);
29
+ try {
30
+ // Reset the event for retry
31
+ event.retry();
32
+ // Re-queue the event using V2 API
33
+ await EventBus.publish(event);
34
+ // Remove from dead letter queue only after successful re-queuing
35
+ await this.repository.remove(event.uuid);
36
+ loggerUseCases.info(`Successfully retried event: ${event.name} (uuid: ${event.uuid})`);
37
+ }
38
+ catch (error) {
39
+ loggerUseCases.error(`Failed to retry event ${event.name} (uuid: ${event.uuid}):`, error);
40
+ throw new Error(`Failed to retry event: ${error instanceof Error ? error.message : String(error)}`);
41
+ }
42
+ }
43
+ /**
44
+ * Retries multiple failed events in batch.
45
+ */
46
+ async retryMultipleFailedEvents(events) {
47
+ loggerUseCases.info(`Batch retrying ${events.length} failed events`);
48
+ let successCount = 0;
49
+ let failedCount = 0;
50
+ for (const event of events) {
51
+ try {
52
+ await this.retryFailedEvent(event);
53
+ successCount++;
54
+ }
55
+ catch (error) {
56
+ loggerUseCases.error(`Failed to retry event ${event.name} (uuid: ${event.uuid}):`, error);
57
+ failedCount++;
58
+ }
59
+ }
60
+ loggerUseCases.info(`Batch retry completed: ${successCount} successful, ${failedCount} failed`);
61
+ return { success: successCount, failed: failedCount };
62
+ }
63
+ /**
64
+ * Permanently deletes a failed event from the dead letter queue.
65
+ * Use with caution as this action cannot be undone.
66
+ */
67
+ async deleteFailedEvent(event) {
68
+ loggerUseCases.info(`Permanently deleting failed event: ${event.name} (uuid: ${event.uuid})`);
69
+ try {
70
+ await this.repository.remove(event.uuid);
71
+ loggerUseCases.info(`Successfully deleted event: ${event.name} (uuid: ${event.uuid})`);
72
+ }
73
+ catch (error) {
74
+ loggerUseCases.error(`Failed to delete event ${event.name} (uuid: ${event.uuid}):`, error);
75
+ throw new Error(`Failed to delete event: ${error instanceof Error ? error.message : String(error)}`);
76
+ }
77
+ }
78
+ /**
79
+ * Deletes multiple failed events in batch.
80
+ */
81
+ async deleteMultipleFailedEvents(events) {
82
+ loggerUseCases.info(`Batch deleting ${events.length} failed events`);
83
+ let successCount = 0;
84
+ let failedCount = 0;
85
+ for (const event of events) {
86
+ try {
87
+ await this.deleteFailedEvent(event);
88
+ successCount++;
89
+ }
90
+ catch (error) {
91
+ loggerUseCases.error(`Failed to delete event ${event.name} (uuid: ${event.uuid}):`, error);
92
+ failedCount++;
93
+ }
94
+ }
95
+ loggerUseCases.info(`Batch delete completed: ${successCount} successful, ${failedCount} failed`);
96
+ return { success: successCount, failed: failedCount };
97
+ }
98
+ }
99
+ export const deadLetterQueueUseCases = new DeadLetterQueueUseCases();
@@ -0,0 +1,7 @@
1
+ import { DomainEvent } from "../domain/event_sourcing";
2
+ declare class EventService {
3
+ listAllEvents(): Promise<DomainEvent[]>;
4
+ republishSync(event: DomainEvent): Promise<void>;
5
+ }
6
+ export declare const eventService: EventService;
7
+ export {};
@@ -0,0 +1,24 @@
1
+ import { DomainEventRepository } from "../adapters/repositories/domain_event.repository";
2
+ import { EEventStatus } from "../domain/event_sourcing";
3
+ import { loggerUseCases } from "../infrastructure/logger";
4
+ import { EventBus } from "../infrastructure/workers/EventBus";
5
+ class EventService {
6
+ async listAllEvents() {
7
+ loggerUseCases.info("Fetching all events from DomainEvent repository");
8
+ // Ordered by created_at DESC from repository query
9
+ const pending = await DomainEventRepository.findByStatuses([
10
+ EEventStatus.PENDING,
11
+ EEventStatus.PROCESSING,
12
+ EEventStatus.ACKNOWLEDGED,
13
+ EEventStatus.FAILED,
14
+ EEventStatus.CANCELLED,
15
+ ]);
16
+ return pending;
17
+ }
18
+ async republishSync(event) {
19
+ const cloned = event.cloneWithReset();
20
+ loggerUseCases.info(`Republishing event sync: ${cloned.name} (${cloned.uuid})`);
21
+ await EventBus.publishSync(cloned);
22
+ }
23
+ }
24
+ export const eventService = new EventService();
@@ -0,0 +1,7 @@
1
+ import { NetworkStatus } from "../domain/connectivity";
2
+ export declare class NetworkUseCases {
3
+ private networkStatus;
4
+ getNetworkStatus(): Promise<NetworkStatus>;
5
+ showToastNotification(networkStatus: NetworkStatus): Promise<void>;
6
+ }
7
+ export declare const networkUseCases: NetworkUseCases;
@@ -0,0 +1,43 @@
1
+ import { NetworkAdapter } from "../adapters/Network.adapter";
2
+ import { InternetIsDownEvent, InternetIsUpEvent } from "../domain/events";
3
+ import { loggerUseCases } from "../infrastructure/logger";
4
+ import { UI_NOTIFICATION_EVENT } from "../infrastructure/ui/events";
5
+ import { UIEventBus } from "../infrastructure/ui/UIEventBus";
6
+ export class NetworkUseCases {
7
+ networkStatus = null;
8
+ async getNetworkStatus() {
9
+ const networkStatus = await NetworkAdapter.getStatus();
10
+ if (networkStatus.isConnected) {
11
+ UIEventBus.emit(InternetIsUpEvent.name, true);
12
+ }
13
+ else {
14
+ UIEventBus.emit(InternetIsDownEvent.name, false);
15
+ }
16
+ this.showToastNotification(networkStatus);
17
+ this.networkStatus = networkStatus;
18
+ return this.networkStatus;
19
+ }
20
+ async showToastNotification(networkStatus) {
21
+ const showToast = networkStatus.isConnected !== this.networkStatus?.isConnected;
22
+ if (!showToast) {
23
+ return;
24
+ }
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",
31
+ });
32
+ }
33
+ 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}`,
39
+ });
40
+ }
41
+ }
42
+ }
43
+ export const networkUseCases = new NetworkUseCases();
@@ -0,0 +1,25 @@
1
+ import { type BluetoothDevice, type IPrinterDriver, type ISelectedPrinter, type PairedPrinter } from "../domain/print";
2
+ import type { RefObject } from "react";
3
+ import type { View } from "react-native";
4
+ declare class PrinterService {
5
+ private readonly bluetooth;
6
+ private cachedPrinter;
7
+ setDriver(driver: IPrinterDriver): void;
8
+ hasDriver(): boolean;
9
+ getPairedDevices(): BluetoothDevice[];
10
+ getPairedPrinters(): PairedPrinter[];
11
+ isConnected(): boolean;
12
+ connect(address: string, name: string): Promise<boolean>;
13
+ disconnect(): Promise<void>;
14
+ getSelectedPrinter(): Promise<ISelectedPrinter | null>;
15
+ saveSelectedPrinter(printer: ISelectedPrinter): Promise<void>;
16
+ clearSelectedPrinter(): Promise<void>;
17
+ printTestPage(): Promise<boolean>;
18
+ printImageBase64(base64Data: string): Promise<boolean>;
19
+ printFromView(viewRef: RefObject<View | null>): Promise<boolean>;
20
+ printHtml(html: string): Promise<boolean>;
21
+ private htmlToPdfBase64;
22
+ private ensureConnected;
23
+ }
24
+ export declare const printerService: PrinterService;
25
+ export {};