@sincpro/mobile 0.4.3 → 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 (197) 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/ReceiptExporter.adapter.js +10 -2
  5. package/dist/adapters/repositories/database_table.repository.d.ts +3 -2
  6. package/dist/adapters/repositories/database_table.repository.js +1 -1
  7. package/dist/adapters/repositories/document.repository.d.ts +81 -0
  8. package/dist/adapters/repositories/document.repository.js +653 -0
  9. package/dist/adapters/repositories/domain_event.repository.d.ts +17 -17
  10. package/dist/adapters/repositories/domain_event.repository.js +25 -31
  11. package/dist/adapters/repositories/domain_event_dead_letter.repository.d.ts +10 -10
  12. package/dist/adapters/repositories/domain_event_dead_letter.repository.js +14 -13
  13. package/dist/adapters/repositories/event_row.d.ts +13 -0
  14. package/dist/adapters/repositories/event_row.js +22 -0
  15. package/dist/adapters/repositories/sqlite_document_store.d.ts +33 -0
  16. package/dist/adapters/repositories/sqlite_document_store.js +201 -0
  17. package/dist/domain/connectivity/events.d.ts +5 -5
  18. package/dist/domain/connectivity/events.js +3 -3
  19. package/dist/domain/database/criteria.d.ts +19 -0
  20. package/dist/domain/database/criteria.js +36 -0
  21. package/dist/domain/database/criteria_clock.d.ts +8 -0
  22. package/dist/domain/database/criteria_clock.js +305 -0
  23. package/dist/domain/database/criteria_sql.d.ts +61 -0
  24. package/dist/domain/database/criteria_sql.js +476 -0
  25. package/dist/domain/database/database.d.ts +1 -0
  26. package/dist/domain/database/index.d.ts +3 -1
  27. package/dist/domain/database/index.js +3 -1
  28. package/dist/domain/database/migration_plan.d.ts +14 -0
  29. package/dist/domain/database/migration_plan.js +44 -0
  30. package/dist/domain/entity/change_tracking.d.ts +21 -0
  31. package/dist/domain/entity/change_tracking.js +71 -0
  32. package/dist/domain/entity/checks.d.ts +8 -0
  33. package/dist/domain/entity/checks.js +82 -0
  34. package/dist/domain/entity/entity.d.ts +39 -32
  35. package/dist/domain/entity/entity.js +94 -105
  36. package/dist/domain/entity/entity_collection.d.ts +15 -30
  37. package/dist/domain/entity/entity_collection.js +30 -121
  38. package/dist/domain/entity/index.d.ts +5 -0
  39. package/dist/domain/entity/index.js +5 -0
  40. package/dist/domain/entity/reconcile.d.ts +7 -0
  41. package/dist/domain/entity/reconcile.js +12 -0
  42. package/dist/domain/entity/relations.d.ts +27 -0
  43. package/dist/domain/entity/relations.js +69 -0
  44. package/dist/domain/entity/remote_sync.d.ts +4 -0
  45. package/dist/domain/entity/remote_sync.js +19 -0
  46. package/dist/domain/entity/values.d.ts +6 -0
  47. package/dist/domain/entity/values.js +13 -0
  48. package/dist/domain/events/catalog.d.ts +29 -0
  49. package/dist/domain/{events.js → events/catalog.js} +7 -11
  50. package/dist/domain/events/chain.d.ts +5 -0
  51. package/dist/domain/events/chain.js +6 -0
  52. package/dist/domain/{event_sourcing → events}/domain_event.d.ts +20 -22
  53. package/dist/domain/events/domain_event.js +227 -0
  54. package/dist/domain/events/index.d.ts +8 -0
  55. package/dist/domain/events/index.js +8 -0
  56. package/dist/domain/events/integration_event.d.ts +103 -0
  57. package/dist/domain/events/integration_event.js +72 -0
  58. package/dist/domain/events/label.d.ts +2 -0
  59. package/dist/domain/events/label.js +26 -0
  60. package/dist/domain/index.d.ts +0 -1
  61. package/dist/domain/index.js +0 -1
  62. package/dist/domain/print/events.d.ts +8 -4
  63. package/dist/domain/print/events.js +9 -4
  64. package/dist/domain/repositories/document_store.d.ts +33 -0
  65. package/dist/domain/repositories/document_store.js +5 -0
  66. package/dist/domain/repositories/hooks.d.ts +23 -0
  67. package/dist/domain/repositories/hooks.js +32 -0
  68. package/dist/domain/repositories/index.d.ts +4 -0
  69. package/dist/domain/repositories/index.js +4 -0
  70. package/dist/domain/{database → repositories}/repository.d.ts +9 -3
  71. package/dist/domain/settings.d.ts +4 -1
  72. package/dist/domain/settings.js +3 -0
  73. package/dist/domain/webview/events.d.ts +2 -2
  74. package/dist/domain/webview/events.js +2 -2
  75. package/dist/entrypoints/db/migrations.js +10 -10
  76. package/dist/entrypoints/queue/QueueProcessor.d.ts +1 -1
  77. package/dist/entrypoints/queue/activateDomain.subscriber.d.ts +2 -2
  78. package/dist/entrypoints/queue/activateDomain.subscriber.js +2 -2
  79. package/dist/entrypoints/queue/newAppSettings.handler.d.ts +2 -2
  80. package/dist/entrypoints/queue/newAppSettings.handler.js +1 -1
  81. package/dist/entrypoints/queue/printImage.subscriber.d.ts +1 -1
  82. package/dist/entrypoints/queue/printImage.subscriber.js +2 -2
  83. package/dist/entrypoints/queue/processWebViewMessage.subscriber.d.ts +1 -1
  84. package/dist/entrypoints/queue/processWebViewMessage.subscriber.js +1 -1
  85. package/dist/entrypoints/ui/AppShell.js +2 -2
  86. package/dist/entrypoints/ui/common_provider.d.ts +1 -13
  87. package/dist/entrypoints/ui/common_provider.js +4 -133
  88. package/dist/entrypoints/ui/domain_switcher.d.ts +2 -2
  89. package/dist/event_driven/index.d.ts +1 -0
  90. package/dist/event_driven/index.js +1 -0
  91. package/dist/{domain/event_sourcing/event_handler.d.ts → event_driven/subscriber.d.ts} +1 -1
  92. package/dist/exceptions.d.ts +21 -0
  93. package/dist/exceptions.js +30 -0
  94. package/dist/framework/base_module.d.ts +1 -1
  95. package/dist/framework/createApp.d.ts +3 -3
  96. package/dist/framework/domain_module.d.ts +1 -1
  97. package/dist/framework/feature.d.ts +26 -0
  98. package/dist/framework/feature.js +36 -0
  99. package/dist/framework/kernel.d.ts +1 -1
  100. package/dist/framework/kernel.js +17 -8
  101. package/dist/index.d.ts +1 -0
  102. package/dist/index.js +1 -0
  103. package/dist/infrastructure/database/connector.d.ts +2 -0
  104. package/dist/infrastructure/database/connector.js +22 -0
  105. package/dist/infrastructure/database/index.d.ts +1 -0
  106. package/dist/infrastructure/database/index.js +1 -0
  107. package/dist/infrastructure/database/schema.d.ts +9 -0
  108. package/dist/infrastructure/database/schema.js +61 -0
  109. package/dist/infrastructure/database/utils.d.ts +2 -0
  110. package/dist/infrastructure/database/utils.js +12 -4
  111. package/dist/infrastructure/event_chain.d.ts +6 -0
  112. package/dist/infrastructure/event_chain.js +25 -0
  113. package/dist/infrastructure/interceptor/intercept.d.ts +7 -2
  114. package/dist/infrastructure/interceptor/intercept.js +5 -2
  115. package/dist/infrastructure/telemetry/tracing/tracing_hooks.d.ts +9 -6
  116. package/dist/infrastructure/telemetry/tracing/tracing_hooks.js +61 -35
  117. package/dist/infrastructure/ui/UIEventBus.d.ts +3 -1
  118. package/dist/infrastructure/ui/UIEventBus.js +8 -1
  119. package/dist/infrastructure/ui/activity.d.ts +37 -0
  120. package/dist/infrastructure/ui/activity.js +84 -0
  121. package/dist/infrastructure/workers/CronWorker.d.ts +6 -4
  122. package/dist/infrastructure/workers/CronWorker.js +24 -18
  123. package/dist/infrastructure/workers/EventBus.d.ts +9 -5
  124. package/dist/infrastructure/workers/EventBus.js +68 -33
  125. package/dist/services/bluetooth.service.js +16 -14
  126. package/dist/services/dead_letter_queue.service.d.ts +7 -7
  127. package/dist/services/dead_letter_queue.service.js +0 -2
  128. package/dist/services/event.service.d.ts +3 -3
  129. package/dist/services/event.service.js +1 -1
  130. package/dist/services/network.service.d.ts +1 -1
  131. package/dist/services/network.service.js +17 -15
  132. package/dist/services/printer.service.d.ts +1 -1
  133. package/dist/services/printer.service.js +50 -44
  134. package/dist/tools/utils/date.js +4 -3
  135. package/dist/tools/utils/monetary.d.ts +6 -3
  136. package/dist/tools/utils/monetary.js +33 -21
  137. package/dist/tools/utils/serializer.d.ts +1 -1
  138. package/dist/tools/utils/serializer.js +32 -35
  139. package/dist/ui/activity/DeviceNotices.d.ts +1 -0
  140. package/dist/ui/activity/DeviceNotices.js +29 -0
  141. package/dist/ui/activity/ProcessToast.d.ts +2 -0
  142. package/dist/ui/activity/ProcessToast.js +71 -0
  143. package/dist/ui/{components/molecules → activity}/ProcessToastProvider.d.ts +1 -1
  144. package/dist/ui/activity/index.d.ts +4 -0
  145. package/dist/ui/activity/index.js +4 -0
  146. package/dist/ui/activity/useActivity.d.ts +9 -0
  147. package/dist/ui/activity/useActivity.js +48 -0
  148. package/dist/ui/components/atoms/DebugBanner.d.ts +1 -1
  149. package/dist/ui/components/molecules/BluetoothDeviceSelectorModal.d.ts +1 -1
  150. package/dist/ui/components/molecules/BluetoothDeviceSelectorModal.js +8 -2
  151. package/dist/ui/components/molecules/DeadLetterErrorBlock.d.ts +1 -1
  152. package/dist/ui/components/molecules/EventTimelineItem.d.ts +3 -3
  153. package/dist/ui/components/molecules/EventTimelineItem.js +1 -1
  154. package/dist/ui/components/molecules/GeoPermissionCard.d.ts +1 -1
  155. package/dist/ui/components/molecules/TimeZoneSelector.d.ts +1 -1
  156. package/dist/ui/components/molecules/TimeZoneSelectorModal.d.ts +1 -1
  157. package/dist/ui/components/molecules/TimeZoneSelectorModal.js +5 -3
  158. package/dist/ui/components/molecules/index.d.ts +1 -2
  159. package/dist/ui/components/molecules/index.js +1 -2
  160. package/dist/ui/components/organisms/BluetoothPrinterSelector.d.ts +1 -1
  161. package/dist/ui/components/organisms/BluetoothPrinterSelector.js +3 -0
  162. package/dist/ui/components/organisms/DatabaseInfoRow.d.ts +1 -1
  163. package/dist/ui/components/organisms/DeadLetterQueueRow.d.ts +5 -4
  164. package/dist/ui/components/organisms/EventRow.d.ts +4 -4
  165. package/dist/ui/components/organisms/EventRow.js +1 -1
  166. package/dist/ui/components/organisms/InjectableWebView.d.ts +2 -2
  167. package/dist/ui/components/organisms/InjectableWebView.js +6 -3
  168. package/dist/ui/components/organisms/Receipt.d.ts +2 -1
  169. package/dist/ui/components/organisms/TableInfoInfoRow.d.ts +1 -1
  170. package/dist/ui/screens/database/database.context.d.ts +2 -2
  171. package/dist/ui/screens/database/database.context.js +9 -18
  172. package/dist/ui/screens/database/database.json_detail.d.ts +1 -1
  173. package/dist/ui/screens/database/database.list.d.ts +1 -1
  174. package/dist/ui/screens/database/database.table_rows.d.ts +1 -1
  175. package/dist/ui/screens/dead_letter_queue/dead_letter_queue.context.d.ts +7 -7
  176. package/dist/ui/screens/dead_letter_queue/dead_letter_queue.list.d.ts +1 -1
  177. package/dist/ui/screens/events/events.context.d.ts +6 -6
  178. package/dist/ui/screens/events/events.context.js +20 -25
  179. package/dist/ui/screens/events/events.list.d.ts +1 -1
  180. package/package.json +51 -40
  181. package/dist/domain/event_sourcing/domain_event.js +0 -164
  182. package/dist/domain/event_sourcing/event.d.ts +0 -25
  183. package/dist/domain/event_sourcing/event.js +0 -25
  184. package/dist/domain/event_sourcing/index.d.ts +0 -2
  185. package/dist/domain/event_sourcing/index.js +0 -2
  186. package/dist/domain/events.d.ts +0 -33
  187. package/dist/infrastructure/ui/ToastHost.d.ts +0 -6
  188. package/dist/infrastructure/ui/ToastHost.js +0 -28
  189. package/dist/infrastructure/ui/events.d.ts +0 -1
  190. package/dist/infrastructure/ui/events.js +0 -1
  191. package/dist/ui/components/molecules/ProcessToast.d.ts +0 -8
  192. package/dist/ui/components/molecules/ProcessToast.js +0 -52
  193. /package/dist/domain/{repositories.d.ts → repositories/catalog.d.ts} +0 -0
  194. /package/dist/domain/{repositories.js → repositories/catalog.js} +0 -0
  195. /package/dist/domain/{database → repositories}/repository.js +0 -0
  196. /package/dist/{domain/event_sourcing/event_handler.js → event_driven/subscriber.js} +0 -0
  197. /package/dist/ui/{components/molecules → activity}/ProcessToastProvider.js +0 -0
@@ -1,5 +1,5 @@
1
- import { DomainEvent } from "../../domain/event_sourcing";
2
- export declare class WebViewMessageReceivedEvent extends DomainEvent {
1
+ import { IntegrationEvent } from "../../domain/events/integration_event";
2
+ export declare class WebViewMessageReceivedEvent extends IntegrationEvent {
3
3
  static readonly name = "common.webview.v1.message_received";
4
4
  static readonly label = "Procesando datos de la web";
5
5
  static readonly requiresNetwork = false;
@@ -1,5 +1,5 @@
1
- import { DomainEvent } from "../../domain/event_sourcing";
2
- export class WebViewMessageReceivedEvent extends DomainEvent {
1
+ import { IntegrationEvent } from "../../domain/events/integration_event";
2
+ export class WebViewMessageReceivedEvent extends IntegrationEvent {
3
3
  static name = "common.webview.v1.message_received";
4
4
  static label = "Procesando datos de la web";
5
5
  static requiresNetwork = false;
@@ -155,16 +155,16 @@ async function createSpansQueueTable() {
155
155
  ON ${DATABASE_TABLES.SPANS_QUEUE}(trace_id);
156
156
  `);
157
157
  }
158
+ function migration(name, migrationFn) {
159
+ return { name, tables: [name], migrationFn };
160
+ }
158
161
  const MIGRATIONS = [
159
- { name: DATABASE_TABLES.SETTINGS, migrationFn: createSettingsTable },
160
- { name: DATABASE_TABLES.EVENT_QUEUE, migrationFn: createEventQueueTable },
161
- { name: DATABASE_TABLES.DEAD_LETTER_QUEUE, migrationFn: createDeadLetterQueueTable },
162
- { name: DATABASE_TABLES.DOMAIN_EVENTS, migrationFn: createDomainEventsTable },
163
- {
164
- name: DATABASE_TABLES.DOMAIN_EVENTS_DEAD_LETTER,
165
- migrationFn: createDomainEventsDeadLetterTable,
166
- },
167
- { name: DATABASE_TABLES.TELEMETRY_QUEUE, migrationFn: createTelemetryQueueTable },
168
- { name: DATABASE_TABLES.SPANS_QUEUE, migrationFn: createSpansQueueTable },
162
+ migration(DATABASE_TABLES.SETTINGS, createSettingsTable),
163
+ migration(DATABASE_TABLES.EVENT_QUEUE, createEventQueueTable),
164
+ migration(DATABASE_TABLES.DEAD_LETTER_QUEUE, createDeadLetterQueueTable),
165
+ migration(DATABASE_TABLES.DOMAIN_EVENTS, createDomainEventsTable),
166
+ migration(DATABASE_TABLES.DOMAIN_EVENTS_DEAD_LETTER, createDomainEventsDeadLetterTable),
167
+ migration(DATABASE_TABLES.TELEMETRY_QUEUE, createTelemetryQueueTable),
168
+ migration(DATABASE_TABLES.SPANS_QUEUE, createSpansQueueTable),
169
169
  ];
170
170
  export default MIGRATIONS;
@@ -1,4 +1,4 @@
1
- import type { Subscriber } from "../../domain/event_sourcing";
1
+ import type { Subscriber } from "../../event_driven";
2
2
  export interface SyncResult {
3
3
  changed: boolean;
4
4
  added: number;
@@ -1,5 +1,5 @@
1
- import { DomainEvent, Subscriber } from "../../domain/event_sourcing";
2
- import { ActivateDomainEvent, DeactivateDomainEvent } from "../../domain/events";
1
+ import { ActivateDomainEvent, DeactivateDomainEvent, DomainEvent } from "../../domain/events";
2
+ import { Subscriber } from "../../event_driven";
3
3
  export declare class ActivateDomainSubscriber extends Subscriber {
4
4
  readonly requiresAuth = false;
5
5
  listen: (typeof ActivateDomainEvent | typeof DeactivateDomainEvent)[];
@@ -1,5 +1,5 @@
1
- import { Subscriber } from "../../domain/event_sourcing";
2
- import { ActivateDomainEvent, DeactivateDomainEvent } from "../../domain/events";
1
+ import { ActivateDomainEvent, DeactivateDomainEvent, } from "../../domain/events";
2
+ import { Subscriber } from "../../event_driven";
3
3
  import { orchestrator } from "../../framework/orchestrator";
4
4
  export class ActivateDomainSubscriber extends Subscriber {
5
5
  requiresAuth = false;
@@ -1,5 +1,5 @@
1
- import { DomainEvent, Subscriber } from "../../domain/event_sourcing";
2
- import { NewAppSettingsEvent } from "../../domain/events";
1
+ import { DomainEvent, NewAppSettingsEvent } from "../../domain/events";
2
+ import { Subscriber } from "../../event_driven";
3
3
  export declare class NewAppSettingsSubscriber extends Subscriber {
4
4
  listen: (typeof NewAppSettingsEvent)[];
5
5
  getEvent(event: DomainEvent): NewAppSettingsEvent;
@@ -1,6 +1,6 @@
1
1
  import { SettingsRepository } from "../../adapters/repositories/setting.repository";
2
- import { Subscriber } from "../../domain/event_sourcing";
3
2
  import { NewAppSettingsEvent } from "../../domain/events";
3
+ import { Subscriber } from "../../event_driven";
4
4
  import { loggerUseCases } from "../../infrastructure/logger";
5
5
  export class NewAppSettingsSubscriber extends Subscriber {
6
6
  listen = [NewAppSettingsEvent];
@@ -1,5 +1,5 @@
1
- import { Subscriber } from "../../domain/event_sourcing";
2
1
  import { PrintImageRequestedEvent } from "../../domain/events";
2
+ import { Subscriber } from "../../event_driven";
3
3
  export declare class PrintImageSubscriber extends Subscriber {
4
4
  readonly requiresAuth = false;
5
5
  listen: (typeof PrintImageRequestedEvent)[];
@@ -1,5 +1,5 @@
1
- import { Subscriber } from "../../domain/event_sourcing";
2
1
  import { PrintImageRequestedEvent } from "../../domain/events";
2
+ import { Subscriber } from "../../event_driven";
3
3
  import { DomainValidationError } from "../../exceptions";
4
4
  import { printerService } from "../../services/printer.service";
5
5
  export class PrintImageSubscriber extends Subscriber {
@@ -8,7 +8,7 @@ export class PrintImageSubscriber extends Subscriber {
8
8
  async process(event) {
9
9
  const printed = await printerService.printImageBase64(event.imageBase64);
10
10
  if (!printed) {
11
- throw new DomainValidationError("Print failed — printer not connected or timed out");
11
+ throw new DomainValidationError("No se pudo imprimir");
12
12
  }
13
13
  }
14
14
  }
@@ -1,5 +1,5 @@
1
- import { Subscriber } from "../../domain/event_sourcing";
2
1
  import { WebViewMessageReceivedEvent } from "../../domain/events";
2
+ import { Subscriber } from "../../event_driven";
3
3
  export declare class ProcessWebViewMessageSubscriber extends Subscriber {
4
4
  readonly requiresAuth = false;
5
5
  listen: (typeof WebViewMessageReceivedEvent)[];
@@ -1,5 +1,5 @@
1
- import { Subscriber } from "../../domain/event_sourcing";
2
1
  import { PrintImageRequestedEvent, WebViewMessageReceivedEvent, } from "../../domain/events";
2
+ import { Subscriber } from "../../event_driven";
3
3
  import { DomainValidationError } from "../../exceptions";
4
4
  import { EventBus } from "../../infrastructure/workers";
5
5
  import { webViewService } from "../../services/webview.service";
@@ -1,7 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "nativewind/jsx-runtime";
2
2
  import { DefaultTheme as NavDefaultTheme, NavigationContainer, } from "@react-navigation/native";
3
3
  import { createApp } from "../../framework/createApp";
4
- import { ToastHost } from "../../infrastructure/ui/ToastHost";
4
+ import { DeviceNotices } from "../../ui/activity";
5
5
  import { setBranding } from "@sincpro/mobile-ui";
6
6
  import { ToastProvider } from "@sincpro/mobile-ui/Feedback";
7
7
  import { setActiveTheme, themeToVars, useTheme, } from "@sincpro/mobile-ui/theme";
@@ -114,6 +114,6 @@ export function createAppShell(config) {
114
114
  const Splash = config.splashComponent;
115
115
  return Splash ? (_jsx(Splash, {})) : (_jsx(View, { style: { flex: 1, backgroundColor: activeTheme.bg.page } }));
116
116
  }
117
- return (_jsx(GestureHandlerRootView, { style: { flex: 1 }, children: _jsx(View, { className: "flex-1", style: themeStyle, children: _jsx(SafeAreaProvider, { initialMetrics: initialWindowMetrics, children: _jsx(SafeAreaView, { edges: ["top"], style: { flex: 1 }, children: _jsx(KeyboardProvider, { children: _jsx(CommonProvider, { darkTheme: config.darkTheme, lightTheme: config.theme, children: _jsxs(ToastProvider, { position: "top", children: [withProviders(providers, _jsx(DomainSwitcherProvider, { apps: apps, initialDomain: config.activeDomain, children: _jsx(NavigationContainer, { theme: navTheme, children: _jsx(ActiveDomainApp, {}) }) })), _jsx(ToastHost, {})] }) }) }) }) }) }) }));
117
+ return (_jsx(GestureHandlerRootView, { style: { flex: 1 }, children: _jsx(View, { className: "flex-1", style: themeStyle, children: _jsx(SafeAreaProvider, { initialMetrics: initialWindowMetrics, children: _jsx(SafeAreaView, { edges: ["top"], style: { flex: 1 }, children: _jsx(KeyboardProvider, { children: _jsx(CommonProvider, { darkTheme: config.darkTheme, lightTheme: config.theme, children: _jsxs(ToastProvider, { position: "top", children: [withProviders(providers, _jsx(DomainSwitcherProvider, { apps: apps, initialDomain: config.activeDomain, children: _jsx(NavigationContainer, { theme: navTheme, children: _jsx(ActiveDomainApp, {}) }) })), _jsx(DeviceNotices, {})] }) }) }) }) }) }) }));
118
118
  };
119
119
  }
@@ -4,22 +4,10 @@ export interface TimezoneLocale {
4
4
  timezone: string;
5
5
  locale: string;
6
6
  }
7
- interface Activity {
8
- id: string;
9
- label: string;
10
- type: "queue" | "cron";
11
- status: "running" | "failed";
12
- error?: string;
13
- startedAt: number;
14
- }
15
7
  interface ICommonContext {
16
8
  debugMode: boolean;
17
9
  debugModeLoaded: boolean;
18
10
  toggleDebugMode: () => Promise<void>;
19
- currentActivity?: Activity;
20
- lastError?: Activity;
21
- isProcessing: boolean;
22
- dismiss: () => void;
23
11
  hasGeoPermission: boolean;
24
12
  geoIsLoading: boolean;
25
13
  geoError: string | null;
@@ -36,6 +24,6 @@ interface CommonProviderProps {
36
24
  lightTheme?: ThemeTokens;
37
25
  darkTheme?: ThemeTokens;
38
26
  }
39
- export declare function CommonProvider({ children, lightTheme, darkTheme }: CommonProviderProps): import("react/jsx-runtime").JSX.Element;
27
+ export declare function CommonProvider({ children, lightTheme, darkTheme }: CommonProviderProps): import("react").JSX.Element;
40
28
  export declare function useCommon(): ICommonContext;
41
29
  export {};
@@ -1,33 +1,24 @@
1
1
  import { jsx as _jsx } from "nativewind/jsx-runtime";
2
2
  import { GeoAdapter } from "../../adapters/Geo.adapter";
3
3
  import { SettingsRepository } from "../../adapters/repositories/setting.repository";
4
- import { QueueEndEvent, QueueStartEvent } from "../../domain/events";
5
- import logger, { loggerUseCases } from "../../infrastructure/logger";
6
- import { UIEventBus } from "../../infrastructure/ui/UIEventBus";
4
+ import logger from "../../infrastructure/logger";
7
5
  import { DEFAULT_DARK_THEME, DEFAULT_THEME, setActiveTheme } from "@sincpro/mobile-ui/theme";
8
- import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState, } from "react";
6
+ import { createContext, useCallback, useContext, useEffect, useMemo, useState, } from "react";
9
7
  import { Appearance, AppState } from "react-native";
10
8
  const DEBUG_MODE_SETTING_KEY = "app.debug_mode";
11
9
  const TIMEZONE_SETTING_KEY = "app.timezone";
12
10
  const LOCALE_SETTING_KEY = "app.locale";
13
11
  const COLOR_SCHEME_SETTING_KEY = "app.color_scheme";
14
- const QUEUE_MIN_VISIBLE_MS = 1200;
15
12
  const CommonContext = createContext(null);
16
13
  export function CommonProvider({ children, lightTheme, darkTheme }) {
17
14
  const [debugMode, setDebugMode] = useState(false);
18
15
  const [debugModeLoaded, setDebugModeLoaded] = useState(false);
19
- const [currentActivity, setCurrentActivity] = useState(undefined);
20
- const [cronTasks, setCronTasks] = useState(new Map());
21
- const [lastError, setLastError] = useState(undefined);
22
- const [dismissed, setDismissed] = useState(false);
23
16
  const [hasGeoPermission, setHasGeoPermission] = useState(false);
24
17
  const [geoIsLoading, setGeoIsLoading] = useState(false);
25
18
  const [geoError, setGeoError] = useState(null);
26
19
  const [locale, setLocale] = useState(null);
27
20
  const [timezone, setTimezone] = useState(null);
28
21
  const [colorScheme, setColorSchemeState] = useState("system");
29
- const errorTimeoutRef = useRef(null);
30
- const queueClearTimeoutRef = useRef(null);
31
22
  useEffect(() => {
32
23
  async function loadDebugMode() {
33
24
  const value = await SettingsRepository.getSettingByName(DEBUG_MODE_SETTING_KEY);
@@ -41,14 +32,6 @@ export function CommonProvider({ children, lightTheme, darkTheme }) {
41
32
  await SettingsRepository.saveOneSetting(DEBUG_MODE_SETTING_KEY, newValue);
42
33
  setDebugMode(newValue);
43
34
  }, [debugMode]);
44
- const dismiss = useCallback(() => {
45
- setDismissed(true);
46
- setLastError(undefined);
47
- if (errorTimeoutRef.current) {
48
- clearTimeout(errorTimeoutRef.current);
49
- errorTimeoutRef.current = null;
50
- }
51
- }, []);
52
35
  const checkGeoPermission = useCallback(async () => {
53
36
  setGeoIsLoading(true);
54
37
  setGeoError(null);
@@ -104,10 +87,10 @@ export function CommonProvider({ children, lightTheme, darkTheme }) {
104
87
  applyTheme(scheme);
105
88
  }, [applyTheme]);
106
89
  useEffect(() => {
107
- checkGeoPermission();
90
+ Promise.resolve().then(() => checkGeoPermission());
108
91
  const sub = AppState.addEventListener("change", (state) => {
109
92
  if (state === "active")
110
- checkGeoPermission();
93
+ Promise.resolve().then(() => checkGeoPermission());
111
94
  });
112
95
  return () => sub.remove();
113
96
  }, [checkGeoPermission]);
@@ -144,118 +127,10 @@ export function CommonProvider({ children, lightTheme, darkTheme }) {
144
127
  }
145
128
  loadTimezoneAndLocale();
146
129
  }, []);
147
- useEffect(() => {
148
- loggerUseCases.debug("[CommonProvider] Setting up UIEventBus listeners");
149
- function handleQueueStart(payload) {
150
- if (!payload || typeof payload !== "object")
151
- return;
152
- const { event, label } = payload;
153
- if (!label)
154
- return;
155
- setCurrentActivity({
156
- id: event,
157
- label,
158
- type: "queue",
159
- status: "running",
160
- startedAt: Date.now(),
161
- });
162
- setDismissed(false);
163
- }
164
- function handleQueueEnd(payload) {
165
- if (!payload || typeof payload !== "object")
166
- return;
167
- const { event, success = true, error } = payload;
168
- setCurrentActivity((current) => {
169
- if (current?.id !== event)
170
- return current;
171
- if (!success) {
172
- const failedActivity = { ...current, status: "failed", error };
173
- setLastError(failedActivity);
174
- if (errorTimeoutRef.current)
175
- clearTimeout(errorTimeoutRef.current);
176
- errorTimeoutRef.current = setTimeout(() => {
177
- setLastError(undefined);
178
- errorTimeoutRef.current = null;
179
- }, 10000);
180
- return undefined;
181
- }
182
- // Éxito: mantener visible un mínimo para que la cola sea perceptible
183
- // aunque el evento se procese al instante.
184
- const remaining = QUEUE_MIN_VISIBLE_MS - (Date.now() - current.startedAt);
185
- if (remaining > 0) {
186
- if (queueClearTimeoutRef.current)
187
- clearTimeout(queueClearTimeoutRef.current);
188
- queueClearTimeoutRef.current = setTimeout(() => {
189
- setCurrentActivity((c) => (c?.id === event ? undefined : c));
190
- queueClearTimeoutRef.current = null;
191
- }, remaining);
192
- return current;
193
- }
194
- return undefined;
195
- });
196
- }
197
- function handleCronStart(payload) {
198
- if (!payload || typeof payload !== "object" || !("task" in payload))
199
- return;
200
- const { task, label } = payload;
201
- setCronTasks((prev) => {
202
- const next = new Map(prev);
203
- next.set(task, {
204
- id: task,
205
- label: label ?? task,
206
- type: "cron",
207
- status: "running",
208
- startedAt: Date.now(),
209
- });
210
- return next;
211
- });
212
- }
213
- function handleCronEnd(payload) {
214
- if (!payload || typeof payload !== "object" || !("task" in payload))
215
- return;
216
- const { task } = payload;
217
- setCronTasks((prev) => {
218
- const next = new Map(prev);
219
- next.delete(task);
220
- return next;
221
- });
222
- }
223
- const unsubscribers = [
224
- UIEventBus.on(QueueStartEvent.name, handleQueueStart),
225
- UIEventBus.on(QueueEndEvent.name, handleQueueEnd),
226
- UIEventBus.on("CRON_START", handleCronStart),
227
- UIEventBus.on("CRON_END", handleCronEnd),
228
- ];
229
- return () => {
230
- loggerUseCases.debug("[CommonProvider] Cleaning up UIEventBus listeners");
231
- unsubscribers.forEach((unsub) => unsub());
232
- if (errorTimeoutRef.current)
233
- clearTimeout(errorTimeoutRef.current);
234
- if (queueClearTimeoutRef.current)
235
- clearTimeout(queueClearTimeoutRef.current);
236
- };
237
- }, []);
238
- const displayActivity = useMemo(() => {
239
- if (currentActivity)
240
- return currentActivity;
241
- const firstCron = cronTasks.values().next().value;
242
- if (firstCron)
243
- return firstCron;
244
- return undefined;
245
- }, [currentActivity, cronTasks]);
246
- const isProcessing = useMemo(() => {
247
- if (dismissed)
248
- return false;
249
- return !!(currentActivity || cronTasks.size > 0 || lastError);
250
- }, [currentActivity, cronTasks, lastError, dismissed]);
251
130
  const value = useMemo(() => ({
252
131
  debugMode,
253
132
  debugModeLoaded,
254
133
  toggleDebugMode,
255
- currentActivity: displayActivity,
256
- lastError,
257
- isProcessing,
258
- dismiss,
259
134
  hasGeoPermission,
260
135
  geoIsLoading,
261
136
  geoError,
@@ -270,10 +145,6 @@ export function CommonProvider({ children, lightTheme, darkTheme }) {
270
145
  debugMode,
271
146
  debugModeLoaded,
272
147
  toggleDebugMode,
273
- displayActivity,
274
- lastError,
275
- isProcessing,
276
- dismiss,
277
148
  hasGeoPermission,
278
149
  geoIsLoading,
279
150
  geoError,
@@ -13,7 +13,7 @@ export declare function DomainSwitcherProvider(props: {
13
13
  apps: DomainApp[];
14
14
  initialDomain: string;
15
15
  children: ReactNode;
16
- }): import("react/jsx-runtime").JSX.Element;
16
+ }): import("react").JSX.Element;
17
17
  export declare function useDomainSwitcher(): DomainSwitcherValue;
18
- export declare function ActiveDomainApp(): import("react/jsx-runtime").JSX.Element | null;
18
+ export declare function ActiveDomainApp(): import("react").JSX.Element | null;
19
19
  export {};
@@ -0,0 +1 @@
1
+ export { Subscriber } from "../event_driven/subscriber";
@@ -0,0 +1 @@
1
+ export { Subscriber } from "../event_driven/subscriber";
@@ -1,4 +1,4 @@
1
- import { DomainEvent } from "../../domain/event_sourcing/domain_event";
1
+ import { DomainEvent } from "../domain/events/domain_event";
2
2
  export declare abstract class Subscriber {
3
3
  abstract listen: (typeof DomainEvent)[];
4
4
  readonly requiresAuth: boolean;
@@ -16,6 +16,27 @@ export declare class DomainBackendError extends DomainException {
16
16
  export declare class DomainAppError extends DomainException {
17
17
  constructor(message: string);
18
18
  }
19
+ export declare class StaleAggregate extends DomainException {
20
+ constructor(message: string);
21
+ }
22
+ export declare class ChecksFailed extends DomainValidationError {
23
+ readonly failures: {
24
+ rule: string;
25
+ message: string;
26
+ path: string[];
27
+ }[];
28
+ constructor(failures: {
29
+ rule: string;
30
+ message: string;
31
+ path: string[];
32
+ }[]);
33
+ }
34
+ export declare class RepeatableFailure extends DomainException {
35
+ constructor(message: string);
36
+ }
37
+ export declare class RejectedFailure extends DomainException {
38
+ constructor(message: string);
39
+ }
19
40
  export declare const ValidationError: (message: string) => never;
20
41
  export declare const UserError: (message: string) => never;
21
42
  export declare const BackendError: (message: string) => never;
@@ -34,6 +34,36 @@ export class DomainAppError extends DomainException {
34
34
  this.name = "AppError";
35
35
  }
36
36
  }
37
+ export class StaleAggregate extends DomainException {
38
+ constructor(message) {
39
+ super(message);
40
+ this.name = "StaleAggregate";
41
+ }
42
+ }
43
+ export class ChecksFailed extends DomainValidationError {
44
+ failures;
45
+ constructor(failures) {
46
+ super(failures
47
+ .map((failure) => failure.path.length > 0
48
+ ? `${failure.path.join(".")}: ${failure.message}`
49
+ : failure.message)
50
+ .join("; "));
51
+ this.failures = failures;
52
+ this.name = "ChecksFailed";
53
+ }
54
+ }
55
+ export class RepeatableFailure extends DomainException {
56
+ constructor(message) {
57
+ super(message);
58
+ this.name = "RepeatableFailure";
59
+ }
60
+ }
61
+ export class RejectedFailure extends DomainException {
62
+ constructor(message) {
63
+ super(message);
64
+ this.name = "RejectedFailure";
65
+ }
66
+ }
37
67
  export const ValidationError = (message) => {
38
68
  // setTimeout(() => {
39
69
  // throw new DomainValidationError(message);
@@ -1,5 +1,5 @@
1
1
  import type { IMigration } from "../domain/database";
2
- import type { Subscriber } from "../domain/event_sourcing";
2
+ import type { Subscriber } from "../event_driven";
3
3
  import type { CronWorker } from "../infrastructure/workers";
4
4
  import { DomainModule } from "./domain_module";
5
5
  export declare class BaseModule extends DomainModule {
@@ -10,10 +10,10 @@ export interface AppConfig {
10
10
  */
11
11
  telemetry?: TelemetryConfig;
12
12
  /**
13
- * Override display options for any cron by taskName.
14
- * Useful for showing/hiding toasts on internal crons (CHECK_NETWORK, TELEMETRY_FLUSH, etc.).
13
+ * Override options for any cron by taskName.
14
+ * `ui` marks the cron for the activity toast. Silence is the default.
15
15
  * @example
16
- * crons: { CHECK_NETWORK: { showToast: true, label: "Verificando conexión" } }
16
+ * crons: { CHECK_NETWORK: { ui: true, label: "Verificando conexión" } }
17
17
  */
18
18
  crons?: Record<string, Partial<CronWorkerOpts>>;
19
19
  }
@@ -1,5 +1,5 @@
1
1
  import type { IMigration } from "../domain/database";
2
- import type { Subscriber } from "../domain/event_sourcing";
2
+ import type { Subscriber } from "../event_driven";
3
3
  import type { CronWorker } from "../infrastructure/workers";
4
4
  export declare abstract class DomainModule {
5
5
  abstract readonly key: string;
@@ -0,0 +1,26 @@
1
+ /**
2
+ * One operation. What the context injects (a repository, an adapter) is `deps`,
3
+ * typed by the subclass.
4
+ *
5
+ * `new` returns a proxy: every public method of the subclass runs inside a span
6
+ * named `ClassName.method`. A name that starts with `_` does not. The author
7
+ * does not open a span. If tracing is not initialized, or the exporter fails,
8
+ * the method still runs.
9
+ *
10
+ * A subclass constructor calls `super(deps)` and does not return another object.
11
+ */
12
+ export declare class Feature<Deps extends object = Record<string, never>> {
13
+ protected readonly deps: Deps;
14
+ constructor(deps?: Deps);
15
+ }
16
+ /**
17
+ * Composes the `Feature`s of its own context. `features` is that set, and only
18
+ * that set: another context's feature is not on the type.
19
+ *
20
+ * `run` is the parent span. Each `this.features.*` call in that turn is a child
21
+ * of the same trace. It does not call another `ApplicationService`.
22
+ */
23
+ export declare class ApplicationService<TFeatures extends Record<string, Feature<Record<string, unknown>>>, Deps extends object = Record<string, never>> extends Feature<Deps> {
24
+ protected readonly features: TFeatures;
25
+ constructor(features: TFeatures, deps?: Deps);
26
+ }
@@ -0,0 +1,36 @@
1
+ import { interceptInstance } from "../infrastructure/interceptor/intercept";
2
+ import { tracingHooks } from "../infrastructure/telemetry/tracing/tracing_hooks";
3
+ /**
4
+ * One operation. What the context injects (a repository, an adapter) is `deps`,
5
+ * typed by the subclass.
6
+ *
7
+ * `new` returns a proxy: every public method of the subclass runs inside a span
8
+ * named `ClassName.method`. A name that starts with `_` does not. The author
9
+ * does not open a span. If tracing is not initialized, or the exporter fails,
10
+ * the method still runs.
11
+ *
12
+ * A subclass constructor calls `super(deps)` and does not return another object.
13
+ */
14
+ export class Feature {
15
+ deps;
16
+ constructor(deps) {
17
+ this.deps = deps ?? {};
18
+ return interceptInstance(this, tracingHooks(new.target.name), {
19
+ skip: (methodName) => methodName.startsWith("_"),
20
+ });
21
+ }
22
+ }
23
+ /**
24
+ * Composes the `Feature`s of its own context. `features` is that set, and only
25
+ * that set: another context's feature is not on the type.
26
+ *
27
+ * `run` is the parent span. Each `this.features.*` call in that turn is a child
28
+ * of the same trace. It does not call another `ApplicationService`.
29
+ */
30
+ export class ApplicationService extends Feature {
31
+ features;
32
+ constructor(features, deps) {
33
+ super(deps);
34
+ this.features = features;
35
+ }
36
+ }
@@ -1,5 +1,5 @@
1
1
  import type { IMigration } from "../domain/database";
2
- import type { Subscriber } from "../domain/event_sourcing";
2
+ import type { Subscriber } from "../event_driven";
3
3
  import type { CronWorker, CronWorkerOpts } from "../infrastructure/workers";
4
4
  import type { DomainModule } from "./domain_module";
5
5
  export declare class Kernel {
@@ -1,6 +1,8 @@
1
+ import { applyMigrationStep, migrationsNewerThanApp, pendingMigrations, resetPlan, } from "../domain/database/migration_plan";
1
2
  import { repos } from "../entrypoints/db/repositories";
2
3
  import { DBCursor } from "../infrastructure/database";
3
4
  import { initializeRepositoryFacade } from "../infrastructure/database/mapped";
5
+ import { appliedMigrationNames, forgetMigrations, markMigrationApplied, } from "../infrastructure/database/schema";
4
6
  import logger, { loggerRepositories } from "../infrastructure/logger";
5
7
  export class Kernel {
6
8
  modules;
@@ -45,9 +47,16 @@ export class Kernel {
45
47
  }
46
48
  }
47
49
  async runMigrations() {
48
- for (const { name, migrationFn } of this.migrations()) {
49
- logger.info(`Running migration: ${name}`);
50
- await migrationFn();
50
+ const applied = await appliedMigrationNames();
51
+ const migrations = this.migrations();
52
+ const newer = migrationsNewerThanApp(applied, migrations.map((migration) => migration.name));
53
+ if (newer.length > 0) {
54
+ throw new Error(`the database is newer than this app: ${newer.join(", ")}`);
55
+ }
56
+ for (const migration of pendingMigrations(migrations, applied)) {
57
+ logger.info(`Running migration: ${migration.name}`);
58
+ await applyMigrationStep(migration, (work) => DBCursor.transaction(work), markMigrationApplied);
59
+ applied.add(migration.name);
51
60
  }
52
61
  }
53
62
  async bootstrap() {
@@ -57,12 +66,12 @@ export class Kernel {
57
66
  }
58
67
  async restartDatabase() {
59
68
  loggerRepositories.warn("Restarting database");
60
- const persisted = this.persistedTables();
61
- const tablesToDrop = this.migrations().filter((migration) => !persisted.includes(migration.name));
62
- for (const { name } of tablesToDrop) {
63
- loggerRepositories.info(`Dropping table: ${name}`);
64
- await DBCursor.execAsync(`DROP TABLE IF EXISTS ${name}`);
69
+ const plan = resetPlan(this.migrations(), this.persistedTables());
70
+ for (const table of plan.drop) {
71
+ loggerRepositories.info(`Dropping table: ${table}`);
72
+ await DBCursor.execAsync(`DROP TABLE IF EXISTS ${table}`);
65
73
  }
74
+ await forgetMigrations(plan.forget);
66
75
  await this.runMigrations();
67
76
  }
68
77
  }
package/dist/index.d.ts CHANGED
@@ -11,6 +11,7 @@ export { BaseModule, baseModule } from "./framework/base_module";
11
11
  export type { AppConfig } from "./framework/createApp";
12
12
  export { createApp } from "./framework/createApp";
13
13
  export { DomainModule } from "./framework/domain_module";
14
+ export { ApplicationService, Feature } from "./framework/feature";
14
15
  export { Kernel } from "./framework/kernel";
15
16
  export { orchestrator } from "./framework/orchestrator";
16
17
  export { installGlobalErrorHandler } from "./infrastructure/ui/errorHandler";
package/dist/index.js CHANGED
@@ -6,6 +6,7 @@ export { createTheme } from "./entrypoints/ui/theme";
6
6
  export { BaseModule, baseModule } from "./framework/base_module";
7
7
  export { createApp } from "./framework/createApp";
8
8
  export { DomainModule } from "./framework/domain_module";
9
+ export { ApplicationService, Feature } from "./framework/feature";
9
10
  export { Kernel } from "./framework/kernel";
10
11
  export { orchestrator } from "./framework/orchestrator";
11
12
  export { installGlobalErrorHandler } from "./infrastructure/ui/errorHandler";