@cratis/chronicle 6.50.0 → 6.51.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/dist/eventSequences/ITransactionalEventSequence.d.ts +2 -2
- package/dist/events/constraints/ConstraintBuilder.d.ts +7 -0
- package/dist/events/constraints/ConstraintBuilder.d.ts.map +1 -1
- package/dist/events/constraints/ConstraintBuilder.js +13 -0
- package/dist/events/constraints/ConstraintBuilder.js.map +1 -1
- package/dist/events/constraints/ConstraintEventSequences.d.ts +19 -0
- package/dist/events/constraints/ConstraintEventSequences.d.ts.map +1 -0
- package/dist/events/constraints/ConstraintEventSequences.js +39 -0
- package/dist/events/constraints/ConstraintEventSequences.js.map +1 -0
- package/dist/events/constraints/Constraints.d.ts.map +1 -1
- package/dist/events/constraints/Constraints.js +24 -3
- package/dist/events/constraints/Constraints.js.map +1 -1
- package/dist/events/constraints/IConstraintBuilder.d.ts +18 -0
- package/dist/events/constraints/IConstraintBuilder.d.ts.map +1 -1
- package/dist/events/constraints/UniqueOptions.d.ts +15 -0
- package/dist/events/constraints/UniqueOptions.d.ts.map +1 -0
- package/dist/events/constraints/UniqueOptions.js +4 -0
- package/dist/events/constraints/UniqueOptions.js.map +1 -0
- package/dist/events/constraints/for_Constraints/when_scoping_to_event_sequences/given/registered_constraints.d.ts +9 -0
- package/dist/events/constraints/for_Constraints/when_scoping_to_event_sequences/given/registered_constraints.d.ts.map +1 -0
- package/dist/events/constraints/for_Constraints/when_scoping_to_event_sequences/given/registered_constraints.js +22 -0
- package/dist/events/constraints/for_Constraints/when_scoping_to_event_sequences/given/registered_constraints.js.map +1 -0
- package/dist/events/constraints/index.d.ts +2 -0
- package/dist/events/constraints/index.d.ts.map +1 -1
- package/dist/events/constraints/index.js.map +1 -1
- package/dist/events/constraints/unique.d.ts +10 -0
- package/dist/events/constraints/unique.d.ts.map +1 -1
- package/dist/events/constraints/unique.js +11 -10
- package/dist/events/constraints/unique.js.map +1 -1
- package/dist/testing/EventScenario.d.ts.map +1 -1
- package/dist/testing/EventScenario.js +8 -3
- package/dist/testing/EventScenario.js.map +1 -1
- package/dist/testing/InProcessConstraints.d.ts +4 -1
- package/dist/testing/InProcessConstraints.d.ts.map +1 -1
- package/dist/testing/InProcessConstraints.js +5 -1
- package/dist/testing/InProcessConstraints.js.map +1 -1
- package/dist/testing/InProcessEventSequence.d.ts.map +1 -1
- package/dist/testing/InProcessEventSequence.js +2 -1
- package/dist/testing/InProcessEventSequence.js.map +1 -1
- package/dist/transactions/ConflictingConcurrencyScopesInUnitOfWork.d.ts +14 -0
- package/dist/transactions/ConflictingConcurrencyScopesInUnitOfWork.d.ts.map +1 -0
- package/dist/transactions/ConflictingConcurrencyScopesInUnitOfWork.js +20 -0
- package/dist/transactions/ConflictingConcurrencyScopesInUnitOfWork.js.map +1 -0
- package/dist/transactions/IUnitOfWork.d.ts +2 -1
- package/dist/transactions/IUnitOfWork.d.ts.map +1 -1
- package/dist/transactions/TransactionalAppendOptions.d.ts +23 -2
- package/dist/transactions/TransactionalAppendOptions.d.ts.map +1 -1
- package/dist/transactions/UnitOfWork.d.ts +1 -0
- package/dist/transactions/UnitOfWork.d.ts.map +1 -1
- package/dist/transactions/UnitOfWork.js +28 -13
- package/dist/transactions/UnitOfWork.js.map +1 -1
- package/dist/transactions/concurrencyScopesAreEqual.d.ts +9 -0
- package/dist/transactions/concurrencyScopesAreEqual.d.ts.map +1 -0
- package/dist/transactions/concurrencyScopesAreEqual.js +19 -0
- package/dist/transactions/concurrencyScopesAreEqual.js.map +1 -0
- package/dist/transactions/for_UnitOfWork/given/a_unit_of_work_with_a_recording_store.d.ts +26 -0
- package/dist/transactions/for_UnitOfWork/given/a_unit_of_work_with_a_recording_store.d.ts.map +1 -0
- package/dist/transactions/for_UnitOfWork/given/a_unit_of_work_with_a_recording_store.js +31 -0
- package/dist/transactions/for_UnitOfWork/given/a_unit_of_work_with_a_recording_store.js.map +1 -0
- package/dist/transactions/index.d.ts +1 -0
- package/dist/transactions/index.d.ts.map +1 -1
- package/dist/transactions/index.js +1 -0
- package/dist/transactions/index.js.map +1 -1
- package/dist/transactions/toEventForEventSourceId.d.ts +13 -0
- package/dist/transactions/toEventForEventSourceId.d.ts.map +1 -0
- package/dist/transactions/toEventForEventSourceId.js +29 -0
- package/dist/transactions/toEventForEventSourceId.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/eventSequences/ITransactionalEventSequence.ts +2 -2
- package/eventSequences/for_TransactionalEventSequence/when_appending_many_with_options.spec.ts +29 -0
- package/events/constraints/ConstraintBuilder.ts +16 -0
- package/events/constraints/ConstraintEventSequences.ts +41 -0
- package/events/constraints/Constraints.ts +22 -3
- package/events/constraints/IConstraintBuilder.ts +20 -0
- package/events/constraints/UniqueOptions.ts +20 -0
- package/events/constraints/for_Constraints/against_a_kernel/when_appending_to_event_sequences_a_constraint_is_scoped_to.integration.spec.ts +118 -0
- package/events/constraints/for_Constraints/when_scoping_to_event_sequences/given/registered_constraints.ts +26 -0
- package/events/constraints/for_Constraints/when_scoping_to_event_sequences/with_fluent_builder.spec.ts +40 -0
- package/events/constraints/for_Constraints/when_scoping_to_event_sequences/with_legacy_decorators.legacy.spec.ts +47 -0
- package/events/constraints/for_Constraints/when_scoping_to_event_sequences/with_merged_declarations.spec.ts +36 -0
- package/events/constraints/for_Constraints/when_scoping_to_event_sequences/with_standard_decorators.standard.spec.ts +46 -0
- package/events/constraints/index.ts +2 -0
- package/events/constraints/unique.ts +22 -2
- package/package.json +2 -2
- package/testing/EventScenario.fixtures.spec.ts +1 -1
- package/testing/EventScenario.ts +10 -4
- package/testing/InProcessConstraints.ts +5 -1
- package/testing/InProcessEventSequence.ts +2 -1
- package/testing/for_EventScenario/when_appending_event_sequence_constraints/event_sequence_scenario_behaviors.fixture.ts +101 -0
- package/testing/for_EventScenario/when_appending_event_sequence_constraints/other_sequence_extended_key.legacy.spec.ts +28 -0
- package/testing/for_EventScenario/when_appending_event_sequence_constraints/other_sequence_extended_key.standard.spec.ts +27 -0
- package/testing/for_EventScenario/when_appending_event_sequence_constraints/other_sequence_extended_key_behaviors.fixture.ts +40 -0
- package/testing/for_EventScenario/when_appending_event_sequence_constraints/with_legacy_decorators.legacy.spec.ts +55 -0
- package/testing/for_EventScenario/when_appending_event_sequence_constraints/with_standard_decorators.standard.spec.ts +54 -0
- package/transactions/ConflictingConcurrencyScopesInUnitOfWork.ts +19 -0
- package/transactions/IUnitOfWork.ts +2 -1
- package/transactions/TransactionalAppendOptions.ts +30 -2
- package/transactions/UnitOfWork.ts +29 -13
- package/transactions/concurrencyScopesAreEqual.ts +23 -0
- package/transactions/for_UnitOfWork/against_a_kernel/when_committing_with_append_metadata.integration.spec.ts +70 -0
- package/transactions/for_UnitOfWork/given/a_unit_of_work_with_a_recording_store.ts +54 -0
- package/transactions/for_UnitOfWork/when_adding_events_with_concurrency_scopes/and_the_event_type_filters_are_equivalent.spec.ts +32 -0
- package/transactions/for_UnitOfWork/when_adding_events_with_concurrency_scopes/and_the_event_type_filters_differ.spec.ts +40 -0
- package/transactions/for_UnitOfWork/when_adding_events_with_concurrency_scopes/and_the_scopes_are_equal_or_omitted.spec.ts +29 -0
- package/transactions/for_UnitOfWork/when_adding_events_with_concurrency_scopes/and_the_scopes_differ_for_one_event_source.spec.ts +29 -0
- package/transactions/for_UnitOfWork/when_committing_events_with_append_metadata/and_a_later_event_sequence_fails.spec.ts +30 -0
- package/transactions/for_UnitOfWork/when_committing_events_with_append_metadata/and_events_span_event_sequences.spec.ts +34 -0
- package/transactions/for_UnitOfWork/when_committing_events_with_append_metadata/and_options_differ_per_event.spec.ts +45 -0
- package/transactions/for_UnitOfWork/when_committing_events_with_append_metadata/and_the_append_is_rejected.spec.ts +26 -0
- package/transactions/for_UnitOfWork/when_rolling_back_events_with_append_metadata.spec.ts +24 -0
- package/transactions/index.ts +1 -0
- package/transactions/toEventForEventSourceId.ts +32 -0
- package/vitest.integration.config.ts +2 -0
- package/webhooks/for_Webhooks/against_a_kernel/given/ReceivedWebhookRequest.fixture.ts +21 -0
- package/webhooks/for_Webhooks/against_a_kernel/given/WebhookReceiver.fixture.ts +99 -0
- package/webhooks/for_Webhooks/against_a_kernel/when_delivering_events_to_a_failing_webhook.integration.spec.ts +101 -0
- package/webhooks/for_Webhooks/against_a_kernel/when_delivering_events_to_a_webhook.integration.spec.ts +130 -0
- package/webhooks/for_Webhooks/against_a_kernel/when_registering_a_webhook_that_is_not_replayable_and_not_active.integration.spec.ts +101 -0
- package/webhooks/for_Webhooks/when_registering_a_webhook_that_is_not_replayable_and_not_active.spec.ts +43 -0
|
@@ -0,0 +1,101 @@
|
|
|
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 { randomUUID } from 'node:crypto';
|
|
5
|
+
import { afterAll, beforeAll, chai, describe, it } from 'vitest';
|
|
6
|
+
import type { WebhookDefinition } from '@cratis/chronicle.contracts';
|
|
7
|
+
import { field } from '@cratis/fundamentals';
|
|
8
|
+
import { ChronicleClient } from '../../../ChronicleClient.js';
|
|
9
|
+
import { ChronicleOptions } from '../../../ChronicleOptions.js';
|
|
10
|
+
import type { IClientArtifactsProvider } from '../../../artifacts/index.js';
|
|
11
|
+
import { eventType } from '../../../events/index.js';
|
|
12
|
+
import type { IEventStore } from '../../../IEventStore.js';
|
|
13
|
+
|
|
14
|
+
chai.should();
|
|
15
|
+
|
|
16
|
+
// Runs against a real Chronicle kernel; skipped locally unless the connection string is set (see vitest.integration.config.ts).
|
|
17
|
+
// In CI it never skips, so a missing connection string or unreachable kernel fails instead of passing vacuously.
|
|
18
|
+
const connectionString = process.env.CHRONICLE_INTEGRATION_CONNECTION_STRING;
|
|
19
|
+
|
|
20
|
+
@eventType()
|
|
21
|
+
class ParcelReturned {
|
|
22
|
+
@field(String) parcelId = '';
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const artifacts: IClientArtifactsProvider = {
|
|
26
|
+
eventTypes: [ParcelReturned],
|
|
27
|
+
readModels: [],
|
|
28
|
+
reactors: [],
|
|
29
|
+
reducers: [],
|
|
30
|
+
seeders: [],
|
|
31
|
+
constraints: [],
|
|
32
|
+
projections: [],
|
|
33
|
+
webhooks: [],
|
|
34
|
+
eventTypeMigrations: [],
|
|
35
|
+
globalForHandlers: []
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
async function eventually<T>(read: () => Promise<T>, accept: (value: T) => boolean, timeoutMs = 20_000): Promise<T> {
|
|
39
|
+
const deadline = Date.now() + timeoutMs;
|
|
40
|
+
let value = await read();
|
|
41
|
+
while (!accept(value)) {
|
|
42
|
+
if (Date.now() > deadline) throw new Error('Timed out waiting for the kernel');
|
|
43
|
+
await new Promise(resolve => setTimeout(resolve, 100));
|
|
44
|
+
value = await read();
|
|
45
|
+
}
|
|
46
|
+
return value;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
describe.skipIf(!connectionString && !process.env.CI)('when registering a webhook that is not replayable and not active against a kernel', () => {
|
|
50
|
+
const defaultWebhookId = randomUUID();
|
|
51
|
+
const restrictedWebhookId = randomUUID();
|
|
52
|
+
const targetUrl = 'http://localhost:9/parcels';
|
|
53
|
+
let client: ChronicleClient;
|
|
54
|
+
let store: IEventStore;
|
|
55
|
+
let defaultWebhook: WebhookDefinition;
|
|
56
|
+
let restrictedWebhook: WebhookDefinition;
|
|
57
|
+
|
|
58
|
+
beforeAll(async () => {
|
|
59
|
+
client = new ChronicleClient(ChronicleOptions.fromConnectionString(connectionString!, {
|
|
60
|
+
discoveryPatterns: [],
|
|
61
|
+
clientArtifactsProvider: artifacts
|
|
62
|
+
}));
|
|
63
|
+
store = await client.getEventStore(`Webhooks${randomUUID().replaceAll('-', '').slice(0, 12)}`);
|
|
64
|
+
|
|
65
|
+
// A webhook with the defaults proves the read-back distinguishes true from false, so a false
|
|
66
|
+
// below cannot be an artifact of how an absent field decodes.
|
|
67
|
+
await store.webhooks.register(defaultWebhookId, targetUrl, _ => _.withEventType(ParcelReturned));
|
|
68
|
+
await store.webhooks.register(restrictedWebhookId, targetUrl, _ => _
|
|
69
|
+
.withEventType(ParcelReturned)
|
|
70
|
+
.notReplayable()
|
|
71
|
+
.notActive());
|
|
72
|
+
|
|
73
|
+
const webhooks = await eventually(
|
|
74
|
+
() => store.webhooks.getWebhooks(),
|
|
75
|
+
_ => [defaultWebhookId, restrictedWebhookId].every(id => _.some(webhook => webhook.Identifier === id)));
|
|
76
|
+
defaultWebhook = webhooks.find(_ => _.Identifier === defaultWebhookId)!;
|
|
77
|
+
restrictedWebhook = webhooks.find(_ => _.Identifier === restrictedWebhookId)!;
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
afterAll(async () => {
|
|
81
|
+
const failures: unknown[] = [];
|
|
82
|
+
for (const id of [defaultWebhookId, restrictedWebhookId]) {
|
|
83
|
+
try {
|
|
84
|
+
await store?.webhooks.remove(id);
|
|
85
|
+
} catch (error) {
|
|
86
|
+
failures.push(error);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
client?.dispose();
|
|
90
|
+
if (failures.length > 0) throw failures[0];
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
it('should keep a default webhook replayable', () => defaultWebhook.IsReplayable.should.be.true);
|
|
94
|
+
it('should keep a default webhook active', () => defaultWebhook.IsActive.should.be.true);
|
|
95
|
+
it('should keep the webhook not replayable', () => restrictedWebhook.IsReplayable.should.be.false);
|
|
96
|
+
// The kernel records IsActive=false in WebhookAdded, but its MongoDB storage converter drops IsActive when reading
|
|
97
|
+
// definitions back (Storage.MongoDB/Observation/Webhooks/WebhookDefinitionConverters.cs, ToKernel), so every
|
|
98
|
+
// kernel up to at least 19.30.0 lists the webhook as active (Cratis/Chronicle#4581). The client sending
|
|
99
|
+
// IsActive=false is covered by the unit spec when_registering_a_webhook_that_is_not_replayable_and_not_active.spec.ts.
|
|
100
|
+
it.todo('should keep the webhook not active once the kernel reads IsActive back from storage');
|
|
101
|
+
});
|
|
@@ -0,0 +1,43 @@
|
|
|
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 { AddWebhooks } from '@cratis/chronicle.contracts';
|
|
5
|
+
import { beforeEach, chai, describe, it } from 'vitest';
|
|
6
|
+
import { field } from '@cratis/fundamentals';
|
|
7
|
+
import type { IClientArtifactsProvider } from '../../artifacts/index.js';
|
|
8
|
+
import type { ChronicleConnection } from '../../connection/index.js';
|
|
9
|
+
import { eventType } from '../../events/index.js';
|
|
10
|
+
import type { IEventTypes } from '../../events/IEventTypes.js';
|
|
11
|
+
import { Webhooks } from '../Webhooks.js';
|
|
12
|
+
|
|
13
|
+
chai.should();
|
|
14
|
+
|
|
15
|
+
@eventType()
|
|
16
|
+
class ParcelReturned {
|
|
17
|
+
@field(String) parcelId = '';
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
describe('when registering a webhook that is not replayable and not active', () => {
|
|
21
|
+
let sent: AddWebhooks | undefined;
|
|
22
|
+
|
|
23
|
+
beforeEach(async () => {
|
|
24
|
+
sent = undefined;
|
|
25
|
+
const connection = {
|
|
26
|
+
webhooks: {
|
|
27
|
+
addWebhooks: async (request: AddWebhooks) => {
|
|
28
|
+
sent = request;
|
|
29
|
+
return { IsAuthorized: true, ValidationResults: [], ExceptionMessages: [] };
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
} as unknown as ChronicleConnection;
|
|
33
|
+
const webhooks = new Webhooks('store', connection, { all: [] } as unknown as IEventTypes, {} as IClientArtifactsProvider);
|
|
34
|
+
|
|
35
|
+
await webhooks.register('parcels', 'http://localhost:9/parcels', _ => _
|
|
36
|
+
.withEventType(ParcelReturned)
|
|
37
|
+
.notReplayable()
|
|
38
|
+
.notActive());
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it('should send the webhook as not active', () => sent!.Webhooks[0].IsActive.should.be.false);
|
|
42
|
+
it('should send the webhook as not replayable', () => sent!.Webhooks[0].IsReplayable.should.be.false);
|
|
43
|
+
});
|