@cratis/chronicle 6.48.0 → 6.49.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/EventStore.ts +8 -2
- package/IEventStore.ts +8 -0
- package/artifacts/DefaultClientArtifactsProvider.ts +5 -0
- package/artifacts/IClientArtifactsProvider.ts +3 -0
- package/connection/ChronicleConnection.ts +6 -0
- package/connection/ChronicleServices.ts +2 -0
- package/dist/EventStore.d.ts +2 -0
- package/dist/EventStore.d.ts.map +1 -1
- package/dist/EventStore.js +7 -2
- package/dist/EventStore.js.map +1 -1
- package/dist/IEventStore.d.ts +7 -0
- package/dist/IEventStore.d.ts.map +1 -1
- package/dist/artifacts/DefaultClientArtifactsProvider.d.ts +2 -0
- package/dist/artifacts/DefaultClientArtifactsProvider.d.ts.map +1 -1
- package/dist/artifacts/DefaultClientArtifactsProvider.js +4 -0
- package/dist/artifacts/DefaultClientArtifactsProvider.js.map +1 -1
- package/dist/artifacts/IClientArtifactsProvider.d.ts +2 -0
- package/dist/artifacts/IClientArtifactsProvider.d.ts.map +1 -1
- package/dist/connection/ChronicleConnection.d.ts +1 -0
- package/dist/connection/ChronicleConnection.d.ts.map +1 -1
- package/dist/connection/ChronicleConnection.js +5 -1
- package/dist/connection/ChronicleConnection.js.map +1 -1
- package/dist/connection/ChronicleServices.d.ts +2 -1
- package/dist/connection/ChronicleServices.d.ts.map +1 -1
- package/dist/eventSequences/AppendOptions.d.ts +12 -0
- package/dist/eventSequences/AppendOptions.d.ts.map +1 -1
- package/dist/eventSequences/EventForEventSourceId.d.ts +11 -0
- package/dist/eventSequences/EventForEventSourceId.d.ts.map +1 -1
- package/dist/eventSequences/EventLog.d.ts +2 -1
- package/dist/eventSequences/EventLog.d.ts.map +1 -1
- package/dist/eventSequences/EventLog.js +2 -2
- package/dist/eventSequences/EventLog.js.map +1 -1
- package/dist/eventSequences/EventSequence.d.ts +4 -1
- package/dist/eventSequences/EventSequence.d.ts.map +1 -1
- package/dist/eventSequences/EventSequence.js +32 -6
- package/dist/eventSequences/EventSequence.js.map +1 -1
- package/dist/eventSequences/ITransactionalEventSequence.d.ts +5 -2
- package/dist/eventSequences/ITransactionalEventSequence.d.ts.map +1 -1
- package/dist/eventSequences/TransactionalEventSequence.d.ts +3 -2
- package/dist/eventSequences/TransactionalEventSequence.d.ts.map +1 -1
- package/dist/eventSequences/TransactionalEventSequence.js +4 -4
- package/dist/eventSequences/TransactionalEventSequence.js.map +1 -1
- package/dist/eventSequences/resolveEventSourceRouting.d.ts +39 -0
- package/dist/eventSequences/resolveEventSourceRouting.d.ts.map +1 -0
- package/dist/eventSequences/resolveEventSourceRouting.js +92 -0
- package/dist/eventSequences/resolveEventSourceRouting.js.map +1 -0
- package/dist/eventSources/ConcurrencyDimensions.d.ts +19 -0
- package/dist/eventSources/ConcurrencyDimensions.d.ts.map +1 -0
- package/dist/eventSources/ConcurrencyDimensions.js +19 -0
- package/dist/eventSources/ConcurrencyDimensions.js.map +1 -0
- package/dist/eventSources/DuplicateEventSourceName.d.ts +6 -0
- package/dist/eventSources/DuplicateEventSourceName.d.ts.map +1 -0
- package/dist/eventSources/DuplicateEventSourceName.js +12 -0
- package/dist/eventSources/DuplicateEventSourceName.js.map +1 -0
- package/dist/eventSources/DuplicateEventStreamName.d.ts +7 -0
- package/dist/eventSources/DuplicateEventStreamName.d.ts.map +1 -0
- package/dist/eventSources/DuplicateEventStreamName.js +14 -0
- package/dist/eventSources/DuplicateEventStreamName.js.map +1 -0
- package/dist/eventSources/EventRoutingContradictsEventSource.d.ts +9 -0
- package/dist/eventSources/EventRoutingContradictsEventSource.d.ts.map +1 -0
- package/dist/eventSources/EventRoutingContradictsEventSource.js +18 -0
- package/dist/eventSources/EventRoutingContradictsEventSource.js.map +1 -0
- package/dist/eventSources/EventSourceDefinition.d.ts +20 -0
- package/dist/eventSources/EventSourceDefinition.d.ts.map +1 -0
- package/dist/eventSources/EventSourceDefinition.js +4 -0
- package/dist/eventSources/EventSourceDefinition.js.map +1 -0
- package/dist/eventSources/EventSources.d.ts +31 -0
- package/dist/eventSources/EventSources.d.ts.map +1 -0
- package/dist/eventSources/EventSources.js +90 -0
- package/dist/eventSources/EventSources.js.map +1 -0
- package/dist/eventSources/EventStreamDefinition.d.ts +13 -0
- package/dist/eventSources/EventStreamDefinition.d.ts.map +1 -0
- package/dist/eventSources/EventStreamDefinition.js +4 -0
- package/dist/eventSources/EventStreamDefinition.js.map +1 -0
- package/dist/eventSources/EventStreamDoesNotBelongToEventSource.d.ts +7 -0
- package/dist/eventSources/EventStreamDoesNotBelongToEventSource.d.ts.map +1 -0
- package/dist/eventSources/EventStreamDoesNotBelongToEventSource.js +14 -0
- package/dist/eventSources/EventStreamDoesNotBelongToEventSource.js.map +1 -0
- package/dist/eventSources/EventStreamRequiresEventSource.d.ts +6 -0
- package/dist/eventSources/EventStreamRequiresEventSource.d.ts.map +1 -0
- package/dist/eventSources/EventStreamRequiresEventSource.js +12 -0
- package/dist/eventSources/EventStreamRequiresEventSource.js.map +1 -0
- package/dist/eventSources/IEventSources.d.ts +27 -0
- package/dist/eventSources/IEventSources.d.ts.map +1 -0
- package/dist/eventSources/IEventSources.js +4 -0
- package/dist/eventSources/IEventSources.js.map +1 -0
- package/dist/eventSources/ResolvedEventRouting.d.ts +37 -0
- package/dist/eventSources/ResolvedEventRouting.d.ts.map +1 -0
- package/dist/eventSources/ResolvedEventRouting.js +60 -0
- package/dist/eventSources/ResolvedEventRouting.js.map +1 -0
- package/dist/eventSources/UnknownEventSource.d.ts +6 -0
- package/dist/eventSources/UnknownEventSource.d.ts.map +1 -0
- package/dist/eventSources/UnknownEventSource.js +12 -0
- package/dist/eventSources/UnknownEventSource.js.map +1 -0
- package/dist/eventSources/eventSource.d.ts +60 -0
- package/dist/eventSources/eventSource.d.ts.map +1 -0
- package/dist/eventSources/eventSource.js +72 -0
- package/dist/eventSources/eventSource.js.map +1 -0
- package/dist/eventSources/index.d.ts +17 -0
- package/dist/eventSources/index.d.ts.map +1 -0
- package/dist/eventSources/index.js +13 -0
- package/dist/eventSources/index.js.map +1 -0
- package/dist/events/EventContext.d.ts +5 -0
- package/dist/events/EventContext.d.ts.map +1 -1
- package/dist/events/WireEventContext.d.ts +2 -0
- package/dist/events/WireEventContext.d.ts.map +1 -1
- package/dist/events/toClientEventContext.d.ts.map +1 -1
- package/dist/events/toClientEventContext.js +1 -0
- package/dist/events/toClientEventContext.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/projections/eventContextPropertyExpression.d.ts.map +1 -1
- package/dist/projections/eventContextPropertyExpression.js +1 -0
- package/dist/projections/eventContextPropertyExpression.js.map +1 -1
- package/dist/testing/projections/ProjectionReadModelProcessor.d.ts.map +1 -1
- package/dist/testing/projections/ProjectionReadModelProcessor.js +2 -1
- package/dist/testing/projections/ProjectionReadModelProcessor.js.map +1 -1
- package/dist/transactions/IUnitOfWork.d.ts +3 -1
- package/dist/transactions/IUnitOfWork.d.ts.map +1 -1
- package/dist/transactions/TransactionalEventRouting.d.ts +12 -0
- package/dist/transactions/TransactionalEventRouting.d.ts.map +1 -0
- package/dist/transactions/TransactionalEventRouting.js +4 -0
- package/dist/transactions/TransactionalEventRouting.js.map +1 -0
- package/dist/transactions/UnitOfWork.d.ts +2 -1
- package/dist/transactions/UnitOfWork.d.ts.map +1 -1
- package/dist/transactions/UnitOfWork.js +11 -2
- package/dist/transactions/UnitOfWork.js.map +1 -1
- package/dist/transactions/index.d.ts +1 -0
- package/dist/transactions/index.d.ts.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/DecoratorType.d.ts +3 -1
- package/dist/types/DecoratorType.d.ts.map +1 -1
- package/dist/types/DecoratorType.js +2 -0
- package/dist/types/DecoratorType.js.map +1 -1
- package/eventSequences/AppendOptions.ts +14 -0
- package/eventSequences/EventForEventSourceId.ts +13 -0
- package/eventSequences/EventLog.ts +4 -2
- package/eventSequences/EventSequence.ts +33 -6
- package/eventSequences/ITransactionalEventSequence.ts +5 -2
- package/eventSequences/TransactionalEventSequence.ts +5 -4
- package/eventSequences/resolveEventSourceRouting.ts +125 -0
- package/eventSources/ConcurrencyDimensions.ts +26 -0
- package/eventSources/DuplicateEventSourceName.ts +10 -0
- package/eventSources/DuplicateEventStreamName.ts +10 -0
- package/eventSources/EventRoutingContradictsEventSource.ts +10 -0
- package/eventSources/EventSourceDefinition.ts +27 -0
- package/eventSources/EventSources.ts +93 -0
- package/eventSources/EventStreamDefinition.ts +18 -0
- package/eventSources/EventStreamDoesNotBelongToEventSource.ts +10 -0
- package/eventSources/EventStreamRequiresEventSource.ts +10 -0
- package/eventSources/IEventSources.ts +33 -0
- package/eventSources/ResolvedEventRouting.ts +78 -0
- package/eventSources/UnknownEventSource.ts +10 -0
- package/eventSources/eventSource.ts +116 -0
- package/eventSources/for_EventSources/against_a_kernel/when_appending_through_registered_sources.integration.spec.ts +106 -0
- package/eventSources/for_EventSources/when_appending_through_a_definition.spec.ts +190 -0
- package/eventSources/for_EventSources/when_batch_requires_differing_guards.spec.ts +139 -0
- package/eventSources/for_EventSources/when_discovering_and_registering.spec.ts +94 -0
- package/eventSources/index.ts +19 -0
- package/events/EventContext.ts +6 -0
- package/events/WireEventContext.ts +2 -0
- package/events/for_EventContext/with_event_source.spec.ts +22 -0
- package/events/toClientEventContext.ts +1 -0
- package/for_EventStore/when_implementing_a_legacy_event_store.spec.ts +19 -0
- package/index.ts +3 -0
- package/package.json +3 -3
- package/projections/eventContextPropertyExpression.ts +2 -1
- package/testing/EventScenario.event-sources.spec.ts +34 -0
- package/testing/projections/ProjectionReadModelProcessor.ts +2 -1
- package/transactions/IUnitOfWork.ts +3 -1
- package/transactions/TransactionalEventRouting.ts +16 -0
- package/transactions/UnitOfWork.ts +13 -2
- package/transactions/for_UnitOfWork/when_committing_events_with_event_source_routing.spec.ts +41 -0
- package/transactions/index.ts +1 -0
- package/types/DecoratorType.ts +4 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cratis/chronicle",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.49.0",
|
|
4
4
|
"description": "Event sourcing for TypeScript and Node.js — the idiomatic client for Cratis Chronicle, the open-source event-sourcing database",
|
|
5
5
|
"author": "Cratis",
|
|
6
6
|
"license": "MIT",
|
|
@@ -173,12 +173,12 @@
|
|
|
173
173
|
"clean": "rm -rf dist",
|
|
174
174
|
"test": "vitest run",
|
|
175
175
|
"test:integration": "vitest run --config vitest.integration.config.ts",
|
|
176
|
-
"test:standard-types": "tsc --ignoreConfig --noEmit --target es2022 --module es2022 --moduleResolution bundler --lib es2022,esnext.decorators --types node --skipLibCheck --strict schemas/decorators.standard.spec.ts projections/declarative/addChildCompatibility.standard.spec.ts projections/declarative/for_CompositeKeyBuilder/when_typing_constant_parts.standard.spec.ts projections/modelBound/decorators.standard.spec.ts events/classDecorators.standard.spec.ts reactors/decorators.standard.spec.ts readModels/standardFallbacks.standard.spec.ts readModels/registration.standard.spec.ts for_ChronicleClient/when_registering_artifacts/with_standard_property_mappings.standard.spec.ts artifacts/validateArtifactSchemas.spec.ts testing/for_EventScenario/when_appending_concept_fields/with_standard_decorators.standard.spec.ts testing/for_EventScenario/when_appending_scoped_constraints/with_standard_decorators.standard.spec.ts schemas/for_JsonSchemaGenerator/when_generating_children/with_standard_decorators.standard.spec.ts events/for_handles/when_decorating_a_method.standard.spec.ts testing/for_ReadModelScenario/when_evaluating_arithmetic/with_standard_decorators.standard.spec.ts testing/for_ReadModelScenario/when_evaluating_joins/with_standard_decorators.standard.spec.ts testing/for_EventScenario/when_appending_field_types/with_standard_decorators.standard.spec.ts eventSequences/for_EventSequence/when_appending/with_subject_annotations.standard.spec.ts projections/for_ProjectionDefinitionCompiler/when_compiling_from_all.standard.spec.ts projections/for_ProjectionDefinitionCompiler/when_compiling_tags/with_standard_decorators.standard.spec.ts telemetry/for_ChronicleTelemetry/when_exposing_names/with_convention_names.spec.ts projections/for_ProjectionDefinitionCompiler/when_compiling_from_all_events.standard.spec.ts events/for_observerFilters/when_registering/with_standard_decorators.standard.spec.ts reactors/for_Reactors/against_a_kernel/when_filtering_source_and_stream_types.integration.spec.ts testing/for_observerScenarios/when_selecting_filters/with_source_and_stream_types.spec.ts readModels/for_ReadModelWatcher/watchCompatibility.standard.spec.ts",
|
|
176
|
+
"test:standard-types": "tsc --ignoreConfig --noEmit --target es2022 --module es2022 --moduleResolution bundler --lib es2022,esnext.decorators --types node --skipLibCheck --strict schemas/decorators.standard.spec.ts projections/declarative/addChildCompatibility.standard.spec.ts projections/declarative/for_CompositeKeyBuilder/when_typing_constant_parts.standard.spec.ts projections/modelBound/decorators.standard.spec.ts events/classDecorators.standard.spec.ts reactors/decorators.standard.spec.ts readModels/standardFallbacks.standard.spec.ts readModels/registration.standard.spec.ts for_ChronicleClient/when_registering_artifacts/with_standard_property_mappings.standard.spec.ts artifacts/validateArtifactSchemas.spec.ts testing/for_EventScenario/when_appending_concept_fields/with_standard_decorators.standard.spec.ts testing/for_EventScenario/when_appending_scoped_constraints/with_standard_decorators.standard.spec.ts schemas/for_JsonSchemaGenerator/when_generating_children/with_standard_decorators.standard.spec.ts events/for_handles/when_decorating_a_method.standard.spec.ts testing/for_ReadModelScenario/when_evaluating_arithmetic/with_standard_decorators.standard.spec.ts testing/for_ReadModelScenario/when_evaluating_joins/with_standard_decorators.standard.spec.ts testing/for_EventScenario/when_appending_field_types/with_standard_decorators.standard.spec.ts eventSequences/for_EventSequence/when_appending/with_subject_annotations.standard.spec.ts projections/for_ProjectionDefinitionCompiler/when_compiling_from_all.standard.spec.ts projections/for_ProjectionDefinitionCompiler/when_compiling_tags/with_standard_decorators.standard.spec.ts telemetry/for_ChronicleTelemetry/when_exposing_names/with_convention_names.spec.ts projections/for_ProjectionDefinitionCompiler/when_compiling_from_all_events.standard.spec.ts events/for_observerFilters/when_registering/with_standard_decorators.standard.spec.ts reactors/for_Reactors/against_a_kernel/when_filtering_source_and_stream_types.integration.spec.ts testing/for_observerScenarios/when_selecting_filters/with_source_and_stream_types.spec.ts readModels/for_ReadModelWatcher/watchCompatibility.standard.spec.ts for_EventStore/when_implementing_a_legacy_event_store.spec.ts",
|
|
177
177
|
"test:native": "node ./scripts/check-native-esm.mjs"
|
|
178
178
|
},
|
|
179
179
|
"dependencies": {
|
|
180
180
|
"@bufbuild/protobuf": "^2.16.0",
|
|
181
|
-
"@cratis/chronicle.contracts": "19.
|
|
181
|
+
"@cratis/chronicle.contracts": "19.30.0",
|
|
182
182
|
"@grpc/grpc-js": "^1.14.5",
|
|
183
183
|
"@opentelemetry/api": "^1.9.1",
|
|
184
184
|
"glob": "^13.0.6",
|
|
@@ -23,7 +23,8 @@ const contextProperties = {
|
|
|
23
23
|
correlationId: true,
|
|
24
24
|
causation: true,
|
|
25
25
|
tags: true
|
|
26
|
-
|
|
26
|
+
// eventSource is deliberately not projectable: its kernel resolution is not part of the supported expression set.
|
|
27
|
+
} satisfies Record<Exclude<keyof EventContext, 'eventSource'>, true>;
|
|
27
28
|
|
|
28
29
|
// Mirror the kernel's DerivedPropertyFunctions registry: Week() applies to dates only.
|
|
29
30
|
const derivedFunctions: Record<string, string> = { week: 'Week' };
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// Copyright (c) Cratis. All rights reserved.
|
|
2
|
+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
3
|
+
|
|
4
|
+
import 'reflect-metadata';
|
|
5
|
+
import { chai, describe, it } from 'vitest';
|
|
6
|
+
import { field } from '@cratis/fundamentals';
|
|
7
|
+
import { eventType } from '../events/eventTypeDecorator.js';
|
|
8
|
+
import { EventScenario, UnsupportedEventSequenceOperation } from './index.js';
|
|
9
|
+
|
|
10
|
+
chai.should();
|
|
11
|
+
class ScenarioSourceEvent { @field(String) name: string; constructor(name: string) { this.name = name; } }
|
|
12
|
+
eventType('ScenarioSourceEvent')(ScenarioSourceEvent);
|
|
13
|
+
|
|
14
|
+
const rejects = async (action: () => Promise<unknown>) => {
|
|
15
|
+
let caught: unknown;
|
|
16
|
+
try { await action(); } catch (error) { caught = error; }
|
|
17
|
+
(caught instanceof UnsupportedEventSequenceOperation).should.be.true;
|
|
18
|
+
};
|
|
19
|
+
const create = () => new EventScenario({ artifacts: { eventTypes: [ScenarioSourceEvent] } });
|
|
20
|
+
|
|
21
|
+
describe('when appending with registered event sources in an in-process scenario', () => {
|
|
22
|
+
it('should reject the eventSource option on append instead of dropping it', async () => {
|
|
23
|
+
await rejects(() => create().append('A', new ScenarioSourceEvent('x'), { eventSource: 'Account' }));
|
|
24
|
+
});
|
|
25
|
+
it('should reject the eventSource option on appendMany instead of dropping it', async () => {
|
|
26
|
+
await rejects(() => create().appendMany([{ eventSourceId: 'A', event: new ScenarioSourceEvent('x') }], { eventSource: 'Account' }));
|
|
27
|
+
});
|
|
28
|
+
it('should reject a per-event eventSource on appendMany instead of dropping it', async () => {
|
|
29
|
+
await rejects(() => create().appendMany([{ eventSourceId: 'A', event: new ScenarioSourceEvent('x'), eventSource: 'Account' }]));
|
|
30
|
+
});
|
|
31
|
+
it('should reject a per-event eventStream on appendMany instead of dropping it', async () => {
|
|
32
|
+
await rejects(() => create().appendMany([{ eventSourceId: 'A', event: new ScenarioSourceEvent('x'), eventStream: 'Transactions' }]));
|
|
33
|
+
});
|
|
34
|
+
});
|
|
@@ -138,7 +138,8 @@ export class ProjectionReadModelProcessor<TReadModel extends object> implements
|
|
|
138
138
|
if (!state) {
|
|
139
139
|
// SetInitialState: an event only a child subscribes to creates an uninitialized parent.
|
|
140
140
|
state = from ? this.initialState(key, event) : this.identityState(key, event, false);
|
|
141
|
-
} else if (state.__initialized === false) {
|
|
141
|
+
} else if (state.__initialized === false && from) {
|
|
142
|
+
// Chronicle 19.30.0 no longer initializes a parent on events only a child subscribes to.
|
|
142
143
|
for (const [name, value] of Object.entries(this.initialValues())) if (!(name in state)) state[name] = value;
|
|
143
144
|
state.__initialized = true;
|
|
144
145
|
}
|
|
@@ -6,6 +6,7 @@ import { AppendError } from '../eventSequences/AppendError.js';
|
|
|
6
6
|
import { ConcurrencyViolation } from '../eventSequences/ConcurrencyViolation.js';
|
|
7
7
|
import { ConstraintViolation } from '../eventSequences/ConstraintViolation.js';
|
|
8
8
|
import { EventSequenceId } from '../eventSequences/EventSequenceId.js';
|
|
9
|
+
import { TransactionalEventRouting } from './TransactionalEventRouting.js';
|
|
9
10
|
import { AppendResult } from '../eventSequences/AppendResult.js';
|
|
10
11
|
|
|
11
12
|
/**
|
|
@@ -26,8 +27,9 @@ export interface IUnitOfWork {
|
|
|
26
27
|
* @param eventSequenceId - The identifier of the event sequence to append to.
|
|
27
28
|
* @param eventSourceId - The event source identifier.
|
|
28
29
|
* @param event - The event payload.
|
|
30
|
+
* @param routing - Optional registered event source / stream routing for this event.
|
|
29
31
|
*/
|
|
30
|
-
addEvent(eventSequenceId: EventSequenceId, eventSourceId: string, event: object): void;
|
|
32
|
+
addEvent(eventSequenceId: EventSequenceId, eventSourceId: string, event: object, routing?: TransactionalEventRouting): void;
|
|
31
33
|
|
|
32
34
|
/**
|
|
33
35
|
* Gets all events currently buffered in this unit of work.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// Copyright (c) Cratis. All rights reserved.
|
|
2
|
+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
3
|
+
|
|
4
|
+
import type { Constructor } from '@cratis/fundamentals';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Optional registered event source routing for an event added to a unit of work.
|
|
8
|
+
* Carried through to the append on commit, where it is validated like any other append.
|
|
9
|
+
*/
|
|
10
|
+
export interface TransactionalEventRouting {
|
|
11
|
+
/** Registered event source definition (class decorated with `@eventSource`, or its name). */
|
|
12
|
+
readonly eventSource?: Constructor | string;
|
|
13
|
+
|
|
14
|
+
/** Stream name declared by {@link eventSource}. */
|
|
15
|
+
readonly eventStream?: string;
|
|
16
|
+
}
|
|
@@ -8,7 +8,9 @@ import { ConcurrencyViolation } from '../eventSequences/ConcurrencyViolation.js'
|
|
|
8
8
|
import { ConstraintViolation } from '../eventSequences/ConstraintViolation.js';
|
|
9
9
|
import { EventForEventSourceId } from '../eventSequences/EventForEventSourceId.js';
|
|
10
10
|
import { EventSequenceId } from '../eventSequences/EventSequenceId.js';
|
|
11
|
+
import { planDerivedGuards, resolveBatchRouting } from '../eventSequences/resolveEventSourceRouting.js';
|
|
11
12
|
import { IEventStore } from '../IEventStore.js';
|
|
13
|
+
import { TransactionalEventRouting } from './TransactionalEventRouting.js';
|
|
12
14
|
import { IUnitOfWork } from './IUnitOfWork.js';
|
|
13
15
|
|
|
14
16
|
interface EventForEventSourceIdWithSequenceNumber {
|
|
@@ -46,14 +48,16 @@ export class UnitOfWork implements IUnitOfWork {
|
|
|
46
48
|
}
|
|
47
49
|
|
|
48
50
|
/** @inheritdoc */
|
|
49
|
-
addEvent(eventSequenceId: EventSequenceId, eventSourceId: string, event: object): void {
|
|
51
|
+
addEvent(eventSequenceId: EventSequenceId, eventSourceId: string, event: object, routing?: TransactionalEventRouting): void {
|
|
50
52
|
this.throwIfCompleted();
|
|
51
53
|
this._events.push({
|
|
52
54
|
sequenceNumber: this._events.length,
|
|
53
55
|
eventSequenceId,
|
|
54
56
|
eventForEventSourceId: {
|
|
55
57
|
eventSourceId,
|
|
56
|
-
event
|
|
58
|
+
event,
|
|
59
|
+
...(routing?.eventSource !== undefined ? { eventSource: routing.eventSource } : {}),
|
|
60
|
+
...(routing?.eventStream !== undefined ? { eventStream: routing.eventStream } : {})
|
|
57
61
|
}
|
|
58
62
|
});
|
|
59
63
|
}
|
|
@@ -100,6 +104,13 @@ export class UnitOfWork implements IUnitOfWork {
|
|
|
100
104
|
eventsByEventSequence.set(key, events);
|
|
101
105
|
}
|
|
102
106
|
|
|
107
|
+
// Resolve routing and required guards for every group first: a rejection must not follow a written group.
|
|
108
|
+
const eventSources = this._eventStore.eventSources;
|
|
109
|
+
for (const eventsForSequence of eventSources ? eventsByEventSequence.values() : []) {
|
|
110
|
+
const events = eventsForSequence.map(_ => _.eventForEventSourceId);
|
|
111
|
+
planDerivedGuards(events.map(_ => resolveBatchRouting(eventSources, _)), events, undefined);
|
|
112
|
+
}
|
|
113
|
+
|
|
103
114
|
for (const [eventSequenceId, eventsForSequence] of eventsByEventSequence) {
|
|
104
115
|
const sequence = this._eventStore.getEventSequence(new EventSequenceId(eventSequenceId));
|
|
105
116
|
const appendResults = await sequence.appendMany(
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// Copyright (c) Cratis. All rights reserved.
|
|
2
|
+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
3
|
+
|
|
4
|
+
import { Guid } from '@cratis/fundamentals';
|
|
5
|
+
import { beforeEach, chai, describe, it, vi } from 'vitest';
|
|
6
|
+
import { EventSequenceId } from '../../eventSequences/index.js';
|
|
7
|
+
import type { IEventStore } from '../../IEventStore.js';
|
|
8
|
+
import { UnitOfWork } from '../UnitOfWork.js';
|
|
9
|
+
|
|
10
|
+
const should = chai.should();
|
|
11
|
+
|
|
12
|
+
describe('when committing events with event source routing in a unit of work', () => {
|
|
13
|
+
let batch: any[];
|
|
14
|
+
beforeEach(async () => {
|
|
15
|
+
const appendMany = vi.fn().mockResolvedValue([{ isSuccess: true, constraintViolations: [], errors: [] }, { isSuccess: true, constraintViolations: [], errors: [] }]);
|
|
16
|
+
const store = { getEventSequence: () => ({ appendMany }) } as unknown as IEventStore;
|
|
17
|
+
const unitOfWork = new UnitOfWork(Guid.create(), () => {}, store);
|
|
18
|
+
unitOfWork.addEvent(EventSequenceId.eventLog, 'a-1', { first: 1 }, { eventSource: 'Account', eventStream: 'Transactions' });
|
|
19
|
+
unitOfWork.addEvent(EventSequenceId.eventLog, 'c-1', { second: 2 }, { eventSource: 'Customer' });
|
|
20
|
+
await unitOfWork.commit();
|
|
21
|
+
batch = appendMany.mock.calls[0][0];
|
|
22
|
+
});
|
|
23
|
+
it('should keep the source and stream of the first event', () => {
|
|
24
|
+
batch[0].eventSource.should.equal('Account');
|
|
25
|
+
batch[0].eventStream.should.equal('Transactions');
|
|
26
|
+
});
|
|
27
|
+
it('should keep a different source on the second event without a stream', () => {
|
|
28
|
+
batch[1].eventSource.should.equal('Customer');
|
|
29
|
+
should.not.exist(batch[1].eventStream);
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
describe('when adding an event to a unit of work without routing', () => {
|
|
34
|
+
it('should not add routing keys to the buffered event', async () => {
|
|
35
|
+
const appendMany = vi.fn().mockResolvedValue([{ isSuccess: true, constraintViolations: [], errors: [] }]);
|
|
36
|
+
const unitOfWork = new UnitOfWork(Guid.create(), () => {}, { getEventSequence: () => ({ appendMany }) } as unknown as IEventStore);
|
|
37
|
+
unitOfWork.addEvent(EventSequenceId.eventLog, 'a-1', {});
|
|
38
|
+
await unitOfWork.commit();
|
|
39
|
+
Object.keys(appendMany.mock.calls[0][0][0]).sort().should.deep.equal(['event', 'eventSourceId']);
|
|
40
|
+
});
|
|
41
|
+
});
|
package/transactions/index.ts
CHANGED
|
@@ -6,3 +6,4 @@ export type { IUnitOfWorkManager } from './IUnitOfWorkManager.js';
|
|
|
6
6
|
export { NoUnitOfWorkHasBeenStarted } from './NoUnitOfWorkHasBeenStarted.js';
|
|
7
7
|
export { UnitOfWork } from './UnitOfWork.js';
|
|
8
8
|
export { UnitOfWorkManager } from './UnitOfWorkManager.js';
|
|
9
|
+
export type { TransactionalEventRouting } from './TransactionalEventRouting.js';
|
package/types/DecoratorType.ts
CHANGED
|
@@ -33,5 +33,8 @@ export enum DecoratorType {
|
|
|
33
33
|
EventTypeMigration = 'eventTypeMigration',
|
|
34
34
|
|
|
35
35
|
/** Global read model variant handler artifacts discovered through the globalFor decorator. */
|
|
36
|
-
GlobalForHandler = 'globalForHandler'
|
|
36
|
+
GlobalForHandler = 'globalForHandler',
|
|
37
|
+
|
|
38
|
+
/** Event source definition artifacts discovered through the eventSource decorator. */
|
|
39
|
+
EventSource = 'eventSource'
|
|
37
40
|
}
|