@sincpro/mobile 0.4.4 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/dist/adapters/JsonSerializer.adapter.d.ts +1 -1
- package/dist/adapters/JsonSerializer.adapter.js +2 -2
- package/dist/adapters/repositories/database_table.repository.d.ts +3 -2
- package/dist/adapters/repositories/database_table.repository.js +1 -1
- package/dist/adapters/repositories/document.repository.d.ts +81 -0
- package/dist/adapters/repositories/document.repository.js +653 -0
- package/dist/adapters/repositories/domain_event.repository.d.ts +17 -17
- package/dist/adapters/repositories/domain_event.repository.js +25 -31
- package/dist/adapters/repositories/domain_event_dead_letter.repository.d.ts +10 -10
- package/dist/adapters/repositories/domain_event_dead_letter.repository.js +14 -13
- package/dist/adapters/repositories/event_row.d.ts +13 -0
- package/dist/adapters/repositories/event_row.js +22 -0
- package/dist/adapters/repositories/sqlite_document_store.d.ts +33 -0
- package/dist/adapters/repositories/sqlite_document_store.js +201 -0
- package/dist/domain/connectivity/events.d.ts +5 -5
- package/dist/domain/connectivity/events.js +3 -3
- package/dist/domain/database/criteria.d.ts +19 -0
- package/dist/domain/database/criteria.js +36 -0
- package/dist/domain/database/criteria_clock.d.ts +8 -0
- package/dist/domain/database/criteria_clock.js +305 -0
- package/dist/domain/database/criteria_sql.d.ts +61 -0
- package/dist/domain/database/criteria_sql.js +476 -0
- package/dist/domain/database/database.d.ts +1 -0
- package/dist/domain/database/index.d.ts +3 -1
- package/dist/domain/database/index.js +3 -1
- package/dist/domain/database/migration_plan.d.ts +14 -0
- package/dist/domain/database/migration_plan.js +44 -0
- package/dist/domain/entity/change_tracking.d.ts +21 -0
- package/dist/domain/entity/change_tracking.js +71 -0
- package/dist/domain/entity/checks.d.ts +8 -0
- package/dist/domain/entity/checks.js +82 -0
- package/dist/domain/entity/entity.d.ts +39 -32
- package/dist/domain/entity/entity.js +94 -105
- package/dist/domain/entity/entity_collection.d.ts +15 -30
- package/dist/domain/entity/entity_collection.js +30 -121
- package/dist/domain/entity/index.d.ts +5 -0
- package/dist/domain/entity/index.js +5 -0
- package/dist/domain/entity/reconcile.d.ts +7 -0
- package/dist/domain/entity/reconcile.js +12 -0
- package/dist/domain/entity/relations.d.ts +27 -0
- package/dist/domain/entity/relations.js +69 -0
- package/dist/domain/entity/remote_sync.d.ts +4 -0
- package/dist/domain/entity/remote_sync.js +19 -0
- package/dist/domain/entity/values.d.ts +6 -0
- package/dist/domain/entity/values.js +13 -0
- package/dist/domain/events/catalog.d.ts +29 -0
- package/dist/domain/{events.js → events/catalog.js} +7 -11
- package/dist/domain/events/chain.d.ts +5 -0
- package/dist/domain/events/chain.js +6 -0
- package/dist/domain/{event_sourcing → events}/domain_event.d.ts +20 -22
- package/dist/domain/events/domain_event.js +227 -0
- package/dist/domain/events/index.d.ts +8 -0
- package/dist/domain/events/index.js +8 -0
- package/dist/domain/events/integration_event.d.ts +103 -0
- package/dist/domain/events/integration_event.js +72 -0
- package/dist/domain/events/label.d.ts +2 -0
- package/dist/domain/events/label.js +26 -0
- package/dist/domain/index.d.ts +0 -1
- package/dist/domain/index.js +0 -1
- package/dist/domain/print/events.d.ts +8 -4
- package/dist/domain/print/events.js +9 -4
- package/dist/domain/repositories/document_store.d.ts +33 -0
- package/dist/domain/repositories/document_store.js +5 -0
- package/dist/domain/repositories/hooks.d.ts +23 -0
- package/dist/domain/repositories/hooks.js +32 -0
- package/dist/domain/repositories/index.d.ts +4 -0
- package/dist/domain/repositories/index.js +4 -0
- package/dist/domain/{database → repositories}/repository.d.ts +9 -3
- package/dist/domain/settings.d.ts +4 -1
- package/dist/domain/settings.js +3 -0
- package/dist/domain/webview/events.d.ts +2 -2
- package/dist/domain/webview/events.js +2 -2
- package/dist/entrypoints/db/migrations.js +10 -10
- package/dist/entrypoints/queue/QueueProcessor.d.ts +1 -1
- package/dist/entrypoints/queue/activateDomain.subscriber.d.ts +2 -2
- package/dist/entrypoints/queue/activateDomain.subscriber.js +2 -2
- package/dist/entrypoints/queue/newAppSettings.handler.d.ts +2 -2
- package/dist/entrypoints/queue/newAppSettings.handler.js +1 -1
- package/dist/entrypoints/queue/printImage.subscriber.d.ts +1 -1
- package/dist/entrypoints/queue/printImage.subscriber.js +2 -2
- package/dist/entrypoints/queue/processWebViewMessage.subscriber.d.ts +1 -1
- package/dist/entrypoints/queue/processWebViewMessage.subscriber.js +1 -1
- package/dist/entrypoints/ui/AppShell.js +2 -2
- package/dist/entrypoints/ui/common_provider.d.ts +0 -12
- package/dist/entrypoints/ui/common_provider.js +2 -131
- package/dist/event_driven/index.d.ts +1 -0
- package/dist/event_driven/index.js +1 -0
- package/dist/{domain/event_sourcing/event_handler.d.ts → event_driven/subscriber.d.ts} +1 -1
- package/dist/exceptions.d.ts +21 -0
- package/dist/exceptions.js +30 -0
- package/dist/framework/base_module.d.ts +1 -1
- package/dist/framework/createApp.d.ts +3 -3
- package/dist/framework/domain_module.d.ts +1 -1
- package/dist/framework/kernel.d.ts +1 -1
- package/dist/framework/kernel.js +17 -8
- package/dist/infrastructure/database/connector.d.ts +2 -0
- package/dist/infrastructure/database/connector.js +22 -0
- package/dist/infrastructure/database/index.d.ts +1 -0
- package/dist/infrastructure/database/index.js +1 -0
- package/dist/infrastructure/database/schema.d.ts +9 -0
- package/dist/infrastructure/database/schema.js +61 -0
- package/dist/infrastructure/database/utils.d.ts +2 -0
- package/dist/infrastructure/database/utils.js +12 -4
- package/dist/infrastructure/event_chain.d.ts +6 -0
- package/dist/infrastructure/event_chain.js +25 -0
- package/dist/infrastructure/telemetry/tracing/tracing_hooks.js +8 -5
- package/dist/infrastructure/ui/UIEventBus.d.ts +3 -1
- package/dist/infrastructure/ui/UIEventBus.js +8 -1
- package/dist/infrastructure/ui/activity.d.ts +37 -0
- package/dist/infrastructure/ui/activity.js +84 -0
- package/dist/infrastructure/workers/CronWorker.d.ts +6 -4
- package/dist/infrastructure/workers/CronWorker.js +24 -18
- package/dist/infrastructure/workers/EventBus.d.ts +9 -5
- package/dist/infrastructure/workers/EventBus.js +68 -33
- package/dist/services/bluetooth.service.js +16 -14
- package/dist/services/dead_letter_queue.service.d.ts +7 -7
- package/dist/services/dead_letter_queue.service.js +0 -2
- package/dist/services/event.service.d.ts +3 -3
- package/dist/services/event.service.js +1 -1
- package/dist/services/network.service.d.ts +1 -1
- package/dist/services/network.service.js +17 -15
- package/dist/services/printer.service.d.ts +1 -1
- package/dist/services/printer.service.js +50 -44
- package/dist/tools/utils/date.js +4 -3
- package/dist/tools/utils/monetary.d.ts +6 -3
- package/dist/tools/utils/monetary.js +33 -21
- package/dist/tools/utils/serializer.d.ts +1 -1
- package/dist/tools/utils/serializer.js +32 -35
- package/dist/ui/activity/DeviceNotices.d.ts +1 -0
- package/dist/ui/activity/DeviceNotices.js +29 -0
- package/dist/ui/activity/ProcessToast.d.ts +2 -0
- package/dist/ui/activity/ProcessToast.js +71 -0
- package/dist/ui/activity/index.d.ts +4 -0
- package/dist/ui/activity/index.js +4 -0
- package/dist/ui/activity/useActivity.d.ts +9 -0
- package/dist/ui/activity/useActivity.js +48 -0
- package/dist/ui/components/molecules/EventTimelineItem.d.ts +2 -2
- package/dist/ui/components/molecules/EventTimelineItem.js +1 -1
- package/dist/ui/components/molecules/index.d.ts +1 -2
- package/dist/ui/components/molecules/index.js +1 -2
- package/dist/ui/components/organisms/DeadLetterQueueRow.d.ts +3 -3
- package/dist/ui/components/organisms/EventRow.d.ts +3 -3
- package/dist/ui/components/organisms/EventRow.js +1 -1
- package/dist/ui/screens/dead_letter_queue/dead_letter_queue.context.d.ts +5 -5
- package/dist/ui/screens/events/events.context.d.ts +4 -4
- package/package.json +13 -8
- package/dist/domain/event_sourcing/domain_event.js +0 -164
- package/dist/domain/event_sourcing/event.d.ts +0 -25
- package/dist/domain/event_sourcing/event.js +0 -25
- package/dist/domain/event_sourcing/index.d.ts +0 -2
- package/dist/domain/event_sourcing/index.js +0 -2
- package/dist/domain/events.d.ts +0 -33
- package/dist/infrastructure/ui/ToastHost.d.ts +0 -6
- package/dist/infrastructure/ui/ToastHost.js +0 -28
- package/dist/infrastructure/ui/events.d.ts +0 -1
- package/dist/infrastructure/ui/events.js +0 -1
- package/dist/ui/components/molecules/ProcessToast.d.ts +0 -8
- package/dist/ui/components/molecules/ProcessToast.js +0 -52
- /package/dist/domain/{repositories.d.ts → repositories/catalog.d.ts} +0 -0
- /package/dist/domain/{repositories.js → repositories/catalog.js} +0 -0
- /package/dist/domain/{database → repositories}/repository.js +0 -0
- /package/dist/{domain/event_sourcing/event_handler.js → event_driven/subscriber.js} +0 -0
- /package/dist/ui/{components/molecules → activity}/ProcessToastProvider.d.ts +0 -0
- /package/dist/ui/{components/molecules → activity}/ProcessToastProvider.js +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export declare class WebViewMessageReceivedEvent extends
|
|
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 {
|
|
2
|
-
export class WebViewMessageReceivedEvent extends
|
|
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
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
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,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
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 {
|
|
2
|
-
import {
|
|
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,
|
|
2
|
-
import {
|
|
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("
|
|
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 {
|
|
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(
|
|
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;
|
|
@@ -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
|
|
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,
|
|
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);
|
|
@@ -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,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Subscriber } from "../event_driven/subscriber";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Subscriber } from "../event_driven/subscriber";
|
package/dist/exceptions.d.ts
CHANGED
|
@@ -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;
|
package/dist/exceptions.js
CHANGED
|
@@ -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 "../
|
|
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
|
|
14
|
-
*
|
|
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: {
|
|
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 "../
|
|
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;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { IMigration } from "../domain/database";
|
|
2
|
-
import type { Subscriber } from "../
|
|
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 {
|
package/dist/framework/kernel.js
CHANGED
|
@@ -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
|
-
|
|
49
|
-
|
|
50
|
-
|
|
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
|
|
61
|
-
const
|
|
62
|
-
|
|
63
|
-
|
|
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
|
}
|
|
@@ -3,6 +3,8 @@ export declare const DB_NAME = "distribution.db";
|
|
|
3
3
|
export declare function getDatabase(): Promise<SQLiteDatabase>;
|
|
4
4
|
export declare function getDatabaseSync(): SQLiteDatabase;
|
|
5
5
|
export declare const DBCursor: {
|
|
6
|
+
inTransaction(): boolean;
|
|
7
|
+
transaction<T>(work: () => Promise<T>): Promise<T>;
|
|
6
8
|
mutateDatabase(query: string, ...params: SQLiteVariadicBindParams): Promise<SQLiteRunResult>;
|
|
7
9
|
getFirstAsync<T>(query: string, ...params: SQLiteVariadicBindParams): Promise<T | null>;
|
|
8
10
|
getAllAsync<T>(query: string, ...params: SQLiteVariadicBindParams): Promise<T[]>;
|
|
@@ -3,6 +3,7 @@ import { Mutex } from "async-mutex";
|
|
|
3
3
|
import { openDatabaseAsync, openDatabaseSync, } from "expo-sqlite";
|
|
4
4
|
export const DB_NAME = "distribution.db";
|
|
5
5
|
let dbInstance = null;
|
|
6
|
+
let currentTx = null;
|
|
6
7
|
const dbLock = new Mutex();
|
|
7
8
|
// Telemetry/queue tables are excluded from query logging: logging their
|
|
8
9
|
// mutations would feed the log pipeline its own writes — and a failing
|
|
@@ -45,12 +46,33 @@ export function getDatabaseSync() {
|
|
|
45
46
|
return dbInstance;
|
|
46
47
|
}
|
|
47
48
|
async function withDB(fn) {
|
|
49
|
+
if (currentTx)
|
|
50
|
+
return fn(currentTx);
|
|
48
51
|
return dbLock.runExclusive(async () => fn(await getDatabase()));
|
|
49
52
|
}
|
|
50
53
|
function withDBSync(fn) {
|
|
51
54
|
return fn(getDatabaseSync());
|
|
52
55
|
}
|
|
53
56
|
export const DBCursor = {
|
|
57
|
+
inTransaction() {
|
|
58
|
+
return currentTx !== null;
|
|
59
|
+
},
|
|
60
|
+
async transaction(work) {
|
|
61
|
+
return dbLock.runExclusive(async () => {
|
|
62
|
+
const db = await getDatabase();
|
|
63
|
+
let result;
|
|
64
|
+
await db.withTransactionAsync(async () => {
|
|
65
|
+
currentTx = db;
|
|
66
|
+
try {
|
|
67
|
+
result = await work();
|
|
68
|
+
}
|
|
69
|
+
finally {
|
|
70
|
+
currentTx = null;
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
return result;
|
|
74
|
+
});
|
|
75
|
+
},
|
|
54
76
|
async mutateDatabase(query, ...params) {
|
|
55
77
|
const safeQuery = `${query.trim()};`;
|
|
56
78
|
return withDB(async (db) => {
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare function assertSqlIdentifier(name: string): void;
|
|
2
|
+
export declare function addColumnStatement(table: string, column: string, definition: string): string;
|
|
3
|
+
export declare function tableColumns(table: string): Promise<string[]>;
|
|
4
|
+
export declare function tableColumnsSync(table: string): string[];
|
|
5
|
+
export declare function addColumnIfMissing(table: string, column: string, definition: string): Promise<void>;
|
|
6
|
+
export declare function addColumnIfMissingSync(table: string, column: string, definition: string): void;
|
|
7
|
+
export declare function appliedMigrationNames(): Promise<Set<string>>;
|
|
8
|
+
export declare function markMigrationApplied(name: string): Promise<void>;
|
|
9
|
+
export declare function forgetMigrations(names: readonly string[]): Promise<void>;
|