@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.
- package/README.md +74 -0
- package/dist/adapters/Bluetooth.adapter.d.ts +14 -0
- package/dist/adapters/Bluetooth.adapter.js +100 -0
- package/dist/adapters/Geo.adapter.d.ts +8 -0
- package/dist/adapters/Geo.adapter.js +30 -0
- package/dist/adapters/JsonSerializer.adapter.d.ts +28 -0
- package/dist/adapters/JsonSerializer.adapter.js +47 -0
- package/dist/adapters/Network.adapter.d.ts +4 -0
- package/dist/adapters/Network.adapter.js +13 -0
- package/dist/adapters/ReceiptExporter.adapter.d.ts +19 -0
- package/dist/adapters/ReceiptExporter.adapter.js +142 -0
- package/dist/adapters/repositories/database_table.repository.d.ts +13 -0
- package/dist/adapters/repositories/database_table.repository.js +29 -0
- package/dist/adapters/repositories/domain_event.repository.d.ts +32 -0
- package/dist/adapters/repositories/domain_event.repository.js +147 -0
- package/dist/adapters/repositories/domain_event_dead_letter.repository.d.ts +23 -0
- package/dist/adapters/repositories/domain_event_dead_letter.repository.js +81 -0
- package/dist/adapters/repositories/setting.repository.d.ts +10 -0
- package/dist/adapters/repositories/setting.repository.js +21 -0
- package/dist/adapters/webview.adapter.d.ts +10 -0
- package/dist/adapters/webview.adapter.js +166 -0
- package/dist/domain/connectivity/bluetooth.d.ts +19 -0
- package/dist/domain/connectivity/bluetooth.js +1 -0
- package/dist/domain/connectivity/events.d.ts +17 -0
- package/dist/domain/connectivity/events.js +17 -0
- package/dist/domain/connectivity/geo.d.ts +4 -0
- package/dist/domain/connectivity/geo.js +1 -0
- package/dist/domain/connectivity/index.d.ts +3 -0
- package/dist/domain/connectivity/index.js +3 -0
- package/dist/domain/connectivity/network.d.ts +7 -0
- package/dist/domain/connectivity/network.js +1 -0
- package/dist/domain/database/database.d.ts +16 -0
- package/dist/domain/database/database.js +1 -0
- package/dist/domain/database/index.d.ts +2 -0
- package/dist/domain/database/index.js +2 -0
- package/dist/domain/database/repository.d.ts +19 -0
- package/dist/domain/database/repository.js +1 -0
- package/dist/domain/entity/entity.d.ts +109 -0
- package/dist/domain/entity/entity.js +246 -0
- package/dist/domain/entity/entity_collection.d.ts +396 -0
- package/dist/domain/entity/entity_collection.js +824 -0
- package/dist/domain/entity/index.d.ts +3 -0
- package/dist/domain/entity/index.js +3 -0
- package/dist/domain/entity/value_object.d.ts +12 -0
- package/dist/domain/entity/value_object.js +39 -0
- package/dist/domain/event_sourcing/domain_event.d.ts +58 -0
- package/dist/domain/event_sourcing/domain_event.js +164 -0
- package/dist/domain/event_sourcing/event.d.ts +25 -0
- package/dist/domain/event_sourcing/event.js +25 -0
- package/dist/domain/event_sourcing/event_handler.d.ts +7 -0
- package/dist/domain/event_sourcing/event_handler.js +13 -0
- package/dist/domain/event_sourcing/index.d.ts +2 -0
- package/dist/domain/event_sourcing/index.js +2 -0
- package/dist/domain/events.d.ts +33 -0
- package/dist/domain/events.js +32 -0
- package/dist/domain/icon.d.ts +1 -0
- package/dist/domain/icon.js +1 -0
- package/dist/domain/index.d.ts +9 -0
- package/dist/domain/index.js +9 -0
- package/dist/domain/print/driver_registry.d.ts +4 -0
- package/dist/domain/print/driver_registry.js +29 -0
- package/dist/domain/print/events.d.ts +13 -0
- package/dist/domain/print/events.js +13 -0
- package/dist/domain/print/index.d.ts +2 -0
- package/dist/domain/print/index.js +1 -0
- package/dist/domain/print/printer.d.ts +35 -0
- package/dist/domain/print/printer.js +1 -0
- package/dist/domain/receipt.d.ts +31 -0
- package/dist/domain/receipt.js +1 -0
- package/dist/domain/repositories.d.ts +6 -0
- package/dist/domain/repositories.js +7 -0
- package/dist/domain/settings.d.ts +7 -0
- package/dist/domain/settings.js +1 -0
- package/dist/domain/webview/events.d.ts +11 -0
- package/dist/domain/webview/events.js +11 -0
- package/dist/domain/webview/index.d.ts +1 -0
- package/dist/domain/webview/index.js +1 -0
- package/dist/domain/webview/webview.d.ts +57 -0
- package/dist/domain/webview/webview.js +9 -0
- package/dist/entrypoints/cron/Cron.d.ts +13 -0
- package/dist/entrypoints/cron/Cron.js +57 -0
- package/dist/entrypoints/cron/checkNetworkStatus.cron.d.ts +3 -0
- package/dist/entrypoints/cron/checkNetworkStatus.cron.js +10 -0
- package/dist/entrypoints/db/index.d.ts +2 -0
- package/dist/entrypoints/db/index.js +2 -0
- package/dist/entrypoints/db/migrations.d.ts +10 -0
- package/dist/entrypoints/db/migrations.js +115 -0
- package/dist/entrypoints/db/repositories.d.ts +8 -0
- package/dist/entrypoints/db/repositories.js +34 -0
- package/dist/entrypoints/queue/QueueProcessor.d.ts +12 -0
- package/dist/entrypoints/queue/QueueProcessor.js +75 -0
- package/dist/entrypoints/queue/activateDomain.subscriber.d.ts +7 -0
- package/dist/entrypoints/queue/activateDomain.subscriber.js +15 -0
- package/dist/entrypoints/queue/newAppSettings.handler.d.ts +7 -0
- package/dist/entrypoints/queue/newAppSettings.handler.js +17 -0
- package/dist/entrypoints/queue/printImage.subscriber.d.ts +7 -0
- package/dist/entrypoints/queue/printImage.subscriber.js +14 -0
- package/dist/entrypoints/queue/processWebViewMessage.subscriber.d.ts +7 -0
- package/dist/entrypoints/queue/processWebViewMessage.subscriber.js +23 -0
- package/dist/entrypoints/ui/AppShell.d.ts +15 -0
- package/dist/entrypoints/ui/AppShell.js +58 -0
- package/dist/entrypoints/ui/common_provider.d.ts +35 -0
- package/dist/entrypoints/ui/common_provider.js +244 -0
- package/dist/entrypoints/ui/domain_switcher.d.ts +19 -0
- package/dist/entrypoints/ui/domain_switcher.js +22 -0
- package/dist/entrypoints/ui/theme.d.ts +15 -0
- package/dist/entrypoints/ui/theme.js +16 -0
- package/dist/exceptions.d.ts +22 -0
- package/dist/exceptions.js +60 -0
- package/dist/framework/base_module.d.ts +14 -0
- package/dist/framework/base_module.js +40 -0
- package/dist/framework/createApp.d.ts +6 -0
- package/dist/framework/createApp.js +9 -0
- package/dist/framework/domain_module.d.ts +13 -0
- package/dist/framework/domain_module.js +18 -0
- package/dist/framework/kernel.d.ts +18 -0
- package/dist/framework/kernel.js +60 -0
- package/dist/framework/orchestrator.d.ts +29 -0
- package/dist/framework/orchestrator.js +118 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.js +11 -0
- package/dist/infrastructure/database/connector.d.ts +13 -0
- package/dist/infrastructure/database/connector.js +165 -0
- package/dist/infrastructure/database/index.d.ts +2 -0
- package/dist/infrastructure/database/index.js +2 -0
- package/dist/infrastructure/database/mapped.d.ts +128 -0
- package/dist/infrastructure/database/mapped.js +174 -0
- package/dist/infrastructure/database/utils.d.ts +10 -0
- package/dist/infrastructure/database/utils.js +35 -0
- package/dist/infrastructure/logger.d.ts +45 -0
- package/dist/infrastructure/logger.js +125 -0
- package/dist/infrastructure/ui/ToastHost.d.ts +1 -0
- package/dist/infrastructure/ui/ToastHost.js +19 -0
- package/dist/infrastructure/ui/UIEventBus.d.ts +12 -0
- package/dist/infrastructure/ui/UIEventBus.js +65 -0
- package/dist/infrastructure/ui/errorHandler.d.ts +1 -0
- package/dist/infrastructure/ui/errorHandler.js +20 -0
- package/dist/infrastructure/ui/events.d.ts +1 -0
- package/dist/infrastructure/ui/events.js +1 -0
- package/dist/infrastructure/workers/CronWorker.d.ts +42 -0
- package/dist/infrastructure/workers/CronWorker.js +143 -0
- package/dist/infrastructure/workers/EventBus.d.ts +67 -0
- package/dist/infrastructure/workers/EventBus.js +279 -0
- package/dist/infrastructure/workers/index.d.ts +2 -0
- package/dist/infrastructure/workers/index.js +2 -0
- package/dist/services/bluetooth.service.d.ts +14 -0
- package/dist/services/bluetooth.service.js +72 -0
- package/dist/services/database_table.service.d.ts +8 -0
- package/dist/services/database_table.service.js +19 -0
- package/dist/services/dead_letter_queue.service.d.ts +38 -0
- package/dist/services/dead_letter_queue.service.js +99 -0
- package/dist/services/event.service.d.ts +7 -0
- package/dist/services/event.service.js +24 -0
- package/dist/services/network.service.d.ts +7 -0
- package/dist/services/network.service.js +43 -0
- package/dist/services/printer.service.d.ts +25 -0
- package/dist/services/printer.service.js +220 -0
- package/dist/services/webview.service.d.ts +17 -0
- package/dist/services/webview.service.js +59 -0
- package/dist/tools/utils/Initials.d.ts +1 -0
- package/dist/tools/utils/Initials.js +12 -0
- package/dist/tools/utils/collections.d.ts +120 -0
- package/dist/tools/utils/collections.js +158 -0
- package/dist/tools/utils/date.d.ts +70 -0
- package/dist/tools/utils/date.js +126 -0
- package/dist/tools/utils/maps.d.ts +4 -0
- package/dist/tools/utils/maps.js +20 -0
- package/dist/tools/utils/monetary.d.ts +3 -0
- package/dist/tools/utils/monetary.js +31 -0
- package/dist/tools/utils/quantity.d.ts +11 -0
- package/dist/tools/utils/quantity.js +44 -0
- package/dist/tools/utils/searchTools.d.ts +39 -0
- package/dist/tools/utils/searchTools.js +56 -0
- package/dist/tools/utils/serializer.d.ts +2 -0
- package/dist/tools/utils/serializer.js +44 -0
- package/dist/ui/components/atoms/DebugBanner.d.ts +2 -0
- package/dist/ui/components/atoms/DebugBanner.js +15 -0
- package/dist/ui/components/atoms/index.d.ts +1 -0
- package/dist/ui/components/atoms/index.js +1 -0
- package/dist/ui/components/molecules/BluetoothDeviceSelectorModal.d.ts +8 -0
- package/dist/ui/components/molecules/BluetoothDeviceSelectorModal.js +61 -0
- package/dist/ui/components/molecules/DeadLetterErrorBlock.d.ts +8 -0
- package/dist/ui/components/molecules/DeadLetterErrorBlock.js +14 -0
- package/dist/ui/components/molecules/EventTimelineItem.d.ts +7 -0
- package/dist/ui/components/molecules/EventTimelineItem.js +65 -0
- package/dist/ui/components/molecules/ProcessToast.d.ts +5 -0
- package/dist/ui/components/molecules/ProcessToast.js +51 -0
- package/dist/ui/components/molecules/ProcessToastProvider.d.ts +4 -0
- package/dist/ui/components/molecules/ProcessToastProvider.js +5 -0
- package/dist/ui/components/molecules/index.d.ts +5 -0
- package/dist/ui/components/molecules/index.js +5 -0
- package/dist/ui/components/organisms/BluetoothPrinterSelector.d.ts +7 -0
- package/dist/ui/components/organisms/BluetoothPrinterSelector.js +92 -0
- package/dist/ui/components/organisms/DatabaseInfoRow.d.ts +11 -0
- package/dist/ui/components/organisms/DatabaseInfoRow.js +8 -0
- package/dist/ui/components/organisms/DeadLetterQueueRow.d.ts +7 -0
- package/dist/ui/components/organisms/DeadLetterQueueRow.js +72 -0
- package/dist/ui/components/organisms/EventRow.d.ts +7 -0
- package/dist/ui/components/organisms/EventRow.js +90 -0
- package/dist/ui/components/organisms/InjectableWebView.d.ts +35 -0
- package/dist/ui/components/organisms/InjectableWebView.js +169 -0
- package/dist/ui/components/organisms/Receipt.d.ts +11 -0
- package/dist/ui/components/organisms/Receipt.js +207 -0
- package/dist/ui/components/organisms/TableInfoInfoRow.d.ts +9 -0
- package/dist/ui/components/organisms/TableInfoInfoRow.js +19 -0
- package/dist/ui/components/organisms/index.d.ts +7 -0
- package/dist/ui/components/organisms/index.js +7 -0
- package/dist/ui/index.d.ts +4 -0
- package/dist/ui/index.js +4 -0
- package/dist/ui/layouts/router_layouts.d.ts +17 -0
- package/dist/ui/layouts/router_layouts.js +20 -0
- package/dist/ui/screens/database/database.context.d.ts +32 -0
- package/dist/ui/screens/database/database.context.js +158 -0
- package/dist/ui/screens/database/database.json_detail.d.ts +2 -0
- package/dist/ui/screens/database/database.json_detail.js +19 -0
- package/dist/ui/screens/database/database.list.d.ts +1 -0
- package/dist/ui/screens/database/database.list.js +41 -0
- package/dist/ui/screens/database/database.table_rows.d.ts +2 -0
- package/dist/ui/screens/database/database.table_rows.js +10 -0
- package/dist/ui/screens/dead_letter_queue/dead_letter_queue.context.d.ts +34 -0
- package/dist/ui/screens/dead_letter_queue/dead_letter_queue.context.js +166 -0
- package/dist/ui/screens/dead_letter_queue/dead_letter_queue.list.d.ts +2 -0
- package/dist/ui/screens/dead_letter_queue/dead_letter_queue.list.js +24 -0
- package/dist/ui/screens/events/events.context.d.ts +25 -0
- package/dist/ui/screens/events/events.context.js +113 -0
- package/dist/ui/screens/events/events.list.d.ts +1 -0
- package/dist/ui/screens/events/events.list.js +26 -0
- package/dist/ui/screens/events/index.d.ts +1 -0
- package/dist/ui/screens/events/index.js +1 -0
- package/dist/ui/screens/index.d.ts +3 -0
- package/dist/ui/screens/index.js +3 -0
- package/package.json +125 -0
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { convertToArray } from "../../tools/utils/collections";
|
|
2
|
+
import * as Crypto from "expo-crypto";
|
|
3
|
+
import { v7 as uuidv7 } from "uuid";
|
|
4
|
+
/**
|
|
5
|
+
* Constructs a SQL placeholder string and corresponding values for use in a query based on the provided field and data.
|
|
6
|
+
*
|
|
7
|
+
* @param {string} field - The database field name to be used in the placeholder condition.
|
|
8
|
+
* @param {any} data - The data used to generate placeholders and corresponding values. Can be an array, object, set, or a single value.
|
|
9
|
+
* @return {[string, string]} - A tuple where the first element is the formatted placeholder condition string,
|
|
10
|
+
* and the second element is the corresponding values. IE: `["field IN (?, ?, ?)", [value1, value2, value3]]`.
|
|
11
|
+
*/
|
|
12
|
+
export function getPlaceholders(field, data) {
|
|
13
|
+
let placeholders = "";
|
|
14
|
+
let values = data;
|
|
15
|
+
if (data instanceof Set) {
|
|
16
|
+
values = convertToArray(data);
|
|
17
|
+
placeholders = values.map(() => "?").join(",");
|
|
18
|
+
}
|
|
19
|
+
else if (data instanceof Object) {
|
|
20
|
+
values = Object.values(data);
|
|
21
|
+
placeholders = Object.keys(data)
|
|
22
|
+
.map(() => "?")
|
|
23
|
+
.join(",");
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
values = convertToArray(data);
|
|
27
|
+
placeholders = data.map(() => "?").join(",");
|
|
28
|
+
}
|
|
29
|
+
return [`${field} IN (${placeholders})`, values];
|
|
30
|
+
}
|
|
31
|
+
export function generateUUID() {
|
|
32
|
+
return uuidv7({
|
|
33
|
+
random: Crypto.getRandomBytes(16),
|
|
34
|
+
});
|
|
35
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
type LoggerArgs = unknown[];
|
|
2
|
+
interface ILogger {
|
|
3
|
+
debug(...args: LoggerArgs): void;
|
|
4
|
+
info(...args: LoggerArgs): void;
|
|
5
|
+
warn(...args: LoggerArgs): void;
|
|
6
|
+
error(...args: LoggerArgs): void;
|
|
7
|
+
}
|
|
8
|
+
declare const enum ELogLevel {
|
|
9
|
+
DEBUG = "DEBUG",
|
|
10
|
+
INFO = "INFO",
|
|
11
|
+
WARN = "WARN",
|
|
12
|
+
ERROR = "ERROR"
|
|
13
|
+
}
|
|
14
|
+
declare const enum EApplicationLogger {
|
|
15
|
+
GLOBAL = "GLOBAL",
|
|
16
|
+
ODOO_CLIENT = "ODOO_CLIENT",
|
|
17
|
+
ADAPTER = "ADAPTER",
|
|
18
|
+
REPOSITORIES = "REPOSITORIES",
|
|
19
|
+
USE_CASES = "USE_CASES",
|
|
20
|
+
QUEUE_PROCESSOR = "EVENT_BUS",
|
|
21
|
+
CRON_JOBS = "CRON_JOBS"
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Production flag - manually toggle to disable all logs
|
|
25
|
+
* Set to true to disable logging, false to enable
|
|
26
|
+
*/
|
|
27
|
+
export declare const IS_PRODUCTION = false;
|
|
28
|
+
/**
|
|
29
|
+
* Global log level for the application.
|
|
30
|
+
*/
|
|
31
|
+
export declare const LOG_LEVEL = ELogLevel.INFO;
|
|
32
|
+
/**
|
|
33
|
+
* Configuration for enabling or disabling logs for specific application contexts.
|
|
34
|
+
*/
|
|
35
|
+
export declare const ENABLED_LOGS: Record<EApplicationLogger, boolean>;
|
|
36
|
+
export declare function createLogger(context: EApplicationLogger): ILogger;
|
|
37
|
+
declare const logger: ILogger;
|
|
38
|
+
export declare const loggerOdooClient: ILogger;
|
|
39
|
+
export declare const loggerAdapter: ILogger;
|
|
40
|
+
export declare const loggerRepositories: ILogger;
|
|
41
|
+
export declare const loggerUseCases: ILogger;
|
|
42
|
+
export declare const loggerQueueProcessor: ILogger;
|
|
43
|
+
export declare const loggerCronJobs: ILogger;
|
|
44
|
+
export { EApplicationLogger };
|
|
45
|
+
export default logger;
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
// ANSI color codes for terminal output
|
|
2
|
+
const Colors = {
|
|
3
|
+
Reset: "\x1b[0m",
|
|
4
|
+
Gray: "\x1b[90m",
|
|
5
|
+
Red: "\x1b[31m",
|
|
6
|
+
Yellow: "\x1b[33m",
|
|
7
|
+
Blue: "\x1b[34m",
|
|
8
|
+
Cyan: "\x1b[36m",
|
|
9
|
+
Green: "\x1b[32m",
|
|
10
|
+
Magenta: "\x1b[35m",
|
|
11
|
+
BrightBlue: "\x1b[94m",
|
|
12
|
+
BrightGreen: "\x1b[92m",
|
|
13
|
+
BrightCyan: "\x1b[96m",
|
|
14
|
+
BrightMagenta: "\x1b[95m",
|
|
15
|
+
BrightYellow: "\x1b[93m",
|
|
16
|
+
White: "\x1b[37m",
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Color mapping for each logger context
|
|
20
|
+
*/
|
|
21
|
+
const LoggerColors = {
|
|
22
|
+
["GLOBAL" /* EApplicationLogger.GLOBAL */]: Colors.White,
|
|
23
|
+
["ODOO_CLIENT" /* EApplicationLogger.ODOO_CLIENT */]: Colors.Gray,
|
|
24
|
+
["ADAPTER" /* EApplicationLogger.ADAPTER */]: Colors.Gray,
|
|
25
|
+
["REPOSITORIES" /* EApplicationLogger.REPOSITORIES */]: Colors.Gray,
|
|
26
|
+
["USE_CASES" /* EApplicationLogger.USE_CASES */]: Colors.BrightGreen,
|
|
27
|
+
["EVENT_BUS" /* EApplicationLogger.QUEUE_PROCESSOR */]: Colors.BrightYellow,
|
|
28
|
+
["CRON_JOBS" /* EApplicationLogger.CRON_JOBS */]: Colors.Gray,
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Production flag - manually toggle to disable all logs
|
|
32
|
+
* Set to true to disable logging, false to enable
|
|
33
|
+
*/
|
|
34
|
+
export const IS_PRODUCTION = false;
|
|
35
|
+
/**
|
|
36
|
+
* Global log level for the application.
|
|
37
|
+
*/
|
|
38
|
+
export const LOG_LEVEL = "INFO" /* ELogLevel.INFO */;
|
|
39
|
+
/**
|
|
40
|
+
* Configuration for enabling or disabling logs for specific application contexts.
|
|
41
|
+
*/
|
|
42
|
+
export const ENABLED_LOGS = {
|
|
43
|
+
["GLOBAL" /* EApplicationLogger.GLOBAL */]: true,
|
|
44
|
+
["ODOO_CLIENT" /* EApplicationLogger.ODOO_CLIENT */]: false,
|
|
45
|
+
["ADAPTER" /* EApplicationLogger.ADAPTER */]: false,
|
|
46
|
+
["REPOSITORIES" /* EApplicationLogger.REPOSITORIES */]: false,
|
|
47
|
+
["USE_CASES" /* EApplicationLogger.USE_CASES */]: true,
|
|
48
|
+
["EVENT_BUS" /* EApplicationLogger.QUEUE_PROCESSOR */]: true,
|
|
49
|
+
["CRON_JOBS" /* EApplicationLogger.CRON_JOBS */]: true,
|
|
50
|
+
};
|
|
51
|
+
class BaseLogger {
|
|
52
|
+
context;
|
|
53
|
+
contextPrefix;
|
|
54
|
+
constructor(context) {
|
|
55
|
+
this.context = context;
|
|
56
|
+
this.contextPrefix = context === "GLOBAL" /* EApplicationLogger.GLOBAL */ ? "" : `[${context}]`;
|
|
57
|
+
}
|
|
58
|
+
getLogColor(level) {
|
|
59
|
+
switch (level) {
|
|
60
|
+
case "DEBUG" /* ELogLevel.DEBUG */:
|
|
61
|
+
return Colors.Gray;
|
|
62
|
+
case "INFO" /* ELogLevel.INFO */:
|
|
63
|
+
return Colors.Cyan;
|
|
64
|
+
case "WARN" /* ELogLevel.WARN */:
|
|
65
|
+
return Colors.Yellow;
|
|
66
|
+
case "ERROR" /* ELogLevel.ERROR */:
|
|
67
|
+
return Colors.Red;
|
|
68
|
+
default:
|
|
69
|
+
return Colors.White;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
getContextColor() {
|
|
73
|
+
return LoggerColors[this.context];
|
|
74
|
+
}
|
|
75
|
+
log(level, method, args) {
|
|
76
|
+
if (this.shouldLog(level)) {
|
|
77
|
+
this.output(method, level, args);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
shouldLog(level) {
|
|
81
|
+
if (IS_PRODUCTION)
|
|
82
|
+
return false;
|
|
83
|
+
if (level === "ERROR" /* ELogLevel.ERROR */ || level === "WARN" /* ELogLevel.WARN */)
|
|
84
|
+
return true;
|
|
85
|
+
if (level === "DEBUG" /* ELogLevel.DEBUG */ && LOG_LEVEL !== "DEBUG" /* ELogLevel.DEBUG */)
|
|
86
|
+
return false;
|
|
87
|
+
if (!ENABLED_LOGS[this.context])
|
|
88
|
+
return false;
|
|
89
|
+
return true;
|
|
90
|
+
}
|
|
91
|
+
output(method, level, args) {
|
|
92
|
+
const timestamp = new Date().toISOString();
|
|
93
|
+
const contextColor = this.getContextColor();
|
|
94
|
+
if (this.contextPrefix) {
|
|
95
|
+
// Colorear todo el mensaje con el color del contexto
|
|
96
|
+
method(`${Colors.Gray}${timestamp}${Colors.Reset}`, `${contextColor}${this.contextPrefix}`, ...args, Colors.Reset);
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
method(`${Colors.Gray}${timestamp}${Colors.Reset}`, ...args);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
debug(...args) {
|
|
103
|
+
this.log("DEBUG" /* ELogLevel.DEBUG */, console.debug, args);
|
|
104
|
+
}
|
|
105
|
+
info(...args) {
|
|
106
|
+
this.log("INFO" /* ELogLevel.INFO */, console.log, args);
|
|
107
|
+
}
|
|
108
|
+
warn(...args) {
|
|
109
|
+
this.log("WARN" /* ELogLevel.WARN */, console.warn, args);
|
|
110
|
+
}
|
|
111
|
+
error(...args) {
|
|
112
|
+
this.log("ERROR" /* ELogLevel.ERROR */, console.error, args);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
export function createLogger(context) {
|
|
116
|
+
return new BaseLogger(context);
|
|
117
|
+
}
|
|
118
|
+
const logger = createLogger("GLOBAL" /* EApplicationLogger.GLOBAL */);
|
|
119
|
+
export const loggerOdooClient = createLogger("ODOO_CLIENT" /* EApplicationLogger.ODOO_CLIENT */);
|
|
120
|
+
export const loggerAdapter = createLogger("ADAPTER" /* EApplicationLogger.ADAPTER */);
|
|
121
|
+
export const loggerRepositories = createLogger("REPOSITORIES" /* EApplicationLogger.REPOSITORIES */);
|
|
122
|
+
export const loggerUseCases = createLogger("USE_CASES" /* EApplicationLogger.USE_CASES */);
|
|
123
|
+
export const loggerQueueProcessor = createLogger("EVENT_BUS" /* EApplicationLogger.QUEUE_PROCESSOR */);
|
|
124
|
+
export const loggerCronJobs = createLogger("CRON_JOBS" /* EApplicationLogger.CRON_JOBS */);
|
|
125
|
+
export default logger;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function ToastHost(): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { jsx as _jsx } from "nativewind/jsx-runtime";
|
|
2
|
+
import { useEffect } from "react";
|
|
3
|
+
import Toast from "react-native-toast-message";
|
|
4
|
+
import { UI_NOTIFICATION_EVENT } from "./events";
|
|
5
|
+
import { UIEventBus } from "./UIEventBus";
|
|
6
|
+
export function ToastHost() {
|
|
7
|
+
useEffect(() => {
|
|
8
|
+
const off = UIEventBus.on(UI_NOTIFICATION_EVENT, (payload) => {
|
|
9
|
+
const notification = payload;
|
|
10
|
+
Toast.show({
|
|
11
|
+
type: notification.type ?? "info",
|
|
12
|
+
text1: notification.text1,
|
|
13
|
+
text2: notification.text2,
|
|
14
|
+
});
|
|
15
|
+
});
|
|
16
|
+
return off;
|
|
17
|
+
}, []);
|
|
18
|
+
return _jsx(Toast, {});
|
|
19
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Handler } from "mitt";
|
|
2
|
+
declare class UIEventBusImpl {
|
|
3
|
+
private emitter;
|
|
4
|
+
private subscriptions;
|
|
5
|
+
private handlerIdCounter;
|
|
6
|
+
on<T = unknown>(event: string, handler: Handler<T>): () => void;
|
|
7
|
+
off<T = unknown>(event: string, handler: Handler<T>): void;
|
|
8
|
+
emit<T = unknown>(event: string, payload?: T): void;
|
|
9
|
+
clear(): void;
|
|
10
|
+
}
|
|
11
|
+
export declare const UIEventBus: UIEventBusImpl;
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import mitt from "mitt";
|
|
2
|
+
const DEBOUNCE_DELAY = 300;
|
|
3
|
+
class UIEventBusImpl {
|
|
4
|
+
emitter = mitt();
|
|
5
|
+
subscriptions = new Map();
|
|
6
|
+
handlerIdCounter = 0;
|
|
7
|
+
on(event, handler) {
|
|
8
|
+
const handlerId = `${event}_${++this.handlerIdCounter}`;
|
|
9
|
+
const wrappedHandler = (payload) => {
|
|
10
|
+
const sub = this.subscriptions.get(handlerId);
|
|
11
|
+
if (sub?.timer) {
|
|
12
|
+
clearTimeout(sub.timer);
|
|
13
|
+
}
|
|
14
|
+
const timer = setTimeout(() => {
|
|
15
|
+
handler(payload);
|
|
16
|
+
const subscription = this.subscriptions.get(handlerId);
|
|
17
|
+
if (subscription)
|
|
18
|
+
subscription.timer = null;
|
|
19
|
+
}, DEBOUNCE_DELAY);
|
|
20
|
+
this.subscriptions.set(handlerId, {
|
|
21
|
+
timer,
|
|
22
|
+
wrappedHandler,
|
|
23
|
+
originalHandler: handler,
|
|
24
|
+
});
|
|
25
|
+
};
|
|
26
|
+
this.subscriptions.set(handlerId, {
|
|
27
|
+
timer: null,
|
|
28
|
+
wrappedHandler,
|
|
29
|
+
originalHandler: handler,
|
|
30
|
+
});
|
|
31
|
+
this.emitter.on(event, wrappedHandler);
|
|
32
|
+
return () => {
|
|
33
|
+
const sub = this.subscriptions.get(handlerId);
|
|
34
|
+
if (sub?.timer)
|
|
35
|
+
clearTimeout(sub.timer);
|
|
36
|
+
if (sub?.wrappedHandler)
|
|
37
|
+
this.emitter.off(event, sub.wrappedHandler);
|
|
38
|
+
this.subscriptions.delete(handlerId);
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
off(event, handler) {
|
|
42
|
+
for (const [handlerId, sub] of this.subscriptions.entries()) {
|
|
43
|
+
if (handlerId.startsWith(`${event}_`) && sub.originalHandler === handler) {
|
|
44
|
+
if (sub.timer)
|
|
45
|
+
clearTimeout(sub.timer);
|
|
46
|
+
this.emitter.off(event, sub.wrappedHandler);
|
|
47
|
+
this.subscriptions.delete(handlerId);
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
this.emitter.off(event, handler);
|
|
52
|
+
}
|
|
53
|
+
emit(event, payload) {
|
|
54
|
+
this.emitter.emit(event, payload);
|
|
55
|
+
}
|
|
56
|
+
clear() {
|
|
57
|
+
this.subscriptions.forEach((sub) => {
|
|
58
|
+
if (sub.timer)
|
|
59
|
+
clearTimeout(sub.timer);
|
|
60
|
+
});
|
|
61
|
+
this.subscriptions.clear();
|
|
62
|
+
this.emitter.all.clear();
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
export const UIEventBus = new UIEventBusImpl();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function installGlobalErrorHandler(): void;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { DomainException } from "../../exceptions";
|
|
2
|
+
import { Alert } from "react-native";
|
|
3
|
+
export function installGlobalErrorHandler() {
|
|
4
|
+
const errorUtils = globalThis.ErrorUtils;
|
|
5
|
+
if (!errorUtils?.setGlobalHandler) {
|
|
6
|
+
return;
|
|
7
|
+
}
|
|
8
|
+
const defaultHandler = errorUtils.getGlobalHandler
|
|
9
|
+
? errorUtils.getGlobalHandler()
|
|
10
|
+
: errorUtils._globalHandler;
|
|
11
|
+
errorUtils.setGlobalHandler((error, isFatal) => {
|
|
12
|
+
if (error instanceof DomainException) {
|
|
13
|
+
Alert.alert("Error", error.message, [{ text: "OK" }], { cancelable: true });
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
if (typeof defaultHandler === "function") {
|
|
17
|
+
defaultHandler(error, isFatal);
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const UI_NOTIFICATION_EVENT = "ui.notification";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const UI_NOTIFICATION_EVENT = "ui.notification";
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export type CronJob = () => Promise<void>;
|
|
2
|
+
export declare class CronWorker {
|
|
3
|
+
readonly taskName: string;
|
|
4
|
+
private readonly job;
|
|
5
|
+
private readonly intervalMin;
|
|
6
|
+
readonly requiresAuth: boolean;
|
|
7
|
+
private stopFn?;
|
|
8
|
+
private isRegistering;
|
|
9
|
+
private isExecuting;
|
|
10
|
+
private registrationError?;
|
|
11
|
+
constructor(taskName: string, job: CronJob, intervalMin?: number, requiresAuth?: boolean);
|
|
12
|
+
/**
|
|
13
|
+
* Registers a task with a specified interval and execution logic.
|
|
14
|
+
* If the interval is less than 15 minutes, a repeating job is created using a defined stop function.
|
|
15
|
+
* If the interval is 15 minutes or greater, the task is registered with a task manager and scheduled as a background task.
|
|
16
|
+
*
|
|
17
|
+
* @return {Promise<void>} A promise that resolves when the task registration process is complete.
|
|
18
|
+
*/
|
|
19
|
+
start(): Promise<void>;
|
|
20
|
+
/**
|
|
21
|
+
* Unregisters a background task with the specified task name.
|
|
22
|
+
* If a stop function is defined, it is invoked before unregistering the task.
|
|
23
|
+
*
|
|
24
|
+
* @return {Promise<void>} A promise that resolves when the task has been successfully unregistered.
|
|
25
|
+
*/
|
|
26
|
+
unregister(): Promise<void>;
|
|
27
|
+
/**
|
|
28
|
+
* Check if the task is properly registered and functioning
|
|
29
|
+
*/
|
|
30
|
+
isHealthy(): boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Get any registration error that occurred
|
|
33
|
+
*/
|
|
34
|
+
getLastError(): Error | undefined;
|
|
35
|
+
private createIntervalJob;
|
|
36
|
+
private runWithEvents;
|
|
37
|
+
/**
|
|
38
|
+
* Waits for current job execution to complete (if any).
|
|
39
|
+
* Timeout after 10 seconds to prevent infinite wait.
|
|
40
|
+
*/
|
|
41
|
+
waitForIdle(): Promise<void>;
|
|
42
|
+
}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { loggerCronJobs } from "../../infrastructure/logger";
|
|
2
|
+
import { UIEventBus } from "../../infrastructure/ui/UIEventBus";
|
|
3
|
+
import * as BackgroundTask from "expo-background-task";
|
|
4
|
+
import * as TaskManager from "expo-task-manager";
|
|
5
|
+
export class CronWorker {
|
|
6
|
+
taskName;
|
|
7
|
+
job;
|
|
8
|
+
intervalMin;
|
|
9
|
+
requiresAuth;
|
|
10
|
+
stopFn;
|
|
11
|
+
isRegistering = false;
|
|
12
|
+
isExecuting = false;
|
|
13
|
+
registrationError;
|
|
14
|
+
constructor(taskName, job, intervalMin = 15, requiresAuth = false) {
|
|
15
|
+
this.taskName = taskName;
|
|
16
|
+
this.job = job;
|
|
17
|
+
this.intervalMin = intervalMin;
|
|
18
|
+
this.requiresAuth = requiresAuth;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Registers a task with a specified interval and execution logic.
|
|
22
|
+
* If the interval is less than 15 minutes, a repeating job is created using a defined stop function.
|
|
23
|
+
* If the interval is 15 minutes or greater, the task is registered with a task manager and scheduled as a background task.
|
|
24
|
+
*
|
|
25
|
+
* @return {Promise<void>} A promise that resolves when the task registration process is complete.
|
|
26
|
+
*/
|
|
27
|
+
async start() {
|
|
28
|
+
if (this.isRegistering)
|
|
29
|
+
return;
|
|
30
|
+
this.isRegistering = true;
|
|
31
|
+
try {
|
|
32
|
+
loggerCronJobs.info(`Schedule [every ${this.intervalMin} min]: task ${this.taskName}`);
|
|
33
|
+
if (this.intervalMin < 15) {
|
|
34
|
+
this.stopFn = this.createIntervalJob(this.job, this.intervalMin);
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
TaskManager.defineTask(this.taskName, async () => {
|
|
38
|
+
try {
|
|
39
|
+
await this.job();
|
|
40
|
+
return BackgroundTask.BackgroundTaskResult.Success;
|
|
41
|
+
}
|
|
42
|
+
catch (e) {
|
|
43
|
+
loggerCronJobs.warn(`${this.taskName} error:`, e);
|
|
44
|
+
return BackgroundTask.BackgroundTaskResult.Failed;
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
await BackgroundTask.registerTaskAsync(this.taskName, {
|
|
48
|
+
minimumInterval: this.intervalMin,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
this.registrationError = undefined;
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
this.registrationError = error instanceof Error ? error : new Error(String(error));
|
|
55
|
+
loggerCronJobs.warn(`Failed to register task ${this.taskName}:`, error);
|
|
56
|
+
throw error;
|
|
57
|
+
}
|
|
58
|
+
finally {
|
|
59
|
+
this.isRegistering = false;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Unregisters a background task with the specified task name.
|
|
64
|
+
* If a stop function is defined, it is invoked before unregistering the task.
|
|
65
|
+
*
|
|
66
|
+
* @return {Promise<void>} A promise that resolves when the task has been successfully unregistered.
|
|
67
|
+
*/
|
|
68
|
+
async unregister() {
|
|
69
|
+
try {
|
|
70
|
+
if (this.stopFn) {
|
|
71
|
+
this.stopFn();
|
|
72
|
+
this.stopFn = undefined;
|
|
73
|
+
}
|
|
74
|
+
// Only attempt to unregister background tasks (>= 15 min)
|
|
75
|
+
if (this.intervalMin >= 15) {
|
|
76
|
+
await BackgroundTask.unregisterTaskAsync(this.taskName);
|
|
77
|
+
}
|
|
78
|
+
loggerCronJobs.info(`Task ${this.taskName} unregistered successfully`);
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
loggerCronJobs.warn(`Failed to unregister task ${this.taskName}:`, error);
|
|
82
|
+
throw error;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Check if the task is properly registered and functioning
|
|
87
|
+
*/
|
|
88
|
+
isHealthy() {
|
|
89
|
+
return !this.registrationError && (this.stopFn !== undefined || this.intervalMin >= 15);
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Get any registration error that occurred
|
|
93
|
+
*/
|
|
94
|
+
getLastError() {
|
|
95
|
+
return this.registrationError;
|
|
96
|
+
}
|
|
97
|
+
createIntervalJob(job, intervalMinutes) {
|
|
98
|
+
this.runWithEvents(job);
|
|
99
|
+
const id = setInterval(() => {
|
|
100
|
+
this.runWithEvents(job);
|
|
101
|
+
}, intervalMinutes * 60 * 1000);
|
|
102
|
+
return () => {
|
|
103
|
+
clearInterval(id);
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
async runWithEvents(job) {
|
|
107
|
+
this.isExecuting = true;
|
|
108
|
+
const startTime = Date.now();
|
|
109
|
+
UIEventBus.emit("CRON_START", { task: this.taskName });
|
|
110
|
+
try {
|
|
111
|
+
await Promise.resolve(job());
|
|
112
|
+
const duration = Date.now() - startTime;
|
|
113
|
+
loggerCronJobs.debug(`${this.taskName} completed successfully in ${duration}ms`);
|
|
114
|
+
}
|
|
115
|
+
catch (e) {
|
|
116
|
+
const duration = Date.now() - startTime;
|
|
117
|
+
const errorMessage = e instanceof Error ? e.message : String(e);
|
|
118
|
+
loggerCronJobs.error(`${this.taskName} failed after ${duration}ms with error: ${errorMessage}`);
|
|
119
|
+
}
|
|
120
|
+
finally {
|
|
121
|
+
this.isExecuting = false;
|
|
122
|
+
UIEventBus.emit("CRON_END", { task: this.taskName });
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Waits for current job execution to complete (if any).
|
|
127
|
+
* Timeout after 10 seconds to prevent infinite wait.
|
|
128
|
+
*/
|
|
129
|
+
async waitForIdle() {
|
|
130
|
+
if (!this.isExecuting)
|
|
131
|
+
return;
|
|
132
|
+
const maxWait = 10000;
|
|
133
|
+
const checkInterval = 100;
|
|
134
|
+
let waited = 0;
|
|
135
|
+
while (this.isExecuting && waited < maxWait) {
|
|
136
|
+
await new Promise((resolve) => setTimeout(resolve, checkInterval));
|
|
137
|
+
waited += checkInterval;
|
|
138
|
+
}
|
|
139
|
+
if (this.isExecuting) {
|
|
140
|
+
loggerCronJobs.warn(`${this.taskName} waitForIdle timed out after 10s`);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { DomainEvent, EventName, Subscriber } from "../../domain/event_sourcing";
|
|
2
|
+
export declare const PROCESS_WORKER_MAX_ATTEMPTS = 1;
|
|
3
|
+
export { EventName };
|
|
4
|
+
export declare class EventBus {
|
|
5
|
+
private static readonly MAX_ATTEMPTS;
|
|
6
|
+
private static readonly INTERVAL_MS;
|
|
7
|
+
private static readonly MAX_INTERVAL_MS;
|
|
8
|
+
private static readonly BACKOFF_MULTIPLIER;
|
|
9
|
+
private static subscribers;
|
|
10
|
+
private static isDraining;
|
|
11
|
+
private static intervalId;
|
|
12
|
+
private static internetConnected;
|
|
13
|
+
private static consecutiveFailures;
|
|
14
|
+
private static currentInterval;
|
|
15
|
+
static initConnectivityListeners(): void;
|
|
16
|
+
private static adjustInterval;
|
|
17
|
+
private static restartPolling;
|
|
18
|
+
private static triggerProcessing;
|
|
19
|
+
static start(): void;
|
|
20
|
+
static stop(): void;
|
|
21
|
+
/**
|
|
22
|
+
* Waits for current processing cycle to complete (if any).
|
|
23
|
+
* Use before clean() to ensure graceful shutdown.
|
|
24
|
+
* Timeout after 5 seconds to prevent infinite wait.
|
|
25
|
+
*/
|
|
26
|
+
static waitForIdle(): Promise<void>;
|
|
27
|
+
/**
|
|
28
|
+
* Validates event, logs start, emits START.
|
|
29
|
+
* Returns false if no subscribers (caller should return early).
|
|
30
|
+
*/
|
|
31
|
+
private static preProcess;
|
|
32
|
+
/**
|
|
33
|
+
* Handles persistence, emits event and END, logs result.
|
|
34
|
+
* If errors is empty -> success, otherwise -> failure + dead letter + throws.
|
|
35
|
+
* @throws Error if there are any errors
|
|
36
|
+
*/
|
|
37
|
+
private static postProcess;
|
|
38
|
+
private static executeSubscribers;
|
|
39
|
+
/**
|
|
40
|
+
* Registers a subscriber for DomainEvent classes.
|
|
41
|
+
* A subscriber can listen to multiple events.
|
|
42
|
+
* Multiple subscribers can listen to the same event.
|
|
43
|
+
* Prevents duplicate registration of the same subscriber instance.
|
|
44
|
+
*/
|
|
45
|
+
static on(subscriber: Subscriber): void;
|
|
46
|
+
static off(subscriber: Subscriber): void;
|
|
47
|
+
/**
|
|
48
|
+
* Publishes a DomainEvent asynchronously - enqueues for later processing.
|
|
49
|
+
*/
|
|
50
|
+
static publish(event: DomainEvent): Promise<void>;
|
|
51
|
+
/**
|
|
52
|
+
* Publishes a DomainEvent synchronously - executes all subscribers immediately.
|
|
53
|
+
* Saves event to DB for traceability. Moves to dead letter on failure.
|
|
54
|
+
* @throws Error if any subscriber fails or no subscribers registered
|
|
55
|
+
*/
|
|
56
|
+
static publishSync(event: DomainEvent): Promise<void>;
|
|
57
|
+
/**
|
|
58
|
+
* Processes all pending DomainEvents from the domain_events table.
|
|
59
|
+
* Executes ALL subscribers registered for each event.
|
|
60
|
+
* Moves to dead letter queue on failure.
|
|
61
|
+
*/
|
|
62
|
+
private static drainAll;
|
|
63
|
+
/**
|
|
64
|
+
* Clears the event queue (domain_events table).
|
|
65
|
+
*/
|
|
66
|
+
static clearQueue(): Promise<void>;
|
|
67
|
+
}
|