@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,220 @@
1
+ import { ReceiptExporterAdapter } from "../adapters/ReceiptExporter.adapter";
2
+ import { SettingsRepository } from "../adapters/repositories/setting.repository";
3
+ import { getPrinterDriver, hasPrinterDriver, setPrinterDriver, } from "../domain/print";
4
+ import { loggerUseCases } from "../infrastructure/logger";
5
+ import { UI_NOTIFICATION_EVENT } from "../infrastructure/ui/events";
6
+ import { UIEventBus } from "../infrastructure/ui/UIEventBus";
7
+ import { File } from "expo-file-system";
8
+ import * as Print from "expo-print";
9
+ import { bluetoothService } from "./bluetooth.service";
10
+ class PrinterService {
11
+ bluetooth = bluetoothService;
12
+ cachedPrinter = null;
13
+ setDriver(driver) {
14
+ setPrinterDriver(driver);
15
+ }
16
+ hasDriver() {
17
+ return hasPrinterDriver();
18
+ }
19
+ getPairedDevices() {
20
+ return getPrinterDriver().getPairedDevices();
21
+ }
22
+ getPairedPrinters() {
23
+ return getPrinterDriver().getPairedPrinters();
24
+ }
25
+ isConnected() {
26
+ return getPrinterDriver().isConnected();
27
+ }
28
+ async connect(address, name) {
29
+ const hasPermissions = await this.bluetooth.ensurePermissionsForPrinter();
30
+ if (!hasPermissions) {
31
+ return false;
32
+ }
33
+ try {
34
+ await getPrinterDriver().connectBluetooth(address);
35
+ const printer = {
36
+ name,
37
+ address,
38
+ selectedAt: new Date().toISOString(),
39
+ };
40
+ await this.saveSelectedPrinter(printer);
41
+ UIEventBus.emit(UI_NOTIFICATION_EVENT, {
42
+ type: "success",
43
+ text1: "Impresora conectada",
44
+ text2: `Conectado a ${name}`,
45
+ });
46
+ return true;
47
+ }
48
+ catch (error) {
49
+ loggerUseCases.error(`Failed to connect to printer: ${name}`, error);
50
+ UIEventBus.emit(UI_NOTIFICATION_EVENT, {
51
+ type: "error",
52
+ text1: "Error de conexión",
53
+ text2: `No se pudo conectar a ${name}`,
54
+ });
55
+ return false;
56
+ }
57
+ }
58
+ async disconnect() {
59
+ try {
60
+ await getPrinterDriver().disconnect();
61
+ UIEventBus.emit(UI_NOTIFICATION_EVENT, {
62
+ type: "info",
63
+ text1: "Desconectado",
64
+ text2: "Impresora desconectada",
65
+ });
66
+ }
67
+ catch (error) {
68
+ loggerUseCases.error("Error disconnecting from printer", error);
69
+ }
70
+ }
71
+ async getSelectedPrinter() {
72
+ if (this.cachedPrinter) {
73
+ return this.cachedPrinter;
74
+ }
75
+ const printer = await SettingsRepository.getSettingByName("common.selected_printer" /* ECommonSetting.SELECTED_PRINTER */);
76
+ this.cachedPrinter = printer;
77
+ return printer;
78
+ }
79
+ async saveSelectedPrinter(printer) {
80
+ await SettingsRepository.saveOneSetting("common.selected_printer" /* ECommonSetting.SELECTED_PRINTER */, printer);
81
+ this.cachedPrinter = printer;
82
+ }
83
+ async clearSelectedPrinter() {
84
+ await SettingsRepository.saveOneSetting("common.selected_printer" /* ECommonSetting.SELECTED_PRINTER */, null);
85
+ this.cachedPrinter = null;
86
+ }
87
+ async printTestPage() {
88
+ if (!this.isConnected()) {
89
+ UIEventBus.emit(UI_NOTIFICATION_EVENT, {
90
+ type: "error",
91
+ text1: "Sin conexión",
92
+ text2: "Conecta una impresora primero",
93
+ });
94
+ return false;
95
+ }
96
+ try {
97
+ await getPrinterDriver().printText("=== PRUEBA DE IMPRESIÓN ===", {
98
+ alignment: "center",
99
+ bold: true,
100
+ fontSize: "large",
101
+ });
102
+ await getPrinterDriver().printText("Impresora configurada correctamente", {
103
+ alignment: "center",
104
+ fontSize: "medium",
105
+ });
106
+ await getPrinterDriver().printText(new Date().toLocaleString(), {
107
+ alignment: "center",
108
+ fontSize: "small",
109
+ });
110
+ UIEventBus.emit(UI_NOTIFICATION_EVENT, {
111
+ type: "success",
112
+ text1: "Impresión exitosa",
113
+ text2: "Página de prueba impresa",
114
+ });
115
+ return true;
116
+ }
117
+ catch (error) {
118
+ loggerUseCases.error("Error printing test page", error);
119
+ UIEventBus.emit(UI_NOTIFICATION_EVENT, {
120
+ type: "error",
121
+ text1: "Error de impresión",
122
+ text2: "No se pudo imprimir la página de prueba",
123
+ });
124
+ return false;
125
+ }
126
+ }
127
+ async printImageBase64(base64Data) {
128
+ const connected = await this.ensureConnected();
129
+ if (!connected)
130
+ return false;
131
+ try {
132
+ await getPrinterDriver().printImageBase64(base64Data);
133
+ return true;
134
+ }
135
+ catch (error) {
136
+ loggerUseCases.error("Error printing image", error);
137
+ return false;
138
+ }
139
+ }
140
+ async printFromView(viewRef) {
141
+ const connected = await this.ensureConnected();
142
+ if (!connected)
143
+ return false;
144
+ try {
145
+ const imageBase64 = await ReceiptExporterAdapter.captureAsImageBase64(viewRef);
146
+ if (!imageBase64) {
147
+ loggerUseCases.warn("Could not capture view for printing");
148
+ return false;
149
+ }
150
+ await getPrinterDriver().printImageBase64(imageBase64);
151
+ UIEventBus.emit(UI_NOTIFICATION_EVENT, {
152
+ type: "success",
153
+ text1: "Impresión enviada",
154
+ text2: "Documento enviado a la impresora",
155
+ });
156
+ return true;
157
+ }
158
+ catch (error) {
159
+ loggerUseCases.error("Error printing from view", error);
160
+ return false;
161
+ }
162
+ }
163
+ async printHtml(html) {
164
+ const connected = await this.ensureConnected();
165
+ if (!connected)
166
+ return false;
167
+ try {
168
+ const pdfBase64 = await this.htmlToPdfBase64(html);
169
+ if (!pdfBase64) {
170
+ loggerUseCases.warn("Could not convert HTML to PDF");
171
+ return false;
172
+ }
173
+ loggerUseCases.info("PDF base64 length:", pdfBase64.length);
174
+ await getPrinterDriver().printPdfBase64(pdfBase64, 1);
175
+ return true;
176
+ }
177
+ catch (error) {
178
+ loggerUseCases.error("Error printing HTML", error);
179
+ return false;
180
+ }
181
+ }
182
+ async htmlToPdfBase64(html) {
183
+ try {
184
+ const THERMAL_WIDTH_PX = 576;
185
+ const THERMAL_HEIGHT_PX = 1500;
186
+ const { uri } = await Print.printToFileAsync({
187
+ html,
188
+ width: THERMAL_WIDTH_PX,
189
+ height: THERMAL_HEIGHT_PX,
190
+ });
191
+ if (!uri)
192
+ return null;
193
+ loggerUseCases.info("PDF generated at:", uri);
194
+ const file = new File(uri);
195
+ const pdfBase64 = await file.base64();
196
+ await file.delete();
197
+ return pdfBase64;
198
+ }
199
+ catch (error) {
200
+ loggerUseCases.error("Error converting HTML to PDF", error);
201
+ return null;
202
+ }
203
+ }
204
+ async ensureConnected() {
205
+ if (this.isConnected()) {
206
+ return true;
207
+ }
208
+ const printer = await this.getSelectedPrinter();
209
+ if (!printer) {
210
+ UIEventBus.emit(UI_NOTIFICATION_EVENT, {
211
+ type: "error",
212
+ text1: "Sin impresora",
213
+ text2: "Selecciona una impresora primero",
214
+ });
215
+ return false;
216
+ }
217
+ return this.connect(printer.address, printer.name);
218
+ }
219
+ }
220
+ export const printerService = new PrinterService();
@@ -0,0 +1,17 @@
1
+ import { type IAjaxInterceptedMessage, type IContentReadyMessage, type IInjectedScript, type IInjectionReadyMessage, type IPrintImageMessage, type IPrintRequestMessage, type TWebViewMessage } from "../domain/webview";
2
+ declare class WebViewService {
3
+ private interceptors;
4
+ registerInterceptor(interceptor: IInjectedScript): void;
5
+ unregisterInterceptor(name: string): void;
6
+ getInterceptor(name: string): IInjectedScript | undefined;
7
+ getAllInterceptors(): IInjectedScript[];
8
+ combineScripts(scripts?: IInjectedScript[], additionalScript?: string): string;
9
+ parseMessage(rawData: string): TWebViewMessage | null;
10
+ isPrintRequest(msg: TWebViewMessage): msg is IPrintRequestMessage;
11
+ isPrintImage(msg: TWebViewMessage): msg is IPrintImageMessage;
12
+ isContentReady(msg: TWebViewMessage): msg is IContentReadyMessage;
13
+ isInjectionReady(msg: TWebViewMessage): msg is IInjectionReadyMessage;
14
+ isAjaxIntercepted(msg: TWebViewMessage): msg is IAjaxInterceptedMessage;
15
+ }
16
+ export declare const webViewService: WebViewService;
17
+ export {};
@@ -0,0 +1,59 @@
1
+ import { EWebViewMessageType, } from "../domain/webview";
2
+ import { safeJsonParse } from "../tools/utils/serializer";
3
+ class WebViewService {
4
+ interceptors = new Map();
5
+ registerInterceptor(interceptor) {
6
+ this.interceptors.set(interceptor.name, interceptor);
7
+ }
8
+ unregisterInterceptor(name) {
9
+ this.interceptors.delete(name);
10
+ }
11
+ getInterceptor(name) {
12
+ return this.interceptors.get(name);
13
+ }
14
+ getAllInterceptors() {
15
+ return Array.from(this.interceptors.values());
16
+ }
17
+ combineScripts(scripts, additionalScript) {
18
+ const parts = [];
19
+ if (scripts) {
20
+ for (const script of scripts) {
21
+ parts.push(script.script);
22
+ }
23
+ }
24
+ if (additionalScript) {
25
+ parts.push(additionalScript);
26
+ }
27
+ return parts.join("\n\n");
28
+ }
29
+ parseMessage(rawData) {
30
+ try {
31
+ const parsed = safeJsonParse(rawData);
32
+ if (!parsed || !parsed.type)
33
+ return null;
34
+ const validTypes = Object.values(EWebViewMessageType);
35
+ if (!validTypes.includes(parsed.type))
36
+ return null;
37
+ return parsed;
38
+ }
39
+ catch {
40
+ return null;
41
+ }
42
+ }
43
+ isPrintRequest(msg) {
44
+ return msg.type === EWebViewMessageType.PRINT_REQUEST;
45
+ }
46
+ isPrintImage(msg) {
47
+ return msg.type === EWebViewMessageType.PRINT_IMAGE;
48
+ }
49
+ isContentReady(msg) {
50
+ return msg.type === EWebViewMessageType.CONTENT_READY;
51
+ }
52
+ isInjectionReady(msg) {
53
+ return msg.type === EWebViewMessageType.INJECTION_READY;
54
+ }
55
+ isAjaxIntercepted(msg) {
56
+ return msg.type === EWebViewMessageType.AJAX_INTERCEPTED;
57
+ }
58
+ }
59
+ export const webViewService = new WebViewService();
@@ -0,0 +1 @@
1
+ export declare const getUserInitials: (fullName: string, maxInitials?: number) => string;
@@ -0,0 +1,12 @@
1
+ export const getUserInitials = (fullName, maxInitials = 2) => {
2
+ if (!fullName || typeof fullName !== "string")
3
+ return "";
4
+ const words = fullName.trim().split(/\s+/).filter(Boolean);
5
+ if (words.length === 0)
6
+ return "";
7
+ const initials = words.length > 1 ? [words[0], words[words.length - 1]] : [words[0]];
8
+ return initials
9
+ .slice(0, maxInitials)
10
+ .map((word) => word.charAt(0).toUpperCase())
11
+ .join("");
12
+ };
@@ -0,0 +1,120 @@
1
+ /**
2
+ * Converts the input value into an array. If the value is already an array, it is returned as is.
3
+ * If the value is a Set, it is converted to an array. Otherwise, the value is wrapped in an array.
4
+ *
5
+ * @param value The value to convert. It can be a single item, an array, a Set, or undefined.
6
+ * @returns An array containing the input value(s). If the input is undefined or null, an empty array is returned.
7
+ *
8
+ * @example
9
+ * // Single value: wrapped in an array
10
+ * const single = convertToArray(42);
11
+ * // single: [42]
12
+ *
13
+ * @example
14
+ * // Already an array: returned as-is
15
+ * const fromArray = convertToArray(['a', 'b', 'c']);
16
+ * // fromArray: ['a', 'b', 'c']
17
+ *
18
+ * @example
19
+ * // From a Set: converted to array
20
+ * const mySet = new Set<number>([1, 2, 3]);
21
+ * const fromSet = convertToArray(mySet);
22
+ * // fromSet: [1, 2, 3]
23
+ */
24
+ export declare function convertToArray<T>(value: T | T[] | Set<T> | undefined): T[];
25
+ type PropertyKey = string | number | symbol;
26
+ type KeySelector<T, K extends PropertyKey> = keyof T | ((item: T) => K);
27
+ /**
28
+ * Groups an array of items by a given property or key-selector function.
29
+ *
30
+ * @param array The array of items to group.
31
+ * @param selector Either the name of a property on T, or a function that returns the key.
32
+ * @returns A record where each key maps to an array of items sharing that key.
33
+ *
34
+ * @example
35
+ * interface Product { id: number; name: string; category: string; }
36
+ * const products: Product[] = [
37
+ * { id: 1, name: 'Milk', category: 'dairy' },
38
+ * { id: 2, name: 'Cheese', category: 'dairy' },
39
+ * { id: 3, name: 'Apple', category: 'fruit' },
40
+ * ];
41
+ *
42
+ * // Group by property:
43
+ * const byCategory = groupBy(products, 'category');
44
+ * // { dairy: [ {…}, {…} ], fruit: [ {…} ] }
45
+ *
46
+ * // Group by function:
47
+ * const byFirstLetter = groupBy(products, p => p.name[0]);
48
+ * // { M: [ {…} ], C: [ {…} ], A: [ {…} ] }
49
+ */
50
+ export declare function groupBy<T, K extends PropertyKey>(array: T[], selector: KeySelector<T, K>): Record<K, T[]>;
51
+ /**
52
+ * Creates a lookup object where each key maps to the last item in the array
53
+ * that corresponds to that key. If multiple items share the same key,
54
+ * the last one wins.
55
+ *
56
+ * @param array – The array of items to index.
57
+ * @param selector – A property name of T, or a function that returns the key.
58
+ * @returns A record where each key maps to a single item.
59
+ *
60
+ * @example
61
+ * interface User { id: number; name: string; }
62
+ * const users: User[] = [
63
+ * { id: 1, name: 'Alice' },
64
+ * { id: 2, name: 'Bob' },
65
+ * { id: 1, name: 'Alicia' },
66
+ * ];
67
+ *
68
+ * // Index by property:
69
+ * const byId = keyBy(users, 'id');
70
+ * // byId === {
71
+ * // 1: { id: 1, name: 'Alicia' }, // last one wins
72
+ * // 2: { id: 2, name: 'Bob' }
73
+ * // }
74
+ *
75
+ * @example
76
+ * // Index by function:
77
+ * const byInitial = keyBy(users, u => u.name[0]);
78
+ * // byInitial === {
79
+ * // A: { id: 1, name: 'Alicia' },
80
+ * // B: { id: 2, name: 'Bob' }
81
+ * // }
82
+ */
83
+ export declare function keyBy<T, K extends PropertyKey>(array: T[], selector: KeySelector<T, K>): Record<K, T>;
84
+ /**
85
+ * Creates a lookup Map where each key maps to the last value
86
+ * produced by `valueSelector` for items in the array.
87
+ * If multiple items share the same key, the last one wins.
88
+ *
89
+ * @param array – The array of items to index.
90
+ * @param keySelector – A property name of T, or a function that returns the key.
91
+ * @param valueSelector – A function that returns the value to store for each key.
92
+ * @returns A Map where each key maps to a single value.
93
+ *
94
+ * @example
95
+ * interface User { id: number; name: string; }
96
+ * const users: User[] = [
97
+ * { id: 1, name: 'Alice' },
98
+ * { id: 2, name: 'Bob' },
99
+ * { id: 1, name: 'Alicia' },
100
+ * ];
101
+ *
102
+ * // Map by property, valueSelector returns the user’s name:
103
+ * const nameMap = toMap(users, 'id', u => u.name);
104
+ * // nameMap.get(1) === 'Alicia' // last one wins
105
+ * // nameMap.get(2) === 'Bob'
106
+ *
107
+ * @example
108
+ * interface MoveLine { id: number; product_id: number; quantity: number; }
109
+ * const moves: MoveLine[] = [
110
+ * { id: 17, product_id: 842, quantity: 42 },
111
+ * { id: 18, product_id: 838, quantity: 45 },
112
+ * ];
113
+ *
114
+ * // Map product_id → quantity:
115
+ * const qtyMap = toMap(moves, m => m.product_id, m => m.quantity);
116
+ * // qtyMap.get(842) === 42
117
+ * // qtyMap.get(838) === 45
118
+ */
119
+ export declare function toMap<T, K extends PropertyKey, V>(array: T[], keySelector: KeySelector<T, K>, valueSelector: (item: T) => V): Map<K, V>;
120
+ export {};
@@ -0,0 +1,158 @@
1
+ /**
2
+ * Converts the input value into an array. If the value is already an array, it is returned as is.
3
+ * If the value is a Set, it is converted to an array. Otherwise, the value is wrapped in an array.
4
+ *
5
+ * @param value The value to convert. It can be a single item, an array, a Set, or undefined.
6
+ * @returns An array containing the input value(s). If the input is undefined or null, an empty array is returned.
7
+ *
8
+ * @example
9
+ * // Single value: wrapped in an array
10
+ * const single = convertToArray(42);
11
+ * // single: [42]
12
+ *
13
+ * @example
14
+ * // Already an array: returned as-is
15
+ * const fromArray = convertToArray(['a', 'b', 'c']);
16
+ * // fromArray: ['a', 'b', 'c']
17
+ *
18
+ * @example
19
+ * // From a Set: converted to array
20
+ * const mySet = new Set<number>([1, 2, 3]);
21
+ * const fromSet = convertToArray(mySet);
22
+ * // fromSet: [1, 2, 3]
23
+ */
24
+ export function convertToArray(value) {
25
+ if (value === undefined || value === null) {
26
+ return [];
27
+ }
28
+ if (value instanceof Set) {
29
+ return Array.from(value);
30
+ }
31
+ if (!Array.isArray(value)) {
32
+ return [value];
33
+ }
34
+ return value;
35
+ }
36
+ /**
37
+ * Groups an array of items by a given property or key-selector function.
38
+ *
39
+ * @param array The array of items to group.
40
+ * @param selector Either the name of a property on T, or a function that returns the key.
41
+ * @returns A record where each key maps to an array of items sharing that key.
42
+ *
43
+ * @example
44
+ * interface Product { id: number; name: string; category: string; }
45
+ * const products: Product[] = [
46
+ * { id: 1, name: 'Milk', category: 'dairy' },
47
+ * { id: 2, name: 'Cheese', category: 'dairy' },
48
+ * { id: 3, name: 'Apple', category: 'fruit' },
49
+ * ];
50
+ *
51
+ * // Group by property:
52
+ * const byCategory = groupBy(products, 'category');
53
+ * // { dairy: [ {…}, {…} ], fruit: [ {…} ] }
54
+ *
55
+ * // Group by function:
56
+ * const byFirstLetter = groupBy(products, p => p.name[0]);
57
+ * // { M: [ {…} ], C: [ {…} ], A: [ {…} ] }
58
+ */
59
+ export function groupBy(array, selector) {
60
+ const getKey = typeof selector === "function"
61
+ ? selector
62
+ : (item) => item[selector];
63
+ return array.reduce((groups, item) => {
64
+ const key = getKey(item);
65
+ if (!groups[key]) {
66
+ groups[key] = [];
67
+ }
68
+ groups[key].push(item);
69
+ return groups;
70
+ }, {});
71
+ }
72
+ /**
73
+ * Creates a lookup object where each key maps to the last item in the array
74
+ * that corresponds to that key. If multiple items share the same key,
75
+ * the last one wins.
76
+ *
77
+ * @param array – The array of items to index.
78
+ * @param selector – A property name of T, or a function that returns the key.
79
+ * @returns A record where each key maps to a single item.
80
+ *
81
+ * @example
82
+ * interface User { id: number; name: string; }
83
+ * const users: User[] = [
84
+ * { id: 1, name: 'Alice' },
85
+ * { id: 2, name: 'Bob' },
86
+ * { id: 1, name: 'Alicia' },
87
+ * ];
88
+ *
89
+ * // Index by property:
90
+ * const byId = keyBy(users, 'id');
91
+ * // byId === {
92
+ * // 1: { id: 1, name: 'Alicia' }, // last one wins
93
+ * // 2: { id: 2, name: 'Bob' }
94
+ * // }
95
+ *
96
+ * @example
97
+ * // Index by function:
98
+ * const byInitial = keyBy(users, u => u.name[0]);
99
+ * // byInitial === {
100
+ * // A: { id: 1, name: 'Alicia' },
101
+ * // B: { id: 2, name: 'Bob' }
102
+ * // }
103
+ */
104
+ export function keyBy(array, selector) {
105
+ const getKey = typeof selector === "function"
106
+ ? selector
107
+ : (item) => item[selector];
108
+ return array.reduce((map, item) => {
109
+ const key = getKey(item);
110
+ map[key] = item;
111
+ return map;
112
+ }, {});
113
+ }
114
+ /**
115
+ * Creates a lookup Map where each key maps to the last value
116
+ * produced by `valueSelector` for items in the array.
117
+ * If multiple items share the same key, the last one wins.
118
+ *
119
+ * @param array – The array of items to index.
120
+ * @param keySelector – A property name of T, or a function that returns the key.
121
+ * @param valueSelector – A function that returns the value to store for each key.
122
+ * @returns A Map where each key maps to a single value.
123
+ *
124
+ * @example
125
+ * interface User { id: number; name: string; }
126
+ * const users: User[] = [
127
+ * { id: 1, name: 'Alice' },
128
+ * { id: 2, name: 'Bob' },
129
+ * { id: 1, name: 'Alicia' },
130
+ * ];
131
+ *
132
+ * // Map by property, valueSelector returns the user’s name:
133
+ * const nameMap = toMap(users, 'id', u => u.name);
134
+ * // nameMap.get(1) === 'Alicia' // last one wins
135
+ * // nameMap.get(2) === 'Bob'
136
+ *
137
+ * @example
138
+ * interface MoveLine { id: number; product_id: number; quantity: number; }
139
+ * const moves: MoveLine[] = [
140
+ * { id: 17, product_id: 842, quantity: 42 },
141
+ * { id: 18, product_id: 838, quantity: 45 },
142
+ * ];
143
+ *
144
+ * // Map product_id → quantity:
145
+ * const qtyMap = toMap(moves, m => m.product_id, m => m.quantity);
146
+ * // qtyMap.get(842) === 42
147
+ * // qtyMap.get(838) === 45
148
+ */
149
+ export function toMap(array, keySelector, valueSelector) {
150
+ const getKey = (item) => typeof keySelector === "function"
151
+ ? keySelector(item)
152
+ : item[keySelector];
153
+ const map = new Map();
154
+ for (const item of array) {
155
+ map.set(getKey(item), valueSelector(item));
156
+ }
157
+ return map;
158
+ }
@@ -0,0 +1,70 @@
1
+ interface FormatDateOptions {
2
+ locale?: string | null;
3
+ showTime?: boolean;
4
+ }
5
+ /**
6
+ * Formatea una fecha en la zona horaria indicada respetando la granularidad de la entrada.
7
+ *
8
+ * Reglas de detección:
9
+ * 1. Si `input` es un string 'YYYY-MM-DD' (solo fecha) => se interpreta como medianoche (00:00:00)
10
+ * en la zona horaria destino y se devuelve SOLO la parte de fecha (sin hora).
11
+ * 2. Si `input` incluye componente de tiempo (ISO completo o Date) => se convierte a la zona destino
12
+ * y se muestra fecha + hora (HH:MM) salvo que se fuerce lo contrario mediante `options.showTime`.
13
+ * 3. Cuando `options.showTime` es `true` o `false` se sobre‑escribe la auto‑detección.
14
+ * 4. Si `timezone` es null/undefined o inválido se retorna la cadena "Error de formateo".
15
+ *
16
+ * Localización:
17
+ * - Usa el primer locale del dispositivo (`expo-localization`) como predeterminado.
18
+ * - Puedes forzar uno diferente con `options.locale` (ej: 'es-CR', 'en-US').
19
+ *
20
+ * Seguridad de zona horaria:
21
+ * - El parse de una fecha sin hora NO se hace en la zona local del dispositivo para luego convertir,
22
+ * sino directamente en la zona destino para evitar corrimientos de día.
23
+ *
24
+ * Ejemplos:
25
+ * ```ts
26
+ * formatDate('2025-09-02', 'America/Costa_Rica');
27
+ * // => "2 de septiembre de 2025"
28
+ *
29
+ * formatDate('2025-09-02T18:30:00Z', 'America/Costa_Rica');
30
+ * // => "2 de septiembre de 2025, 12:30 p. m." (dependiendo del locale real)
31
+ *
32
+ * formatDate(new Date('2025-09-02T23:15:00Z'), 'Europe/Madrid');
33
+ * // => "3 de septiembre de 2025, 01:15" (cambio de día por zona +02)
34
+ *
35
+ * formatDate('2025-09-02', 'America/Costa_Rica', { showTime: true });
36
+ * // => "2 de septiembre de 2025, 12:00 a. m." (fuerza hora)
37
+ * ```
38
+ *
39
+ * @param input Fecha (string ISO, 'YYYY-MM-DD' o instancia Date)
40
+ * @param timezone Zona horaria IANA (ej: 'America/Costa_Rica', 'Asia/Tokyo'). Si es null/undefined usa Costa Rica
41
+ * @param options Opcional: locale forzado y/o bandera para mostrar hora
42
+ * @returns Cadena localizada o "Error de formateo" si no se puede procesar
43
+ */
44
+ export declare function formatDate(input: string | Date, timezone: string | null | undefined, options?: FormatDateOptions): string;
45
+ /**
46
+ * Formatea una fecha usando automáticamente el timezone por defecto (Costa Rica).
47
+ * Útil para casos donde no se tiene acceso al timezone del usuario.
48
+ *
49
+ * @param input Fecha (string ISO, 'YYYY-MM-DD' o instancia Date)
50
+ * @param options Opcional: locale forzado y/o bandera para mostrar hora
51
+ * @returns Cadena localizada en timezone de Costa Rica
52
+ */
53
+ export declare function formatDateWithDefaultTimezone(input: string | Date, options?: FormatDateOptions): string;
54
+ /**
55
+ * Obtiene la fecha actual en formato YYYY-MM-DD en el timezone especificado.
56
+ * Útil para crear fechas de programación que respeten el timezone del usuario.
57
+ *
58
+ * @param timezone Zona horaria IANA. Si es null/undefined usa Costa Rica
59
+ * @returns Fecha actual en formato YYYY-MM-DD en el timezone especificado
60
+ */
61
+ export declare function getCurrentDateInTimezone(timezone?: string | null): string;
62
+ /**
63
+ * Obtiene la fecha y hora actual en formato ISO en el timezone especificado.
64
+ * Útil para timestamps que necesiten reflejar el timezone del usuario.
65
+ *
66
+ * @param timezone Zona horaria IANA. Si es null/undefined usa Costa Rica
67
+ * @returns Fecha actual en formato ISO en el timezone especificado
68
+ */
69
+ export declare function getCurrentDateTimeInTimezone(timezone?: string | null): string;
70
+ export {};