@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
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { heldEntities, relations } from "../../domain/entity/relations";
|
|
2
|
+
import { ChecksFailed, DomainValidationError } from "../../exceptions";
|
|
3
|
+
const CHECK = Symbol("check");
|
|
4
|
+
export function check(watches) {
|
|
5
|
+
return function (_target, _key, descriptor) {
|
|
6
|
+
descriptor.value[CHECK] = watches;
|
|
7
|
+
return descriptor;
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
function watchedNames(watches, entity) {
|
|
11
|
+
const names = [];
|
|
12
|
+
const proxy = new Proxy(entity, {
|
|
13
|
+
get(target, prop, receiver) {
|
|
14
|
+
if (typeof prop === "string" && prop !== "constructor")
|
|
15
|
+
names.push(prop);
|
|
16
|
+
return Reflect.get(target, prop, receiver);
|
|
17
|
+
},
|
|
18
|
+
});
|
|
19
|
+
watches(proxy);
|
|
20
|
+
return names;
|
|
21
|
+
}
|
|
22
|
+
function rulesOf(entity) {
|
|
23
|
+
const seen = new Set();
|
|
24
|
+
const rules = [];
|
|
25
|
+
let proto = Object.getPrototypeOf(entity);
|
|
26
|
+
while (proto && proto !== Object.prototype) {
|
|
27
|
+
for (const key of Object.getOwnPropertyNames(proto)) {
|
|
28
|
+
if (seen.has(key))
|
|
29
|
+
continue;
|
|
30
|
+
const value = proto[key];
|
|
31
|
+
const watches = value?.[CHECK];
|
|
32
|
+
if (!watches || typeof value !== "function")
|
|
33
|
+
continue;
|
|
34
|
+
seen.add(key);
|
|
35
|
+
rules.push({ name: key, watches, run: value.bind(entity) });
|
|
36
|
+
}
|
|
37
|
+
proto = Object.getPrototypeOf(proto);
|
|
38
|
+
}
|
|
39
|
+
return rules;
|
|
40
|
+
}
|
|
41
|
+
function failureOf(rule, run) {
|
|
42
|
+
try {
|
|
43
|
+
run();
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
if (error instanceof DomainValidationError) {
|
|
48
|
+
return { rule, message: error.message };
|
|
49
|
+
}
|
|
50
|
+
throw error;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
export function checkWarnings(entity, touched) {
|
|
54
|
+
return collect(entity, [], new Set(touched));
|
|
55
|
+
}
|
|
56
|
+
export function assertChecks(entity) {
|
|
57
|
+
const failures = collect(entity, [], null);
|
|
58
|
+
if (failures.length > 0)
|
|
59
|
+
throw new ChecksFailed(failures);
|
|
60
|
+
}
|
|
61
|
+
function collect(entity, path, touched) {
|
|
62
|
+
const failures = [];
|
|
63
|
+
for (const rule of rulesOf(entity)) {
|
|
64
|
+
if (touched) {
|
|
65
|
+
const fields = watchedNames(rule.watches, entity);
|
|
66
|
+
const reached = fields.some((field) => touched.has(field)) ||
|
|
67
|
+
(path.length > 0 && touched.has(path[0]));
|
|
68
|
+
if (!reached)
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
const failure = failureOf(rule.name, rule.run);
|
|
72
|
+
if (failure)
|
|
73
|
+
failures.push({ ...failure, path });
|
|
74
|
+
}
|
|
75
|
+
const record = entity;
|
|
76
|
+
for (const relation of relations(entity)) {
|
|
77
|
+
heldEntities(record[relation.field]).forEach((child, index) => {
|
|
78
|
+
failures.push(...collect(child, [...path, relation.field, String(index)], touched));
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
return failures;
|
|
82
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { type DomainEvent, type DomainEventClass, type EventData } from "../../domain/
|
|
1
|
+
import { type DomainEvent, type DomainEventClass, type EventData } from "../../domain/events/domain_event";
|
|
2
|
+
import { IntegrationEvent } from "../../domain/events/integration_event";
|
|
2
3
|
import { IValueObject, ValueObject } from "./value_object";
|
|
3
4
|
export declare enum ERemoteState {
|
|
4
5
|
SYNCED = "SYNCED",
|
|
@@ -9,31 +10,32 @@ export interface IRemote {
|
|
|
9
10
|
remoteId?: number;
|
|
10
11
|
remoteRef?: string;
|
|
11
12
|
remoteState: ERemoteState;
|
|
13
|
+
ackedVersion: number;
|
|
14
|
+
readonly isDirty: boolean;
|
|
12
15
|
fromRemoteDTO: (data: any) => this;
|
|
13
16
|
mergeWithRemote: (data: this) => void;
|
|
14
17
|
remotePayload(): any;
|
|
15
18
|
}
|
|
16
|
-
export interface
|
|
17
|
-
addDomainEvent<T extends DomainEvent>(EventClass: DomainEventClass<T>, payload?: EventData<T>): string;
|
|
18
|
-
addDomainEventWithEntity<T extends DomainEvent>(EventClass: DomainEventClass<T>): string;
|
|
19
|
-
getDomainEvents(): readonly DomainEvent[];
|
|
20
|
-
clearDomainEvents(): void;
|
|
21
|
-
publishAllDomainEvents(): Promise<void>;
|
|
22
|
-
publishAllDomainEventsSync(): Promise<void>;
|
|
23
|
-
publishDomainEvent<T extends DomainEvent>(EventClass: DomainEventClass<T>, payload: Partial<T>): Promise<void>;
|
|
24
|
-
publishDomainEventSync<T extends DomainEvent>(EventClass: DomainEventClass<T>, payload: Partial<T>): Promise<void>;
|
|
25
|
-
publishDomainEventWithEntity<T extends DomainEvent>(EventClass: DomainEventClass<T>): Promise<void>;
|
|
26
|
-
publishDomainEventWithEntitySync<T extends DomainEvent>(EventClass: DomainEventClass<T>): Promise<void>;
|
|
27
|
-
publishEventWith<T extends DomainEvent>(EventClass: DomainEventClass<T>, selector: (entity: this) => Partial<T>): Promise<void>;
|
|
28
|
-
publishEventWithSync<T extends DomainEvent>(EventClass: DomainEventClass<T>, selector: (entity: this) => Partial<T>): Promise<void>;
|
|
29
|
-
copyDomainEventsFrom(source: Entity): void;
|
|
30
|
-
}
|
|
31
|
-
export interface IEntity extends IEventSourced, IValueObject {
|
|
19
|
+
export interface IEntity extends IValueObject {
|
|
32
20
|
uuid: string;
|
|
33
21
|
name?: string;
|
|
34
22
|
eventIds: string[];
|
|
23
|
+
createdAt: string;
|
|
24
|
+
updatedAt: string | null;
|
|
25
|
+
version: number;
|
|
26
|
+
readonly isNew: boolean;
|
|
35
27
|
equals(other: IEntity): boolean;
|
|
36
28
|
clone(): this;
|
|
29
|
+
record<C extends DomainEventClass<DomainEvent>>(EventClass: C, payload?: EventData<InstanceType<C>>): string;
|
|
30
|
+
recordEntity<C extends DomainEventClass<DomainEvent>>(EventClass: C): string;
|
|
31
|
+
recordedEvents(): readonly DomainEvent[];
|
|
32
|
+
pullEvents(): DomainEvent[];
|
|
33
|
+
releaseDeliverable(): IntegrationEvent[];
|
|
34
|
+
restoreRecorded(events: readonly DomainEvent[]): void;
|
|
35
|
+
copyRecordedFrom(source: Entity): void;
|
|
36
|
+
replaceRecorded(events: readonly DomainEvent[]): void;
|
|
37
|
+
noteHeld(): void;
|
|
38
|
+
heldIds(field: string): readonly string[];
|
|
37
39
|
}
|
|
38
40
|
export interface IEntityRemote extends IEntity, IRemote {
|
|
39
41
|
}
|
|
@@ -41,11 +43,16 @@ export declare class Entity extends ValueObject implements IEntity {
|
|
|
41
43
|
uuid: string;
|
|
42
44
|
name?: string;
|
|
43
45
|
eventIds: string[];
|
|
44
|
-
|
|
45
|
-
|
|
46
|
+
createdAt: string;
|
|
47
|
+
updatedAt: string | null;
|
|
48
|
+
version: number;
|
|
49
|
+
protected _recordedEvents: DomainEvent[];
|
|
50
|
+
protected _correlationId: string | null;
|
|
51
|
+
private _held;
|
|
46
52
|
protected readonly REPOSITORY: string | null;
|
|
47
53
|
protected constructor();
|
|
48
54
|
static obj<T>(data?: Partial<T>): T;
|
|
55
|
+
get isNew(): boolean;
|
|
49
56
|
/**
|
|
50
57
|
* Resolves domain events collection in runtime from repository.
|
|
51
58
|
* Uses @mapped decorator to automatically query events by eventIds.
|
|
@@ -66,24 +73,23 @@ export declare class Entity extends ValueObject implements IEntity {
|
|
|
66
73
|
*/
|
|
67
74
|
reload(): Promise<this>;
|
|
68
75
|
equals(other: any): boolean;
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
publishEventWith<T extends DomainEvent>(EventClass: DomainEventClass<T>, selector: (entity: this) => Partial<T>): Promise<void>;
|
|
81
|
-
publishEventWithSync<T extends DomainEvent>(EventClass: DomainEventClass<T>, selector: (entity: this) => Partial<T>): Promise<void>;
|
|
76
|
+
record<C extends DomainEventClass<DomainEvent>>(EventClass: C, payload?: EventData<InstanceType<C>>): string;
|
|
77
|
+
recordEntity<C extends DomainEventClass<DomainEvent>>(EventClass: C): string;
|
|
78
|
+
recordedEvents(): readonly DomainEvent[];
|
|
79
|
+
pullEvents(): DomainEvent[];
|
|
80
|
+
releaseDeliverable(): IntegrationEvent[];
|
|
81
|
+
restoreRecorded(events: readonly DomainEvent[]): void;
|
|
82
|
+
replaceRecorded(events: readonly DomainEvent[]): void;
|
|
83
|
+
copyRecordedFrom(source: Entity): void;
|
|
84
|
+
noteHeld(): void;
|
|
85
|
+
heldIds(field: string): readonly string[];
|
|
86
|
+
private stageDomainEvent;
|
|
82
87
|
}
|
|
83
88
|
export declare class RemoteEntity extends Entity implements IRemote {
|
|
84
89
|
remoteId?: number;
|
|
85
90
|
remoteRef?: string;
|
|
86
91
|
remoteState: ERemoteState;
|
|
92
|
+
ackedVersion: number;
|
|
87
93
|
protected constructor();
|
|
88
94
|
static fromRemoteDTO(data: any): RemoteEntity;
|
|
89
95
|
fromRemoteDTO(data: any): this;
|
|
@@ -101,6 +107,7 @@ export declare class RemoteEntity extends Entity implements IRemote {
|
|
|
101
107
|
* const refreshed = await product.reloadByRemoteId();
|
|
102
108
|
*/
|
|
103
109
|
reloadByRemoteId(): Promise<this>;
|
|
110
|
+
get isDirty(): boolean;
|
|
104
111
|
mergeWithRemote(data: this): void;
|
|
105
112
|
remotePayload(): any;
|
|
106
113
|
markAsSynced(): void;
|
|
@@ -7,12 +7,13 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
7
7
|
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
8
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
9
|
};
|
|
10
|
-
import {
|
|
10
|
+
import { IntegrationEvent } from "../../domain/events/integration_event";
|
|
11
|
+
import { ECommonRepository } from "../../domain/repositories/catalog";
|
|
11
12
|
import { DomainValidationError } from "../../exceptions";
|
|
12
13
|
import { mapped, resolveEntity } from "../../infrastructure/database";
|
|
13
14
|
import { generateUUID } from "../../infrastructure/database/utils";
|
|
14
15
|
import { loggerQueueProcessor } from "../../infrastructure/logger";
|
|
15
|
-
import {
|
|
16
|
+
import { heldEntities, relations } from "./relations";
|
|
16
17
|
import { ValueObject } from "./value_object";
|
|
17
18
|
export var ERemoteState;
|
|
18
19
|
(function (ERemoteState) {
|
|
@@ -24,8 +25,12 @@ export class Entity extends ValueObject {
|
|
|
24
25
|
uuid;
|
|
25
26
|
name;
|
|
26
27
|
eventIds = [];
|
|
27
|
-
|
|
28
|
-
|
|
28
|
+
createdAt = "";
|
|
29
|
+
updatedAt = null;
|
|
30
|
+
version = 0;
|
|
31
|
+
_recordedEvents = [];
|
|
32
|
+
_correlationId = null;
|
|
33
|
+
_held = {};
|
|
29
34
|
REPOSITORY = null;
|
|
30
35
|
constructor() {
|
|
31
36
|
super();
|
|
@@ -38,8 +43,17 @@ export class Entity extends ValueObject {
|
|
|
38
43
|
if (!instance.uuid) {
|
|
39
44
|
instance.uuid = generateUUID();
|
|
40
45
|
}
|
|
46
|
+
if (!instance.createdAt) {
|
|
47
|
+
instance.createdAt = new Date().toISOString();
|
|
48
|
+
}
|
|
49
|
+
if (typeof instance.version !== "number") {
|
|
50
|
+
instance.version = 0;
|
|
51
|
+
}
|
|
41
52
|
return instance;
|
|
42
53
|
}
|
|
54
|
+
get isNew() {
|
|
55
|
+
return this.version === 0;
|
|
56
|
+
}
|
|
43
57
|
/**
|
|
44
58
|
* Resolves domain events collection in runtime from repository.
|
|
45
59
|
* Uses @mapped decorator to automatically query events by eventIds.
|
|
@@ -73,118 +87,81 @@ export class Entity extends ValueObject {
|
|
|
73
87
|
return false;
|
|
74
88
|
return this.uuid === other.uuid;
|
|
75
89
|
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
90
|
+
record(EventClass, payload) {
|
|
91
|
+
return this.stageDomainEvent(EventClass.create(payload));
|
|
92
|
+
}
|
|
93
|
+
recordEntity(EventClass) {
|
|
94
|
+
return this.stageDomainEvent(EventClass.create({ record: this }));
|
|
95
|
+
}
|
|
96
|
+
recordedEvents() {
|
|
97
|
+
return this._recordedEvents.map((event) => event.clone());
|
|
98
|
+
}
|
|
99
|
+
pullEvents() {
|
|
100
|
+
const events = this._recordedEvents;
|
|
101
|
+
this._recordedEvents = [];
|
|
102
|
+
this._correlationId = null;
|
|
103
|
+
return events;
|
|
104
|
+
}
|
|
105
|
+
releaseDeliverable() {
|
|
106
|
+
const kept = [];
|
|
107
|
+
const released = [];
|
|
108
|
+
for (const event of this._recordedEvents) {
|
|
109
|
+
if (event instanceof IntegrationEvent)
|
|
110
|
+
released.push(event);
|
|
111
|
+
else
|
|
112
|
+
kept.push(event);
|
|
82
113
|
}
|
|
83
|
-
|
|
84
|
-
|
|
114
|
+
this._recordedEvents = kept;
|
|
115
|
+
if (kept.length === 0)
|
|
116
|
+
this._correlationId = null;
|
|
117
|
+
if (released.length > 0) {
|
|
118
|
+
const gone = new Set(released.map((event) => event.uuid));
|
|
119
|
+
this.eventIds = this.eventIds.filter((id) => !gone.has(id));
|
|
85
120
|
}
|
|
86
|
-
|
|
87
|
-
.withAggregateId(this.uuid)
|
|
88
|
-
.withCorrelationId(this._correlationIdV2)
|
|
89
|
-
.withSequence(this._domainEventsV2.length + 1);
|
|
90
|
-
this._domainEventsV2.push(event);
|
|
91
|
-
this.eventIds.push(event.uuid);
|
|
92
|
-
return event.uuid;
|
|
121
|
+
return released;
|
|
93
122
|
}
|
|
94
|
-
|
|
95
|
-
const event
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
return existingEvent.uuid;
|
|
100
|
-
}
|
|
101
|
-
if (!this._correlationIdV2) {
|
|
102
|
-
this._correlationIdV2 = generateUUID();
|
|
103
|
-
}
|
|
104
|
-
event
|
|
105
|
-
.withAggregateId(this.uuid)
|
|
106
|
-
.withCorrelationId(this._correlationIdV2)
|
|
107
|
-
.withSequence(this._domainEventsV2.length + 1);
|
|
108
|
-
this._domainEventsV2.push(event);
|
|
109
|
-
this.eventIds.push(event.uuid);
|
|
110
|
-
return event.uuid;
|
|
111
|
-
}
|
|
112
|
-
getDomainEvents() {
|
|
113
|
-
return this._domainEventsV2.map((e) => e.clone());
|
|
114
|
-
}
|
|
115
|
-
copyDomainEventsFrom(source) {
|
|
116
|
-
for (const event of source.getDomainEvents()) {
|
|
117
|
-
const clonedEvent = event
|
|
118
|
-
.clone()
|
|
119
|
-
.withAggregateId(this.uuid)
|
|
120
|
-
.withCorrelationId(this._correlationIdV2 || generateUUID())
|
|
121
|
-
.withSequence(this._domainEventsV2.length + 1);
|
|
122
|
-
this._domainEventsV2.push(clonedEvent);
|
|
123
|
-
this.eventIds.push(clonedEvent.uuid);
|
|
123
|
+
restoreRecorded(events) {
|
|
124
|
+
for (const event of events) {
|
|
125
|
+
this._recordedEvents.push(event);
|
|
126
|
+
if (!this.eventIds.includes(event.uuid))
|
|
127
|
+
this.eventIds.push(event.uuid);
|
|
124
128
|
}
|
|
125
129
|
}
|
|
126
|
-
|
|
127
|
-
this.
|
|
128
|
-
this._correlationIdV2 = null;
|
|
130
|
+
replaceRecorded(events) {
|
|
131
|
+
this._recordedEvents = [...events];
|
|
129
132
|
}
|
|
130
|
-
|
|
131
|
-
const
|
|
132
|
-
|
|
133
|
-
loggerQueueProcessor.info(`class ${this.constructor.name} - Publishing total [${events.length}] V2 domain events for entity '${this.uuid}'`);
|
|
133
|
+
copyRecordedFrom(source) {
|
|
134
|
+
for (const event of source.recordedEvents()) {
|
|
135
|
+
this.stageDomainEvent(event.clone());
|
|
134
136
|
}
|
|
135
|
-
for (const event of events) {
|
|
136
|
-
await EventBus.publish(event);
|
|
137
|
-
}
|
|
138
|
-
this.clearDomainEvents();
|
|
139
137
|
}
|
|
140
|
-
|
|
141
|
-
const
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
}
|
|
145
|
-
const errors = [];
|
|
146
|
-
for (const event of events) {
|
|
147
|
-
try {
|
|
148
|
-
await EventBus.publishSync(event);
|
|
149
|
-
}
|
|
150
|
-
catch (error) {
|
|
151
|
-
loggerQueueProcessor.warn(`class ${this.constructor.name} - Error publishing V2 domain event '${event.name}' for entity '${this.uuid}': ${error.message}`);
|
|
152
|
-
errors.push(error);
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
this.clearDomainEvents();
|
|
156
|
-
if (errors.length > 0) {
|
|
157
|
-
const errorList = errors.map((e) => ` - ${e.message}`).join("\n");
|
|
158
|
-
throw new Error(`Errors occurred while publishing V2 domain events synchronously:\n${errorList}`);
|
|
138
|
+
noteHeld() {
|
|
139
|
+
const held = {};
|
|
140
|
+
for (const relation of relations(this)) {
|
|
141
|
+
held[relation.field] = heldEntities(this[relation.field]).map((child) => child.uuid);
|
|
159
142
|
}
|
|
143
|
+
this._held = held;
|
|
160
144
|
}
|
|
161
|
-
|
|
162
|
-
this.
|
|
163
|
-
await this.publishAllDomainEvents();
|
|
164
|
-
}
|
|
165
|
-
async publishDomainEventSync(EventClass, payload) {
|
|
166
|
-
this.addDomainEvent(EventClass, payload);
|
|
167
|
-
await this.publishAllDomainEventsSync();
|
|
168
|
-
}
|
|
169
|
-
async publishDomainEventWithEntity(EventClass) {
|
|
170
|
-
this.addDomainEventWithEntity(EventClass);
|
|
171
|
-
await this.publishAllDomainEvents();
|
|
172
|
-
}
|
|
173
|
-
async publishDomainEventWithEntitySync(EventClass) {
|
|
174
|
-
this.addDomainEventWithEntity(EventClass);
|
|
175
|
-
await this.publishAllDomainEventsSync();
|
|
176
|
-
}
|
|
177
|
-
async publishEventWith(EventClass, selector) {
|
|
178
|
-
const event = EventClass.create(selector(this));
|
|
179
|
-
event.withAggregateId(this.uuid);
|
|
180
|
-
this._domainEventsV2.push(event);
|
|
181
|
-
await this.publishAllDomainEvents();
|
|
145
|
+
heldIds(field) {
|
|
146
|
+
return this._held[field] ?? [];
|
|
182
147
|
}
|
|
183
|
-
|
|
184
|
-
const
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
148
|
+
stageDomainEvent(event) {
|
|
149
|
+
const existingEvent = this._recordedEvents.find((recorded) => recorded.hasSameBusinessPayload(event));
|
|
150
|
+
if (existingEvent) {
|
|
151
|
+
loggerQueueProcessor.warn(`class ${this.constructor.name} - Event '${event.name}' is already recorded for '${this.uuid}' with the same payload. Skipping.`);
|
|
152
|
+
return existingEvent.uuid;
|
|
153
|
+
}
|
|
154
|
+
if (!this._correlationId) {
|
|
155
|
+
this._correlationId = generateUUID();
|
|
156
|
+
}
|
|
157
|
+
event
|
|
158
|
+
.withEntityType(this.constructor.name)
|
|
159
|
+
.withAggregateId(this.uuid)
|
|
160
|
+
.withSequence(this._recordedEvents.length + 1)
|
|
161
|
+
.applyChain(this._correlationId);
|
|
162
|
+
this._recordedEvents.push(event);
|
|
163
|
+
this.eventIds.push(event.uuid);
|
|
164
|
+
return event.uuid;
|
|
188
165
|
}
|
|
189
166
|
}
|
|
190
167
|
__decorate([
|
|
@@ -196,6 +173,7 @@ export class RemoteEntity extends Entity {
|
|
|
196
173
|
remoteId;
|
|
197
174
|
remoteRef;
|
|
198
175
|
remoteState = ERemoteState.PENDING;
|
|
176
|
+
ackedVersion = 0;
|
|
199
177
|
constructor() {
|
|
200
178
|
super();
|
|
201
179
|
}
|
|
@@ -224,12 +202,23 @@ export class RemoteEntity extends Entity {
|
|
|
224
202
|
}
|
|
225
203
|
return (await resolveEntity(this.REPOSITORY, this.remoteId, true));
|
|
226
204
|
}
|
|
205
|
+
get isDirty() {
|
|
206
|
+
return this.version === 0 || this.version !== this.ackedVersion;
|
|
207
|
+
}
|
|
227
208
|
mergeWithRemote(data) {
|
|
228
209
|
const preservedUuid = this.uuid;
|
|
229
210
|
const preservedEventIds = this.eventIds;
|
|
211
|
+
const preservedVersion = this.version;
|
|
212
|
+
const preservedAcked = this.ackedVersion;
|
|
213
|
+
const preservedState = this.remoteState;
|
|
214
|
+
const preservedCreatedAt = this.createdAt;
|
|
230
215
|
Object.assign(this, data);
|
|
231
216
|
this.uuid = preservedUuid;
|
|
232
217
|
this.eventIds = preservedEventIds;
|
|
218
|
+
this.version = preservedVersion;
|
|
219
|
+
this.ackedVersion = preservedAcked;
|
|
220
|
+
this.remoteState = preservedState;
|
|
221
|
+
this.createdAt = preservedCreatedAt;
|
|
233
222
|
}
|
|
234
223
|
remotePayload() {
|
|
235
224
|
throw new Error(`${this.name}.remotePayload debe ser implementado`);
|
|
@@ -1,15 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { type DocumentCriteria } from "../../domain/database/criteria";
|
|
2
|
+
import { type DomainEventClass, type EventData } from "../../domain/events/domain_event";
|
|
3
|
+
import { type IntegrationEvent } from "../../domain/events/integration_event";
|
|
2
4
|
import { type Entity, type RemoteEntity } from "./entity";
|
|
3
5
|
import { ValueObject } from "./value_object";
|
|
4
|
-
export type CriteriaOperator = "=" | "!=" | "in" | "not_in" | "like" | ">" | "<" | ">=" | "<=";
|
|
5
|
-
export interface ICriteria<T = any> {
|
|
6
|
-
field: keyof T;
|
|
7
|
-
operator: CriteriaOperator;
|
|
8
|
-
value: any;
|
|
9
|
-
}
|
|
10
6
|
/**
|
|
11
|
-
*
|
|
12
|
-
* Implements IEventSourced for domain event publishing and provides functional operations.
|
|
7
|
+
* Collection of aggregates. Records integration events for the set and offers the list operations.
|
|
13
8
|
*
|
|
14
9
|
* @example
|
|
15
10
|
* const collection = new EntityCollection([priceList1, priceList2]);
|
|
@@ -25,15 +20,15 @@ export interface ICriteria<T = any> {
|
|
|
25
20
|
* const union = collection1.union(collection2);
|
|
26
21
|
* const common = collection1.intersect(collection2);
|
|
27
22
|
*
|
|
28
|
-
* //
|
|
29
|
-
*
|
|
23
|
+
* // Record an integration event for the set
|
|
24
|
+
* collection.record(PriceListsSynced, { count: collection.length });
|
|
30
25
|
*/
|
|
31
26
|
export declare class EntityCollection<T extends Entity> extends ValueObject {
|
|
32
27
|
uuid: string;
|
|
33
28
|
eventIds: string[];
|
|
34
29
|
private entities;
|
|
35
|
-
private
|
|
36
|
-
private
|
|
30
|
+
private _recordedEvents;
|
|
31
|
+
private _correlationId;
|
|
37
32
|
constructor(entities?: T[]);
|
|
38
33
|
/** Factory method for creating instances - override in subclasses */
|
|
39
34
|
protected createInstance(entities: T[]): this;
|
|
@@ -236,16 +231,11 @@ export declare class EntityCollection<T extends Entity> extends ValueObject {
|
|
|
236
231
|
* const entity = byUuid.get("abc-123"); // Fast lookup
|
|
237
232
|
*/
|
|
238
233
|
toMapByUuid(): Map<string, T>;
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
publishAllDomainEventsSync(): Promise<void>;
|
|
245
|
-
publishDomainEvent<E extends DomainEvent>(EventClass: DomainEventClass<E>, payload: Partial<E>): Promise<void>;
|
|
246
|
-
publishDomainEventSync<E extends DomainEvent>(EventClass: DomainEventClass<E>, payload: Partial<E>): Promise<void>;
|
|
247
|
-
publishDomainEventWithEntities<E extends DomainEvent>(EventClass: DomainEventClass<E>): Promise<void>;
|
|
248
|
-
publishDomainEventWithEntitiesSync<E extends DomainEvent>(EventClass: DomainEventClass<E>): Promise<void>;
|
|
234
|
+
record<C extends DomainEventClass<IntegrationEvent>>(EventClass: C, payload: EventData<InstanceType<C>>): string;
|
|
235
|
+
recordEntities<C extends DomainEventClass<IntegrationEvent>>(EventClass: C): string;
|
|
236
|
+
private stageDomainEvent;
|
|
237
|
+
recordedEvents(): readonly IntegrationEvent[];
|
|
238
|
+
pullEvents(): IntegrationEvent[];
|
|
249
239
|
/**
|
|
250
240
|
* Serializes collection as array of entity JSONs.
|
|
251
241
|
* Collection is a manager, not an entity, so it serializes as pure entity list.
|
|
@@ -255,14 +245,9 @@ export declare class EntityCollection<T extends Entity> extends ValueObject {
|
|
|
255
245
|
*/
|
|
256
246
|
asJSON(pretty?: boolean): string;
|
|
257
247
|
/**
|
|
258
|
-
*
|
|
259
|
-
* @example
|
|
260
|
-
* const filtered = collection.findByCriteria([
|
|
261
|
-
* { field: 'customerId', operator: '=', value: 123 },
|
|
262
|
-
* { field: 'state', operator: 'in', value: ['draft', 'posted'] }
|
|
263
|
-
* ]);
|
|
248
|
+
* The entities that answer a criteria. The filter is `selection`.
|
|
264
249
|
*/
|
|
265
|
-
findByCriteria(criteria:
|
|
250
|
+
findByCriteria(criteria: DocumentCriteria<T>): this;
|
|
266
251
|
/**
|
|
267
252
|
* Deserializes collection from array of entity JSONs.
|
|
268
253
|
* Collection is a manager, not an entity, so it deserializes from pure entity list.
|