@cratis/chronicle 6.52.0 → 6.53.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.
Files changed (75) hide show
  1. package/dist/reactors/Reactors.d.ts.map +1 -1
  2. package/dist/reactors/Reactors.js +2 -0
  3. package/dist/reactors/Reactors.js.map +1 -1
  4. package/dist/reactors/index.d.ts +1 -0
  5. package/dist/reactors/index.d.ts.map +1 -1
  6. package/dist/reactors/index.js +1 -0
  7. package/dist/reactors/index.js.map +1 -1
  8. package/dist/reactors/startAtTail.d.ts +18 -0
  9. package/dist/reactors/startAtTail.d.ts.map +1 -0
  10. package/dist/reactors/startAtTail.js +30 -0
  11. package/dist/reactors/startAtTail.js.map +1 -0
  12. package/dist/readModels/for_ReadModels/given/Book.d.ts +8 -0
  13. package/dist/readModels/for_ReadModels/given/Book.d.ts.map +1 -0
  14. package/dist/readModels/for_ReadModels/given/Book.js +25 -0
  15. package/dist/readModels/for_ReadModels/given/Book.js.map +1 -0
  16. package/dist/readModels/for_ReadModels/given/BookBorrowed.d.ts +3 -0
  17. package/dist/readModels/for_ReadModels/given/BookBorrowed.d.ts.map +1 -0
  18. package/dist/readModels/for_ReadModels/given/BookBorrowed.js +5 -0
  19. package/dist/readModels/for_ReadModels/given/BookBorrowed.js.map +1 -0
  20. package/dist/readModels/for_ReadModels/given/BookRegistered.d.ts +5 -0
  21. package/dist/readModels/for_ReadModels/given/BookRegistered.d.ts.map +1 -0
  22. package/dist/readModels/for_ReadModels/given/BookRegistered.js +7 -0
  23. package/dist/readModels/for_ReadModels/given/BookRegistered.js.map +1 -0
  24. package/dist/readModels/for_ReadModels/given/BookReturned.d.ts +3 -0
  25. package/dist/readModels/for_ReadModels/given/BookReturned.d.ts.map +1 -0
  26. package/dist/readModels/for_ReadModels/given/BookReturned.js +5 -0
  27. package/dist/readModels/for_ReadModels/given/BookReturned.js.map +1 -0
  28. package/dist/readModels/for_deserializeReadModel/given/Address.d.ts +6 -0
  29. package/dist/readModels/for_deserializeReadModel/given/Address.d.ts.map +1 -0
  30. package/dist/readModels/for_deserializeReadModel/given/Address.js +11 -0
  31. package/dist/readModels/for_deserializeReadModel/given/Address.js.map +1 -0
  32. package/dist/readModels/for_deserializeReadModel/given/a_read_model_with_defaults.d.ts +9 -0
  33. package/dist/readModels/for_deserializeReadModel/given/a_read_model_with_defaults.d.ts.map +1 -0
  34. package/dist/readModels/for_deserializeReadModel/given/a_read_model_with_defaults.js +16 -0
  35. package/dist/readModels/for_deserializeReadModel/given/a_read_model_with_defaults.js.map +1 -0
  36. package/dist/tsconfig.tsbuildinfo +1 -1
  37. package/dist/webhooks/WebhookDefinitionBuilder.d.ts +1 -1
  38. package/dist/webhooks/WebhookDefinitionBuilder.d.ts.map +1 -1
  39. package/dist/webhooks/WebhookDefinitionBuilder.js +3 -1
  40. package/dist/webhooks/WebhookDefinitionBuilder.js.map +1 -1
  41. package/dist/webhooks/Webhooks.d.ts.map +1 -1
  42. package/dist/webhooks/Webhooks.js +2 -1
  43. package/dist/webhooks/Webhooks.js.map +1 -1
  44. package/package.json +4 -4
  45. package/projections/for_ProjectionDefinitionCompiler/against_a_kernel/when_subscribing_with_from_all_events.integration.spec.ts +3 -3
  46. package/reactors/Reactors.startAtTail.spec.ts +60 -0
  47. package/reactors/Reactors.ts +2 -0
  48. package/reactors/for_Reactors/against_a_kernel/when_starting_at_the_tail.integration.spec.ts +107 -0
  49. package/reactors/index.ts +1 -0
  50. package/reactors/startAtTail.spec.ts +31 -0
  51. package/reactors/startAtTail.ts +33 -0
  52. package/readModels/for_ReadModels/given/Book.ts +26 -0
  53. package/readModels/for_ReadModels/given/BookBorrowed.ts +4 -0
  54. package/readModels/for_ReadModels/given/BookRegistered.ts +7 -0
  55. package/readModels/for_ReadModels/given/BookReturned.ts +4 -0
  56. package/readModels/for_ReadModels/when_reading_a_model_bound_projection/without_registration_fields.spec.ts +30 -0
  57. package/readModels/for_deserializeReadModel/given/Address.ts +12 -0
  58. package/readModels/for_deserializeReadModel/given/IdentityDefaults.fixture.ts +15 -0
  59. package/readModels/for_deserializeReadModel/given/SetterDefaults.fixture.ts +22 -0
  60. package/readModels/for_deserializeReadModel/given/a_read_model_with_defaults.ts +18 -0
  61. package/readModels/for_deserializeReadModel/when_restoring/with_a_non_idempotent_setter_and_an_absent_sibling.spec.ts +20 -0
  62. package/readModels/for_deserializeReadModel/when_restoring/with_a_partial_nested_object.spec.ts +31 -0
  63. package/readModels/for_deserializeReadModel/when_restoring/with_absent_fields.spec.ts +22 -0
  64. package/readModels/for_deserializeReadModel/when_restoring/with_explicit_null.spec.ts +20 -0
  65. package/readModels/for_deserializeReadModel/when_restoring/with_identity_dependent_defaults.spec.ts +20 -0
  66. package/readModels/for_deserializeReadModel/when_restoring/with_partial_array_items.spec.ts +23 -0
  67. package/readModels/for_deserializeReadModel/when_restoring/with_present_fields.spec.ts +19 -0
  68. package/testing/EventScenario.constraint-values.spec.ts +2 -2
  69. package/testing/for_ReadModelScenario/when_evaluating_arithmetic/with_legacy_decorators.legacy.spec.ts +1 -1
  70. package/testing/for_ReadModelScenario/when_evaluating_arithmetic/with_standard_decorators.standard.spec.ts +1 -1
  71. package/testing/for_ReadModelScenario/when_evaluating_joins/with_a_fluent_projection.spec.ts +2 -2
  72. package/testing/for_ReadModelScenario/when_evaluating_joins/with_legacy_decorators.legacy.spec.ts +2 -2
  73. package/testing/for_ReadModelScenario/when_evaluating_joins/with_standard_decorators.standard.spec.ts +2 -2
  74. package/webhooks/WebhookDefinitionBuilder.ts +9 -7
  75. package/webhooks/Webhooks.ts +2 -1
@@ -0,0 +1,31 @@
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 { describe, expect, it } from 'vitest';
5
+ import { isStartAtTail, startAtTail } from './startAtTail.js';
6
+
7
+ @startAtTail()
8
+ class MarkedReactor {}
9
+
10
+ class OrdinaryReactor {}
11
+
12
+ class InheritedReactor extends MarkedReactor {}
13
+
14
+ describe('the start-at-tail decorator', () => {
15
+ it('marks the reactor class', () => {
16
+ expect(isStartAtTail(MarkedReactor)).toBe(true);
17
+ });
18
+
19
+ it('leaves an unmarked class alone', () => {
20
+ expect(isStartAtTail(OrdinaryReactor)).toBe(false);
21
+ });
22
+
23
+ it('is not inherited by a subclass', () => {
24
+ expect(isStartAtTail(InheritedReactor)).toBe(false);
25
+ });
26
+
27
+ it('refuses to decorate anything but a class', () => {
28
+ const decorate = startAtTail() as unknown as (target: object, context: { kind: string }) => void;
29
+ expect(() => decorate(() => {}, { kind: 'method' })).toThrow(TypeError);
30
+ });
31
+ });
@@ -0,0 +1,33 @@
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
+
6
+ const METADATA_KEY = 'chronicle:reactor:startAtTail';
7
+
8
+ /**
9
+ * A new reactor normally catches up from the beginning of the event sequence, so one whose handlers have side
10
+ * effects acts on every historical event the moment it is deployed. `@onceOnly()` does not prevent that, because it
11
+ * only excludes replay.
12
+ *
13
+ * Marks a reactor class so that the first time Chronicle sees it, it begins at the tail of the event sequence and
14
+ * observes only what is appended from then on. A reactor that already has a position keeps it, so the marker is safe
15
+ * to leave in place. Renaming the reactor or moving it changes its default id and makes it a new reactor, which
16
+ * starts at the tail again, unless an explicit id is given to `@reactor()`. An explicit replay still replays from the
17
+ * beginning. Both the Chronicle server and the client must support it; a server that predates it ignores the request.
18
+ * The marker is not inherited by subclasses.
19
+ * @returns A class decorator for legacy and standard TypeScript decorators.
20
+ */
21
+ export function startAtTail(): ClassDecorator & ((value: Function, context: ClassDecoratorContext) => void) {
22
+ return (target: object, context?: ClassDecoratorContext) => {
23
+ if (typeof context === 'object' && context.kind !== 'class') {
24
+ throw new TypeError('Start-at-tail can only decorate a reactor class.');
25
+ }
26
+ Reflect.defineMetadata(METADATA_KEY, true, target);
27
+ };
28
+ }
29
+
30
+ /** Whether this reactor class is marked to start at the tail (without inheriting the marker). */
31
+ export function isStartAtTail(target: Function): boolean {
32
+ return Reflect.getOwnMetadata(METADATA_KEY, target) === true;
33
+ }
@@ -0,0 +1,26 @@
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 { field } from '@cratis/fundamentals';
6
+ import { fromEvent } from '../../../projections/modelBound/fromEvent.js';
7
+ import { setValue } from '../../../projections/modelBound/setValue.js';
8
+ import { BookRegistered } from './BookRegistered.js';
9
+ import { BookBorrowed } from './BookBorrowed.js';
10
+ import { BookReturned } from './BookReturned.js';
11
+
12
+ export class Book {
13
+ id = '';
14
+ title: string | null = null;
15
+ isbn: string | null = null;
16
+ borrowed = false;
17
+ }
18
+ field(String)(Book.prototype, 'id');
19
+ field(String)(Book.prototype, 'title');
20
+ field(String)(Book.prototype, 'isbn');
21
+ field(Boolean)(Book.prototype, 'borrowed');
22
+ fromEvent(BookRegistered)(Book);
23
+ fromEvent(BookBorrowed)(Book);
24
+ fromEvent(BookReturned)(Book);
25
+ setValue(BookBorrowed, true)(Book.prototype, 'borrowed');
26
+ setValue(BookReturned, false)(Book.prototype, 'borrowed');
@@ -0,0 +1,4 @@
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
+ export class BookBorrowed {}
@@ -0,0 +1,7 @@
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
+ export class BookRegistered {
5
+ title = '';
6
+ isbn = '';
7
+ }
@@ -0,0 +1,4 @@
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
+ export class BookReturned {}
@@ -0,0 +1,30 @@
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 { beforeEach, chai, describe, it, vi } from 'vitest';
5
+ import type { IClientArtifactsProvider } from '../../../artifacts/index.js';
6
+ import type { ChronicleConnection } from '../../../connection/index.js';
7
+ import { ReadModels } from '../../ReadModels.js';
8
+ import { Book } from '../given/Book.js';
9
+
10
+ const should = chai.should();
11
+
12
+ for (const borrowed of [true, false]) {
13
+ describe(`when reading a model-bound projection after a book is ${borrowed ? 'borrowed' : 'returned'} without registration fields`, () => {
14
+ let result: Book;
15
+
16
+ beforeEach(async () => {
17
+ const connection = {
18
+ readModels: { getInstanceByKey: vi.fn().mockResolvedValue({ ReadModel: JSON.stringify({ id: 'book', borrowed }) }) }
19
+ } as unknown as ChronicleConnection;
20
+ const artifacts = { readModels: [Book], projections: [], reducers: [] } as unknown as IClientArtifactsProvider;
21
+ const readModels = new ReadModels('store', 'tenant', connection, artifacts, 'sink');
22
+ result = await readModels.getInstanceById(Book, 'book');
23
+ });
24
+
25
+ it('should restore the model type', () => result.should.be.instanceOf(Book));
26
+ it('should keep the title null', () => should.equal(result.title, null));
27
+ it('should keep the isbn null', () => should.equal(result.isbn, null));
28
+ it('should restore the borrowed state', () => result.borrowed.should.equal(borrowed));
29
+ });
30
+ }
@@ -0,0 +1,12 @@
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 { field } from '@cratis/fundamentals';
6
+
7
+ export class Address {
8
+ street = 'Default street';
9
+ city: string | null = null;
10
+ }
11
+ field(String)(Address.prototype, 'street');
12
+ field(String)(Address.prototype, 'city');
@@ -0,0 +1,15 @@
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 { field } from '@cratis/fundamentals';
6
+
7
+ export class IdentityDefaults {
8
+ original = {};
9
+ mirror = this.original;
10
+ owner = this;
11
+ name = 'default';
12
+ }
13
+ field(Object)(IdentityDefaults.prototype, 'mirror');
14
+ field(Object)(IdentityDefaults.prototype, 'owner');
15
+ field(String)(IdentityDefaults.prototype, 'name');
@@ -0,0 +1,22 @@
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 { field } from '@cratis/fundamentals';
6
+
7
+ export class SetterDefaults {
8
+ sibling = 'default';
9
+ assignments = 0;
10
+ private _name = 'default';
11
+
12
+ get name(): string {
13
+ return this._name;
14
+ }
15
+
16
+ set name(value: string) {
17
+ this.assignments++;
18
+ this._name = `prefix:${value}`;
19
+ }
20
+ }
21
+ field(String)(SetterDefaults.prototype, 'name');
22
+ field(String)(SetterDefaults.prototype, 'sibling');
@@ -0,0 +1,18 @@
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 { field } from '@cratis/fundamentals';
6
+
7
+ import { Address } from './Address.js';
8
+
9
+ export class Model {
10
+ title: string | null = null;
11
+ status = 'available';
12
+ address = new Address();
13
+ children = [new Address()];
14
+ }
15
+ field(String)(Model.prototype, 'title');
16
+ field(String)(Model.prototype, 'status');
17
+ field(Address)(Model.prototype, 'address');
18
+ field(Array, { genericArguments: [Address] })(Model.prototype, 'children');
@@ -0,0 +1,20 @@
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 { beforeEach, chai, describe, it } from 'vitest';
5
+ import { deserializeReadModel } from '../../deserializeReadModel.js';
6
+ import { SetterDefaults } from '../given/SetterDefaults.fixture.js';
7
+
8
+ chai.should();
9
+
10
+ describe('when restoring with a non-idempotent setter and an absent sibling', () => {
11
+ let result: SetterDefaults;
12
+
13
+ beforeEach(() => {
14
+ result = deserializeReadModel(SetterDefaults, '{"name":"stored"}');
15
+ });
16
+
17
+ it('should apply the setter transformation once', () => result.name.should.equal('prefix:stored'));
18
+ it('should invoke the setter once', () => result.assignments.should.equal(1));
19
+ it('should keep the absent sibling default', () => result.sibling.should.equal('default'));
20
+ });
@@ -0,0 +1,31 @@
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 { beforeEach, chai, describe, it } from 'vitest';
5
+ import { deserializeReadModel } from '../../deserializeReadModel.js';
6
+ import { Model } from '../given/a_read_model_with_defaults.js';
7
+ import { Address } from '../given/Address.js';
8
+
9
+ const should = chai.should();
10
+
11
+ describe('when restoring with a partial nested object', () => {
12
+ let result: Model;
13
+
14
+ beforeEach(() => {
15
+ result = deserializeReadModel(Model, '{"address":{"city":"Oslo"}}');
16
+ });
17
+
18
+ it('should restore the nested type', () => result.address.should.be.instanceOf(Address));
19
+ it('should keep the absent nested field default', () => result.address.street.should.equal('Default street'));
20
+ it('should replace the present nested field default', () => result.address.city!.should.equal('Oslo'));
21
+ });
22
+
23
+ describe('when restoring with explicit null in a nested object', () => {
24
+ let result: Model;
25
+
26
+ beforeEach(() => {
27
+ result = deserializeReadModel(Model, '{"address":{"street":null}}');
28
+ });
29
+
30
+ it('should replace the non-null nested field default', () => should.equal(result.address.street, null));
31
+ });
@@ -0,0 +1,22 @@
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 { beforeEach, chai, describe, it } from 'vitest';
5
+ import { deserializeReadModel } from '../../deserializeReadModel.js';
6
+ import { Model } from '../given/a_read_model_with_defaults.js';
7
+ import { Address } from '../given/Address.js';
8
+
9
+ const should = chai.should();
10
+
11
+ describe('when restoring with absent fields', () => {
12
+ let result: Model;
13
+
14
+ beforeEach(() => {
15
+ result = deserializeReadModel(Model, '{}');
16
+ });
17
+
18
+ it('should keep the null default', () => should.equal(result.title, null));
19
+ it('should keep the non-null default', () => result.status.should.equal('available'));
20
+ it('should keep the nested object default', () => result.address.should.deep.equal(new Address()));
21
+ it('should deserialize an absent array to an empty array', () => result.children.should.deep.equal([]));
22
+ });
@@ -0,0 +1,20 @@
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 { beforeEach, chai, describe, it } from 'vitest';
5
+ import { deserializeReadModel } from '../../deserializeReadModel.js';
6
+ import { Model } from '../given/a_read_model_with_defaults.js';
7
+
8
+ const should = chai.should();
9
+
10
+ describe('when restoring with explicit null', () => {
11
+ let result: Model;
12
+
13
+ beforeEach(() => {
14
+ result = deserializeReadModel(Model, '{"status":null,"address":null,"children":null}');
15
+ });
16
+
17
+ it('should replace the non-null scalar default', () => should.equal(result.status, null));
18
+ it('should replace the nested object default', () => should.equal(result.address, null));
19
+ it('should replace the array default', () => should.equal(result.children, null));
20
+ });
@@ -0,0 +1,20 @@
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 { beforeEach, chai, describe, it } from 'vitest';
5
+ import { deserializeReadModel } from '../../deserializeReadModel.js';
6
+ import { IdentityDefaults } from '../given/IdentityDefaults.fixture.js';
7
+
8
+ chai.should();
9
+
10
+ describe('when restoring with identity-dependent defaults', () => {
11
+ let result: IdentityDefaults;
12
+
13
+ beforeEach(() => {
14
+ result = deserializeReadModel(IdentityDefaults, '{"name":"stored"}');
15
+ });
16
+
17
+ it('should keep the default referencing another member identical to that member', () => result.mirror.should.equal(result.original));
18
+ it('should keep the default referencing its owner identical to the returned instance', () => result.owner.should.equal(result));
19
+ it('should still replace a present decorated field', () => result.name.should.equal('stored'));
20
+ });
@@ -0,0 +1,23 @@
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 { beforeEach, chai, describe, it } from 'vitest';
5
+ import { deserializeReadModel } from '../../deserializeReadModel.js';
6
+ import { Model } from '../given/a_read_model_with_defaults.js';
7
+ import { Address } from '../given/Address.js';
8
+
9
+ const should = chai.should();
10
+
11
+ describe('when restoring with partial array items', () => {
12
+ let result: Model;
13
+
14
+ beforeEach(() => {
15
+ result = deserializeReadModel(Model, '{"children":[{}, {"street":"Stored street","city":null}]}');
16
+ });
17
+
18
+ it('should replace the array default', () => result.children.should.have.lengthOf(2));
19
+ it('should restore the child type', () => result.children[0].should.be.instanceOf(Address));
20
+ it('should keep the absent child field default', () => result.children[0].street.should.equal('Default street'));
21
+ it('should replace the present child field default', () => result.children[1].street.should.equal('Stored street'));
22
+ it('should preserve the null child field', () => should.equal(result.children[1].city, null));
23
+ });
@@ -0,0 +1,19 @@
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 { beforeEach, chai, describe, it } from 'vitest';
5
+ import { deserializeReadModel } from '../../deserializeReadModel.js';
6
+ import { Model } from '../given/a_read_model_with_defaults.js';
7
+
8
+ chai.should();
9
+
10
+ describe('when restoring with present fields', () => {
11
+ let result: Model;
12
+
13
+ beforeEach(() => {
14
+ result = deserializeReadModel(Model, '{"title":"Stored title","status":"borrowed"}');
15
+ });
16
+
17
+ it('should replace the null default', () => result.title!.should.equal('Stored title'));
18
+ it('should replace the non-null default', () => result.status.should.equal('borrowed'));
19
+ });
@@ -168,11 +168,11 @@ describe('fixture-backed unique scalar values', () => {
168
168
  const results = scenario.results;
169
169
  const unprovenKeys = ['!', '#', '%', '&', "'", '(', ')', '*', '+', ',', '/', ';', '<', '=', '>', '?', '[', ']', '^', '`', '~'];
170
170
  const invalidContent: unknown[] = [1, 0, 1.5, undefined, [], {}, new Date(), 'É', 'e\u0301', '"', '\\', '\n'];
171
- // The production serializer throws on null before checkedContent can run.
171
+ // Fundamentals preserves null in JSON, so checkedContent rejects it as unsupported string content.
172
172
  for (const [value, operation] of [
173
173
  ...unprovenKeys.map(value => [value, 'artifacts.constraints']),
174
174
  ...invalidContent.map(value => [value, 'append.content']),
175
- [null, 'append.serialization']
175
+ [null, 'append.content']
176
176
  ] as Array<[unknown, string]>) {
177
177
  const bad = new OracleDomainText('valid');
178
178
  Object.assign(bad, { key: value });
@@ -83,7 +83,7 @@ describe('when evaluating arithmetic with legacy model-bound decorators', () =>
83
83
  it('should suppress aggregate-only AutoMap and restore it for mixed mappings', async () => {
84
84
  const scenario = new ReadModelScenario(Totals, artifacts);
85
85
  scenario.given.forEventSource('A').events(new Added(2));
86
- ((await scenario.instance)!.title === undefined).should.be.true;
86
+ (await scenario.instance)!.title.should.equal('');
87
87
  scenario.given.forEventSource('A').events(new Renamed());
88
88
  const result = (await scenario.instance)!;
89
89
  [result.total, result.title, result.label].should.deep.equal([3, 'automapped', 'explicit']);
@@ -84,7 +84,7 @@ describe('when evaluating arithmetic with standard model-bound decorators', () =
84
84
  it('should suppress aggregate-only AutoMap and restore it for mixed mappings', async () => {
85
85
  const scenario = new ReadModelScenario(Totals, artifacts);
86
86
  scenario.given.forEventSource('A').events(new Added(2));
87
- should((await scenario.instance)!.title === undefined).be.true;
87
+ should((await scenario.instance)!.title).equal('');
88
88
  scenario.given.forEventSource('A').events(new Renamed());
89
89
  const result = (await scenario.instance)!;
90
90
  should([result.total, result.title, result.label]).deep.equal([3, 'automapped', 'explicit']);
@@ -61,7 +61,7 @@ describe('when evaluating a fluent root join', () => {
61
61
  scenario.given.forEventSource('customer').events(new CustomerNamed('name'));
62
62
  (await scenario.instanceForEventSourceId('A'))!.customerName.should.equal('name');
63
63
  (await scenario.instanceForEventSourceId('B'))!.customerName.should.equal('name');
64
- ((await scenario.instanceForEventSourceId('C'))!.customerName === undefined).should.be.true;
64
+ (await scenario.instanceForEventSourceId('C'))!.customerName.should.equal('');
65
65
  });
66
66
 
67
67
  it('should retain joined history across removal without resurrecting the removed root', async () => {
@@ -95,7 +95,7 @@ describe('when evaluating a fluent root join', () => {
95
95
  (await first.instance)!.customerName.should.equal('second');
96
96
  const second = new ReadModelScenario(Order, artifacts);
97
97
  second.given.forEventSource('A').events(new OrderPlaced('customer'));
98
- ((await second.instance)!.customerName === undefined).should.be.true;
98
+ (await second.instance)!.customerName.should.equal('');
99
99
  });
100
100
 
101
101
  it('should update the root keys when observing a committed event sequence', async () => {
@@ -47,8 +47,8 @@ describe('when evaluating joins with legacy model-bound decorators', () => {
47
47
  const result = (await scenario.instance)!;
48
48
  result.customerName.should.equal('before');
49
49
  result.city.should.equal('Oslo');
50
- (result.name === undefined).should.be.true;
51
- (result.ignored === undefined).should.be.true;
50
+ result.name.should.equal('');
51
+ result.ignored.should.equal('');
52
52
  });
53
53
 
54
54
  it('should update existing roots and recreate a removed root from the latest joined history', async () => {
@@ -44,8 +44,8 @@ describe('when evaluating joins with standard model-bound decorators', () => {
44
44
  const result = (await scenario.instance)!;
45
45
  result.customerName.should.equal('before');
46
46
  result.city.should.equal('Oslo');
47
- (result.name === undefined).should.be.true;
48
- (result.ignored === undefined).should.be.true;
47
+ result.name.should.equal('');
48
+ result.ignored.should.equal('');
49
49
  });
50
50
 
51
51
  it('should fan out subsequent join events to all matching roots', async () => {
@@ -1,12 +1,13 @@
1
1
  // Copyright (c) Cratis. All rights reserved.
2
2
  // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
3
 
4
- import type {
5
- BasicAuthorization,
6
- BearerTokenAuthorization,
7
- OAuthAuthorization,
8
- OneOfBasicAuthorizationBearerTokenAuthorizationOAuthAuthorization,
9
- WebhookDefinition
4
+ import {
5
+ EventGenerationDelivery,
6
+ type BasicAuthorization,
7
+ type BearerTokenAuthorization,
8
+ type OAuthAuthorization,
9
+ type OneOfBasicAuthorizationBearerTokenAuthorizationOAuthAuthorization,
10
+ type WebhookDefinition
10
11
  } from '@cratis/chronicle.contracts';
11
12
  import { Constructor } from '@cratis/fundamentals';
12
13
  import { IEventTypes } from '../events/IEventTypes.js';
@@ -140,7 +141,8 @@ export class WebhookDefinitionBuilder implements IWebhookDefinitionBuilder {
140
141
  IsReplayable: this._isReplayable,
141
142
  IsActive: this._isActive,
142
143
  IsNotReplayable: !this._isReplayable,
143
- IsInactive: !this._isActive
144
+ IsInactive: !this._isActive,
145
+ GenerationDelivery: EventGenerationDelivery.Compatibility
144
146
  };
145
147
  }
146
148
  }
@@ -104,7 +104,8 @@ export class Webhooks implements IWebhooks {
104
104
  IsReplayable: webhook.IsReplayable,
105
105
  IsActive: webhook.IsActive,
106
106
  IsNotReplayable: !webhook.IsReplayable,
107
- IsInactive: !webhook.IsActive
107
+ IsInactive: !webhook.IsActive,
108
+ GenerationDelivery: webhook.GenerationDelivery
108
109
  }));
109
110
  }
110
111