@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,11 @@
|
|
|
1
|
+
import { DomainEvent } from "../../domain/event_sourcing";
|
|
2
|
+
export class WebViewMessageReceivedEvent extends DomainEvent {
|
|
3
|
+
static name = "common.webview.v1.message_received";
|
|
4
|
+
static label = "Procesando datos de la web";
|
|
5
|
+
static requiresNetwork = false;
|
|
6
|
+
name = WebViewMessageReceivedEvent.name;
|
|
7
|
+
label = WebViewMessageReceivedEvent.label;
|
|
8
|
+
requiresNetwork = WebViewMessageReceivedEvent.requiresNetwork;
|
|
9
|
+
raw = "";
|
|
10
|
+
source = "";
|
|
11
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { EWebViewMessageType, type IAjaxInterceptedMessage, type IContentReadyMessage, type IDebugPrintMessage, type IInjectedScript, type IInjectionReadyMessage, type IPrintImageMessage, type IPrintRequestMessage, type IWebViewMetadata, type TPrintSource, type TWebViewMessage, } from "./webview";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { EWebViewMessageType, } from "./webview";
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
export declare enum EWebViewMessageType {
|
|
2
|
+
PRINT_REQUEST = "PRINT_REQUEST",
|
|
3
|
+
PRINT_IMAGE = "PRINT_IMAGE",
|
|
4
|
+
CONTENT_READY = "CONTENT_READY",
|
|
5
|
+
INJECTION_READY = "INJECTION_READY",
|
|
6
|
+
AJAX_INTERCEPTED = "AJAX_INTERCEPTED",
|
|
7
|
+
DEBUG_PRINT = "DEBUG_PRINT"
|
|
8
|
+
}
|
|
9
|
+
export type TPrintSource = "pos-receipt" | "report" | "document" | "unknown";
|
|
10
|
+
export interface IWebViewMetadata {
|
|
11
|
+
url: string;
|
|
12
|
+
title: string;
|
|
13
|
+
capturedAt: string;
|
|
14
|
+
}
|
|
15
|
+
export interface IPrintRequestMessage {
|
|
16
|
+
type: EWebViewMessageType.PRINT_REQUEST;
|
|
17
|
+
source: TPrintSource;
|
|
18
|
+
content: string;
|
|
19
|
+
metadata: IWebViewMetadata;
|
|
20
|
+
}
|
|
21
|
+
export interface IPrintImageMessage {
|
|
22
|
+
type: EWebViewMessageType.PRINT_IMAGE;
|
|
23
|
+
image: string;
|
|
24
|
+
width: number;
|
|
25
|
+
height: number;
|
|
26
|
+
metadata: IWebViewMetadata;
|
|
27
|
+
}
|
|
28
|
+
export interface IContentReadyMessage {
|
|
29
|
+
type: EWebViewMessageType.CONTENT_READY;
|
|
30
|
+
height: number;
|
|
31
|
+
}
|
|
32
|
+
export interface IInjectionReadyMessage {
|
|
33
|
+
type: EWebViewMessageType.INJECTION_READY;
|
|
34
|
+
injector: string;
|
|
35
|
+
}
|
|
36
|
+
export interface IAjaxInterceptedMessage {
|
|
37
|
+
type: EWebViewMessageType.AJAX_INTERCEPTED;
|
|
38
|
+
url: string;
|
|
39
|
+
method: string;
|
|
40
|
+
response?: unknown;
|
|
41
|
+
}
|
|
42
|
+
export interface IDebugPrintMessage {
|
|
43
|
+
type: EWebViewMessageType.DEBUG_PRINT;
|
|
44
|
+
debug: {
|
|
45
|
+
tagName: string;
|
|
46
|
+
className: string;
|
|
47
|
+
id: string;
|
|
48
|
+
width: number;
|
|
49
|
+
height: number;
|
|
50
|
+
isBody: boolean;
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
export type TWebViewMessage = IPrintRequestMessage | IPrintImageMessage | IContentReadyMessage | IInjectionReadyMessage | IAjaxInterceptedMessage | IDebugPrintMessage;
|
|
54
|
+
export interface IInjectedScript {
|
|
55
|
+
name: string;
|
|
56
|
+
script: string;
|
|
57
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export var EWebViewMessageType;
|
|
2
|
+
(function (EWebViewMessageType) {
|
|
3
|
+
EWebViewMessageType["PRINT_REQUEST"] = "PRINT_REQUEST";
|
|
4
|
+
EWebViewMessageType["PRINT_IMAGE"] = "PRINT_IMAGE";
|
|
5
|
+
EWebViewMessageType["CONTENT_READY"] = "CONTENT_READY";
|
|
6
|
+
EWebViewMessageType["INJECTION_READY"] = "INJECTION_READY";
|
|
7
|
+
EWebViewMessageType["AJAX_INTERCEPTED"] = "AJAX_INTERCEPTED";
|
|
8
|
+
EWebViewMessageType["DEBUG_PRINT"] = "DEBUG_PRINT";
|
|
9
|
+
})(EWebViewMessageType || (EWebViewMessageType = {}));
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { CronWorker } from "../../infrastructure/workers";
|
|
2
|
+
export interface SyncResult {
|
|
3
|
+
changed: boolean;
|
|
4
|
+
added: number;
|
|
5
|
+
removed: number;
|
|
6
|
+
}
|
|
7
|
+
declare class Cron {
|
|
8
|
+
private lastSyncState;
|
|
9
|
+
private currentCrons;
|
|
10
|
+
sync(domains: Set<string>, isAuthenticated: boolean, cronsByKey: Record<string, CronWorker[]>): Promise<SyncResult>;
|
|
11
|
+
}
|
|
12
|
+
export declare const cron: Cron;
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { loggerCronJobs } from "../../infrastructure/logger";
|
|
2
|
+
function statesAreEqual(a, b) {
|
|
3
|
+
if (!a)
|
|
4
|
+
return false;
|
|
5
|
+
if (a.isAuthenticated !== b.isAuthenticated)
|
|
6
|
+
return false;
|
|
7
|
+
if (a.domains.size !== b.domains.size)
|
|
8
|
+
return false;
|
|
9
|
+
for (const domain of a.domains) {
|
|
10
|
+
if (!b.domains.has(domain))
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
return true;
|
|
14
|
+
}
|
|
15
|
+
function calculateDesiredCrons(domains, isAuthenticated, cronsByKey) {
|
|
16
|
+
const desired = new Set();
|
|
17
|
+
for (const domain of domains) {
|
|
18
|
+
const domainCrons = cronsByKey[domain] ?? [];
|
|
19
|
+
for (const cronWorker of domainCrons) {
|
|
20
|
+
if (isAuthenticated || !cronWorker.requiresAuth) {
|
|
21
|
+
desired.add(cronWorker);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return desired;
|
|
26
|
+
}
|
|
27
|
+
class Cron {
|
|
28
|
+
lastSyncState = null;
|
|
29
|
+
currentCrons = new Set();
|
|
30
|
+
async sync(domains, isAuthenticated, cronsByKey) {
|
|
31
|
+
const newState = { domains: new Set(domains), isAuthenticated };
|
|
32
|
+
if (statesAreEqual(this.lastSyncState, newState)) {
|
|
33
|
+
return { changed: false, added: 0, removed: 0 };
|
|
34
|
+
}
|
|
35
|
+
const desired = calculateDesiredCrons(domains, isAuthenticated, cronsByKey);
|
|
36
|
+
let added = 0;
|
|
37
|
+
let removed = 0;
|
|
38
|
+
for (const cronWorker of this.currentCrons) {
|
|
39
|
+
if (!desired.has(cronWorker)) {
|
|
40
|
+
await cronWorker.waitForIdle();
|
|
41
|
+
await cronWorker.unregister();
|
|
42
|
+
removed++;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
for (const cronWorker of desired) {
|
|
46
|
+
if (!this.currentCrons.has(cronWorker)) {
|
|
47
|
+
await cronWorker.start();
|
|
48
|
+
added++;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
this.currentCrons = desired;
|
|
52
|
+
this.lastSyncState = newState;
|
|
53
|
+
loggerCronJobs.info(`Cron.sync: +${added} -${removed} crons (domains=${[...domains].join(",")}, auth=${isAuthenticated})`);
|
|
54
|
+
return { changed: true, added, removed };
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
export const cron = new Cron();
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { loggerCronJobs } from "../../infrastructure/logger";
|
|
2
|
+
import { CronWorker } from "../../infrastructure/workers";
|
|
3
|
+
import { networkUseCases } from "../../services/network.service";
|
|
4
|
+
async function checkNetworkStatus() {
|
|
5
|
+
loggerCronJobs.info("Checking network status");
|
|
6
|
+
await networkUseCases.getNetworkStatus();
|
|
7
|
+
loggerCronJobs.info("Finished checking network status");
|
|
8
|
+
}
|
|
9
|
+
const cronCheckNetworkStatus = new CronWorker("CHECK_NETWORK", checkNetworkStatus, 2.5);
|
|
10
|
+
export default cronCheckNetworkStatus;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { IMigration } from "../../domain/database";
|
|
2
|
+
export declare const enum DATABASE_TABLES {
|
|
3
|
+
SETTINGS = "settings",
|
|
4
|
+
EVENT_QUEUE = "event_queue",
|
|
5
|
+
DEAD_LETTER_QUEUE = "dead_letter_queue",
|
|
6
|
+
DOMAIN_EVENTS = "domain_events",
|
|
7
|
+
DOMAIN_EVENTS_DEAD_LETTER = "domain_events_dead_letter"
|
|
8
|
+
}
|
|
9
|
+
declare const MIGRATIONS: IMigration[];
|
|
10
|
+
export default MIGRATIONS;
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { DBCursor } from "../../infrastructure/database";
|
|
2
|
+
async function createSettingsTable() {
|
|
3
|
+
await DBCursor.execAsync(`
|
|
4
|
+
CREATE TABLE IF NOT EXISTS ${"settings" /* DATABASE_TABLES.SETTINGS */}(
|
|
5
|
+
name TEXT PRIMARY KEY NOT NULL,
|
|
6
|
+
value TEXT NOT NULL,
|
|
7
|
+
type TEXT NOT NULL,
|
|
8
|
+
updated_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
9
|
+
);
|
|
10
|
+
`);
|
|
11
|
+
}
|
|
12
|
+
async function createDeadLetterQueueTable() {
|
|
13
|
+
await DBCursor.execAsync(`
|
|
14
|
+
CREATE TABLE IF NOT EXISTS ${"dead_letter_queue" /* DATABASE_TABLES.DEAD_LETTER_QUEUE */} (
|
|
15
|
+
uuid TEXT PRIMARY KEY NOT NULL, -- UUID v7 for chronological ordering
|
|
16
|
+
name TEXT NOT NULL,
|
|
17
|
+
payload TEXT NOT NULL,
|
|
18
|
+
attempts INTEGER NOT NULL DEFAULT 0,
|
|
19
|
+
created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
20
|
+
error_message TEXT
|
|
21
|
+
);
|
|
22
|
+
`);
|
|
23
|
+
}
|
|
24
|
+
async function createEventQueueTable() {
|
|
25
|
+
await DBCursor.execAsync(`
|
|
26
|
+
CREATE TABLE IF NOT EXISTS ${"event_queue" /* DATABASE_TABLES.EVENT_QUEUE */}(
|
|
27
|
+
uuid TEXT PRIMARY KEY NOT NULL,
|
|
28
|
+
name TEXT NOT NULL,
|
|
29
|
+
payload TEXT NOT NULL,
|
|
30
|
+
attempts INTEGER NOT NULL DEFAULT 0,
|
|
31
|
+
created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
32
|
+
network_event INTEGER DEFAULT 0,
|
|
33
|
+
aggregate_id TEXT DEFAULT NULL,
|
|
34
|
+
sequence INTEGER DEFAULT 0,
|
|
35
|
+
status TEXT NOT NULL DEFAULT 'PENDING',
|
|
36
|
+
acknowledged_at TEXT DEFAULT NULL,
|
|
37
|
+
error_message TEXT DEFAULT NULL
|
|
38
|
+
);
|
|
39
|
+
`);
|
|
40
|
+
}
|
|
41
|
+
async function createDomainEventsTable() {
|
|
42
|
+
await DBCursor.execAsync(`
|
|
43
|
+
CREATE TABLE IF NOT EXISTS ${"domain_events" /* DATABASE_TABLES.DOMAIN_EVENTS */} (
|
|
44
|
+
uuid TEXT PRIMARY KEY NOT NULL,
|
|
45
|
+
name TEXT NOT NULL,
|
|
46
|
+
label TEXT NOT NULL,
|
|
47
|
+
data TEXT NOT NULL,
|
|
48
|
+
requires_network INTEGER NOT NULL DEFAULT 0,
|
|
49
|
+
created_at TEXT NOT NULL,
|
|
50
|
+
status TEXT NOT NULL DEFAULT 'PENDING',
|
|
51
|
+
attempts INTEGER NOT NULL DEFAULT 0,
|
|
52
|
+
error_message TEXT DEFAULT NULL,
|
|
53
|
+
acknowledged_at TEXT DEFAULT NULL,
|
|
54
|
+
failed_at TEXT DEFAULT NULL,
|
|
55
|
+
aggregate_id TEXT DEFAULT NULL,
|
|
56
|
+
source_id TEXT DEFAULT NULL,
|
|
57
|
+
correlation_id TEXT DEFAULT NULL,
|
|
58
|
+
sequence INTEGER NOT NULL DEFAULT 0
|
|
59
|
+
);
|
|
60
|
+
`);
|
|
61
|
+
await DBCursor.execAsync(`
|
|
62
|
+
CREATE INDEX IF NOT EXISTS idx_domain_events_status ON ${"domain_events" /* DATABASE_TABLES.DOMAIN_EVENTS */}(status);
|
|
63
|
+
`);
|
|
64
|
+
await DBCursor.execAsync(`
|
|
65
|
+
CREATE INDEX IF NOT EXISTS idx_domain_events_correlation ON ${"domain_events" /* DATABASE_TABLES.DOMAIN_EVENTS */}(correlation_id);
|
|
66
|
+
`);
|
|
67
|
+
await DBCursor.execAsync(`
|
|
68
|
+
CREATE INDEX IF NOT EXISTS idx_domain_events_aggregate ON ${"domain_events" /* DATABASE_TABLES.DOMAIN_EVENTS */}(aggregate_id);
|
|
69
|
+
`);
|
|
70
|
+
await DBCursor.execAsync(`
|
|
71
|
+
CREATE INDEX IF NOT EXISTS idx_domain_events_name ON ${"domain_events" /* DATABASE_TABLES.DOMAIN_EVENTS */}(name);
|
|
72
|
+
`);
|
|
73
|
+
await DBCursor.execAsync(`
|
|
74
|
+
CREATE INDEX IF NOT EXISTS idx_domain_events_created ON ${"domain_events" /* DATABASE_TABLES.DOMAIN_EVENTS */}(created_at);
|
|
75
|
+
`);
|
|
76
|
+
}
|
|
77
|
+
async function createDomainEventsDeadLetterTable() {
|
|
78
|
+
await DBCursor.execAsync(`
|
|
79
|
+
CREATE TABLE IF NOT EXISTS ${"domain_events_dead_letter" /* DATABASE_TABLES.DOMAIN_EVENTS_DEAD_LETTER */} (
|
|
80
|
+
uuid TEXT PRIMARY KEY NOT NULL,
|
|
81
|
+
name TEXT NOT NULL,
|
|
82
|
+
label TEXT NOT NULL,
|
|
83
|
+
data TEXT NOT NULL,
|
|
84
|
+
requires_network INTEGER NOT NULL DEFAULT 0,
|
|
85
|
+
created_at TEXT NOT NULL,
|
|
86
|
+
attempts INTEGER NOT NULL DEFAULT 0,
|
|
87
|
+
error_message TEXT DEFAULT NULL,
|
|
88
|
+
failed_at TEXT NOT NULL,
|
|
89
|
+
aggregate_id TEXT DEFAULT NULL,
|
|
90
|
+
source_id TEXT DEFAULT NULL,
|
|
91
|
+
correlation_id TEXT DEFAULT NULL,
|
|
92
|
+
sequence INTEGER NOT NULL DEFAULT 0
|
|
93
|
+
);
|
|
94
|
+
`);
|
|
95
|
+
await DBCursor.execAsync(`
|
|
96
|
+
CREATE INDEX IF NOT EXISTS idx_dead_letter_correlation ON ${"domain_events_dead_letter" /* DATABASE_TABLES.DOMAIN_EVENTS_DEAD_LETTER */}(correlation_id);
|
|
97
|
+
`);
|
|
98
|
+
await DBCursor.execAsync(`
|
|
99
|
+
CREATE INDEX IF NOT EXISTS idx_dead_letter_name ON ${"domain_events_dead_letter" /* DATABASE_TABLES.DOMAIN_EVENTS_DEAD_LETTER */}(name);
|
|
100
|
+
`);
|
|
101
|
+
await DBCursor.execAsync(`
|
|
102
|
+
CREATE INDEX IF NOT EXISTS idx_dead_letter_failed ON ${"domain_events_dead_letter" /* DATABASE_TABLES.DOMAIN_EVENTS_DEAD_LETTER */}(failed_at);
|
|
103
|
+
`);
|
|
104
|
+
}
|
|
105
|
+
const MIGRATIONS = [
|
|
106
|
+
{ name: "settings" /* DATABASE_TABLES.SETTINGS */, migrationFn: createSettingsTable },
|
|
107
|
+
{ name: "event_queue" /* DATABASE_TABLES.EVENT_QUEUE */, migrationFn: createEventQueueTable },
|
|
108
|
+
{ name: "dead_letter_queue" /* DATABASE_TABLES.DEAD_LETTER_QUEUE */, migrationFn: createDeadLetterQueueTable },
|
|
109
|
+
{ name: "domain_events" /* DATABASE_TABLES.DOMAIN_EVENTS */, migrationFn: createDomainEventsTable },
|
|
110
|
+
{
|
|
111
|
+
name: "domain_events_dead_letter" /* DATABASE_TABLES.DOMAIN_EVENTS_DEAD_LETTER */,
|
|
112
|
+
migrationFn: createDomainEventsDeadLetterTable,
|
|
113
|
+
},
|
|
114
|
+
];
|
|
115
|
+
export default MIGRATIONS;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { EntityCollection, RemoteEntityCollection } from "../../domain/entity";
|
|
2
|
+
export declare class RepositoriesContainer {
|
|
3
|
+
private registry;
|
|
4
|
+
register(repositories: Record<string, any>): void;
|
|
5
|
+
get<T = any>(repositoryKey: string): T;
|
|
6
|
+
resolveRelation(repositoryKey: string, foreignKeyValue: number | string | number[] | string[], remote?: boolean): EntityCollection<any> | RemoteEntityCollection<any> | undefined;
|
|
7
|
+
}
|
|
8
|
+
export declare const repos: RepositoriesContainer;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { EntityCollection, RemoteEntityCollection } from "../../domain/entity";
|
|
2
|
+
import { DomainAppError } from "../../exceptions";
|
|
3
|
+
import { loggerRepositories } from "../../infrastructure/logger";
|
|
4
|
+
export class RepositoriesContainer {
|
|
5
|
+
registry = {};
|
|
6
|
+
register(repositories) {
|
|
7
|
+
this.registry = { ...this.registry, ...repositories };
|
|
8
|
+
}
|
|
9
|
+
get(repositoryKey) {
|
|
10
|
+
const repo = this.registry[repositoryKey];
|
|
11
|
+
if (!repo) {
|
|
12
|
+
throw new DomainAppError(`[RepositoryFacade] Repository not found: ${repositoryKey}`);
|
|
13
|
+
}
|
|
14
|
+
return repo;
|
|
15
|
+
}
|
|
16
|
+
resolveRelation(repositoryKey, foreignKeyValue, remote = false) {
|
|
17
|
+
const repo = this.registry[repositoryKey];
|
|
18
|
+
if (!repo) {
|
|
19
|
+
loggerRepositories.warn(`[RepositoryFacade] Repository not found: ${repositoryKey}`);
|
|
20
|
+
return Array.isArray(foreignKeyValue) ? new EntityCollection([]) : undefined;
|
|
21
|
+
}
|
|
22
|
+
if (Array.isArray(foreignKeyValue)) {
|
|
23
|
+
if (remote) {
|
|
24
|
+
return repo.findByRemoteIdsSync?.(foreignKeyValue) ?? new RemoteEntityCollection([]);
|
|
25
|
+
}
|
|
26
|
+
return repo.findByIdsSync?.(foreignKeyValue) ?? new EntityCollection([]);
|
|
27
|
+
}
|
|
28
|
+
if (remote) {
|
|
29
|
+
return repo.findByRemoteIdSync?.(foreignKeyValue) ?? undefined;
|
|
30
|
+
}
|
|
31
|
+
return repo.findByIdSync?.(foreignKeyValue) ?? undefined;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
export const repos = new RepositoriesContainer();
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Subscriber } from "../../domain/event_sourcing";
|
|
2
|
+
export interface SyncResult {
|
|
3
|
+
changed: boolean;
|
|
4
|
+
added: number;
|
|
5
|
+
removed: number;
|
|
6
|
+
}
|
|
7
|
+
export declare const QueueProcessor: {
|
|
8
|
+
start: () => void;
|
|
9
|
+
stop: () => void;
|
|
10
|
+
clearQueue: () => Promise<void>;
|
|
11
|
+
sync: (domains: Set<string>, isAuthenticated: boolean, subscribersByKey: Record<string, Subscriber[]>) => Promise<SyncResult>;
|
|
12
|
+
};
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { loggerQueueProcessor } from "../../infrastructure/logger";
|
|
2
|
+
import { EventBus } from "../../infrastructure/workers";
|
|
3
|
+
let isRunning = false;
|
|
4
|
+
let lastSyncState = null;
|
|
5
|
+
let currentSubscribers = new Set();
|
|
6
|
+
function statesAreEqual(a, b) {
|
|
7
|
+
if (!a)
|
|
8
|
+
return false;
|
|
9
|
+
if (a.isAuthenticated !== b.isAuthenticated)
|
|
10
|
+
return false;
|
|
11
|
+
if (a.domains.size !== b.domains.size)
|
|
12
|
+
return false;
|
|
13
|
+
for (const domain of a.domains) {
|
|
14
|
+
if (!b.domains.has(domain))
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
19
|
+
function calculateDesiredSubscribers(domains, isAuthenticated, subscribersByKey) {
|
|
20
|
+
const desired = new Set();
|
|
21
|
+
for (const domain of domains) {
|
|
22
|
+
const domainSubscribers = subscribersByKey[domain] ?? [];
|
|
23
|
+
for (const subscriber of domainSubscribers) {
|
|
24
|
+
if (isAuthenticated || !subscriber.requiresAuth) {
|
|
25
|
+
desired.add(subscriber);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return desired;
|
|
30
|
+
}
|
|
31
|
+
export const QueueProcessor = {
|
|
32
|
+
start: () => {
|
|
33
|
+
if (isRunning)
|
|
34
|
+
return;
|
|
35
|
+
isRunning = true;
|
|
36
|
+
EventBus.start();
|
|
37
|
+
loggerQueueProcessor.info("QueueProcessor started");
|
|
38
|
+
},
|
|
39
|
+
stop: () => {
|
|
40
|
+
EventBus.stop();
|
|
41
|
+
isRunning = false;
|
|
42
|
+
loggerQueueProcessor.info("QueueProcessor stopped");
|
|
43
|
+
},
|
|
44
|
+
clearQueue: async () => {
|
|
45
|
+
await EventBus.clearQueue();
|
|
46
|
+
},
|
|
47
|
+
sync: async (domains, isAuthenticated, subscribersByKey) => {
|
|
48
|
+
const newState = { domains: new Set(domains), isAuthenticated };
|
|
49
|
+
if (statesAreEqual(lastSyncState, newState)) {
|
|
50
|
+
return { changed: false, added: 0, removed: 0 };
|
|
51
|
+
}
|
|
52
|
+
EventBus.stop();
|
|
53
|
+
await EventBus.waitForIdle();
|
|
54
|
+
const desired = calculateDesiredSubscribers(domains, isAuthenticated, subscribersByKey);
|
|
55
|
+
let added = 0;
|
|
56
|
+
let removed = 0;
|
|
57
|
+
for (const subscriber of currentSubscribers) {
|
|
58
|
+
if (!desired.has(subscriber)) {
|
|
59
|
+
EventBus.off(subscriber);
|
|
60
|
+
removed++;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
for (const subscriber of desired) {
|
|
64
|
+
if (!currentSubscribers.has(subscriber)) {
|
|
65
|
+
EventBus.on(subscriber);
|
|
66
|
+
added++;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
currentSubscribers = desired;
|
|
70
|
+
lastSyncState = newState;
|
|
71
|
+
loggerQueueProcessor.info(`QueueProcessor.sync: +${added} -${removed} subscribers (domains=${[...domains].join(",")}, auth=${isAuthenticated})`);
|
|
72
|
+
EventBus.start();
|
|
73
|
+
return { changed: true, added, removed };
|
|
74
|
+
},
|
|
75
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { DomainEvent, Subscriber } from "../../domain/event_sourcing";
|
|
2
|
+
import { ActivateDomainEvent, DeactivateDomainEvent } from "../../domain/events";
|
|
3
|
+
export declare class ActivateDomainSubscriber extends Subscriber {
|
|
4
|
+
readonly requiresAuth = false;
|
|
5
|
+
listen: (typeof ActivateDomainEvent | typeof DeactivateDomainEvent)[];
|
|
6
|
+
process(event: DomainEvent): Promise<void>;
|
|
7
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Subscriber } from "../../domain/event_sourcing";
|
|
2
|
+
import { ActivateDomainEvent, DeactivateDomainEvent } from "../../domain/events";
|
|
3
|
+
import { orchestrator } from "../../framework/orchestrator";
|
|
4
|
+
export class ActivateDomainSubscriber extends Subscriber {
|
|
5
|
+
requiresAuth = false;
|
|
6
|
+
listen = [ActivateDomainEvent, DeactivateDomainEvent];
|
|
7
|
+
async process(event) {
|
|
8
|
+
if (event.name === ActivateDomainEvent.name) {
|
|
9
|
+
await orchestrator.enableDomain(event.domain);
|
|
10
|
+
}
|
|
11
|
+
else if (event.name === DeactivateDomainEvent.name) {
|
|
12
|
+
await orchestrator.disableDomain(event.domain);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { DomainEvent, Subscriber } from "../../domain/event_sourcing";
|
|
2
|
+
import { NewAppSettingsEvent } from "../../domain/events";
|
|
3
|
+
export declare class NewAppSettingsSubscriber extends Subscriber {
|
|
4
|
+
listen: (typeof NewAppSettingsEvent)[];
|
|
5
|
+
getEvent(event: DomainEvent): NewAppSettingsEvent;
|
|
6
|
+
process(event: NewAppSettingsEvent): Promise<void>;
|
|
7
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { SettingsRepository } from "../../adapters/repositories/setting.repository";
|
|
2
|
+
import { Subscriber } from "../../domain/event_sourcing";
|
|
3
|
+
import { NewAppSettingsEvent } from "../../domain/events";
|
|
4
|
+
import { loggerUseCases } from "../../infrastructure/logger";
|
|
5
|
+
export class NewAppSettingsSubscriber extends Subscriber {
|
|
6
|
+
listen = [NewAppSettingsEvent];
|
|
7
|
+
getEvent(event) {
|
|
8
|
+
return NewAppSettingsEvent.from(event);
|
|
9
|
+
}
|
|
10
|
+
async process(event) {
|
|
11
|
+
loggerUseCases.info(`Setting ${event.settings.length} settings`);
|
|
12
|
+
for (const setting of event.settings) {
|
|
13
|
+
await SettingsRepository.saveOneSetting(setting.key, setting.value);
|
|
14
|
+
}
|
|
15
|
+
loggerUseCases.info(`${event.settings.length} settings saved successfully`);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Subscriber } from "../../domain/event_sourcing";
|
|
2
|
+
import { PrintImageRequestedEvent } from "../../domain/events";
|
|
3
|
+
export declare class PrintImageSubscriber extends Subscriber {
|
|
4
|
+
readonly requiresAuth = false;
|
|
5
|
+
listen: (typeof PrintImageRequestedEvent)[];
|
|
6
|
+
process(event: PrintImageRequestedEvent): Promise<void>;
|
|
7
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Subscriber } from "../../domain/event_sourcing";
|
|
2
|
+
import { PrintImageRequestedEvent } from "../../domain/events";
|
|
3
|
+
import { DomainValidationError } from "../../exceptions";
|
|
4
|
+
import { printerService } from "../../services/printer.service";
|
|
5
|
+
export class PrintImageSubscriber extends Subscriber {
|
|
6
|
+
requiresAuth = false;
|
|
7
|
+
listen = [PrintImageRequestedEvent];
|
|
8
|
+
async process(event) {
|
|
9
|
+
if (!(await printerService.isConnected())) {
|
|
10
|
+
throw new DomainValidationError("No printer connected");
|
|
11
|
+
}
|
|
12
|
+
await printerService.printImageBase64(event.imageBase64);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Subscriber } from "../../domain/event_sourcing";
|
|
2
|
+
import { WebViewMessageReceivedEvent } from "../../domain/events";
|
|
3
|
+
export declare class ProcessWebViewMessageSubscriber extends Subscriber {
|
|
4
|
+
readonly requiresAuth = false;
|
|
5
|
+
listen: (typeof WebViewMessageReceivedEvent)[];
|
|
6
|
+
process(event: WebViewMessageReceivedEvent): Promise<void>;
|
|
7
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Subscriber } from "../../domain/event_sourcing";
|
|
2
|
+
import { PrintImageRequestedEvent, WebViewMessageReceivedEvent, } from "../../domain/events";
|
|
3
|
+
import { DomainValidationError } from "../../exceptions";
|
|
4
|
+
import { EventBus } from "../../infrastructure/workers";
|
|
5
|
+
import { webViewService } from "../../services/webview.service";
|
|
6
|
+
export class ProcessWebViewMessageSubscriber extends Subscriber {
|
|
7
|
+
requiresAuth = false;
|
|
8
|
+
listen = [WebViewMessageReceivedEvent];
|
|
9
|
+
async process(event) {
|
|
10
|
+
const parsed = webViewService.parseMessage(event.raw);
|
|
11
|
+
if (!parsed) {
|
|
12
|
+
throw new DomainValidationError("Invalid WebView message format");
|
|
13
|
+
}
|
|
14
|
+
if (webViewService.isPrintImage(parsed)) {
|
|
15
|
+
await EventBus.publishSync(PrintImageRequestedEvent.create({
|
|
16
|
+
imageBase64: parsed.image,
|
|
17
|
+
width: parsed.width,
|
|
18
|
+
height: parsed.height,
|
|
19
|
+
title: parsed.metadata.title,
|
|
20
|
+
}));
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { DomainModule } from "../../framework/domain_module";
|
|
2
|
+
import { type ThemeTokens } from "@sincpro/mobile-ui/theme";
|
|
3
|
+
import { type ComponentType, type ReactNode } from "react";
|
|
4
|
+
type ProviderComponent = ComponentType<{
|
|
5
|
+
children: ReactNode;
|
|
6
|
+
}>;
|
|
7
|
+
export interface AppShellConfig {
|
|
8
|
+
domains: DomainModule[];
|
|
9
|
+
ui: Record<string, ComponentType>;
|
|
10
|
+
activeDomain: string;
|
|
11
|
+
providers?: ProviderComponent[];
|
|
12
|
+
theme?: ThemeTokens;
|
|
13
|
+
}
|
|
14
|
+
export declare function createAppShell(config: AppShellConfig): ComponentType;
|
|
15
|
+
export {};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "nativewind/jsx-runtime";
|
|
2
|
+
import { createApp } from "../../framework/createApp";
|
|
3
|
+
import { ToastHost } from "../../infrastructure/ui/ToastHost";
|
|
4
|
+
import { setActiveTheme, themeToVars } from "@sincpro/mobile-ui/theme";
|
|
5
|
+
import { useAppFonts } from "@sincpro/mobile-ui/theme/typography";
|
|
6
|
+
import * as SplashScreen from "expo-splash-screen";
|
|
7
|
+
import { vars } from "nativewind";
|
|
8
|
+
import { useEffect, useState } from "react";
|
|
9
|
+
import { View } from "react-native";
|
|
10
|
+
import { GestureHandlerRootView } from "react-native-gesture-handler";
|
|
11
|
+
import { KeyboardProvider } from "react-native-keyboard-controller";
|
|
12
|
+
import { initialWindowMetrics, SafeAreaProvider } from "react-native-safe-area-context";
|
|
13
|
+
import { NativeRouter } from "react-router-native";
|
|
14
|
+
import { CommonProvider } from "./common_provider";
|
|
15
|
+
import { ActiveDomainApp, DomainSwitcherProvider } from "./domain_switcher";
|
|
16
|
+
function withProviders(providers, children) {
|
|
17
|
+
return providers.reduceRight((acc, Provider) => _jsx(Provider, { children: acc }), children);
|
|
18
|
+
}
|
|
19
|
+
export function createAppShell(config) {
|
|
20
|
+
const apps = config.domains
|
|
21
|
+
.filter((module) => Boolean(config.ui[module.key]))
|
|
22
|
+
.map((module) => ({
|
|
23
|
+
key: module.key,
|
|
24
|
+
name: module.name,
|
|
25
|
+
component: config.ui[module.key],
|
|
26
|
+
}));
|
|
27
|
+
const providers = config.providers ?? [];
|
|
28
|
+
if (config.theme) {
|
|
29
|
+
setActiveTheme(config.theme);
|
|
30
|
+
}
|
|
31
|
+
const themeStyle = config.theme ? vars(themeToVars(config.theme)) : undefined;
|
|
32
|
+
return function AppShell() {
|
|
33
|
+
const [isReady, setIsReady] = useState(false);
|
|
34
|
+
const fontsLoaded = useAppFonts();
|
|
35
|
+
useEffect(() => {
|
|
36
|
+
let active = true;
|
|
37
|
+
createApp({ domains: config.domains }).then(() => {
|
|
38
|
+
if (active)
|
|
39
|
+
setIsReady(true);
|
|
40
|
+
});
|
|
41
|
+
return () => {
|
|
42
|
+
active = false;
|
|
43
|
+
};
|
|
44
|
+
}, []);
|
|
45
|
+
useEffect(() => {
|
|
46
|
+
SplashScreen.preventAutoHideAsync().catch(() => { });
|
|
47
|
+
}, []);
|
|
48
|
+
useEffect(() => {
|
|
49
|
+
if (fontsLoaded && isReady) {
|
|
50
|
+
SplashScreen.hideAsync().catch(() => { });
|
|
51
|
+
}
|
|
52
|
+
}, [fontsLoaded, isReady]);
|
|
53
|
+
if (!isReady || !fontsLoaded) {
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
return (_jsx(GestureHandlerRootView, { style: { flex: 1 }, children: _jsx(View, { className: "flex-1", style: themeStyle, children: _jsx(SafeAreaProvider, { initialMetrics: initialWindowMetrics, children: _jsx(KeyboardProvider, { children: _jsxs(CommonProvider, { children: [withProviders(providers, _jsx(DomainSwitcherProvider, { apps: apps, initialDomain: config.activeDomain, children: _jsx(NativeRouter, { children: _jsx(ActiveDomainApp, {}) }) })), _jsx(ToastHost, {})] }) }) }) }) }));
|
|
57
|
+
};
|
|
58
|
+
}
|