@cratis/chronicle 4.0.0 → 5.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.
Files changed (48) hide show
  1. package/ChronicleClient.ts +3 -3
  2. package/EventStore.ts +3 -3
  3. package/connection/ChronicleConnection.ts +6 -0
  4. package/connection/ChronicleServices.ts +2 -0
  5. package/connection/callResults.ts +23 -0
  6. package/dist/ChronicleClient.js +3 -3
  7. package/dist/ChronicleClient.js.map +1 -1
  8. package/dist/EventStore.js +3 -3
  9. package/dist/EventStore.js.map +1 -1
  10. package/dist/connection/ChronicleConnection.d.ts +1 -0
  11. package/dist/connection/ChronicleConnection.d.ts.map +1 -1
  12. package/dist/connection/ChronicleConnection.js +5 -1
  13. package/dist/connection/ChronicleConnection.js.map +1 -1
  14. package/dist/connection/ChronicleServices.d.ts +2 -1
  15. package/dist/connection/ChronicleServices.d.ts.map +1 -1
  16. package/dist/connection/callResults.d.ts +13 -0
  17. package/dist/connection/callResults.d.ts.map +1 -1
  18. package/dist/connection/callResults.js +14 -0
  19. package/dist/connection/callResults.js.map +1 -1
  20. package/dist/eventSequences/EventSequence.d.ts +2 -2
  21. package/dist/eventSequences/EventSequence.d.ts.map +1 -1
  22. package/dist/eventSequences/EventSequence.js +39 -57
  23. package/dist/eventSequences/EventSequence.js.map +1 -1
  24. package/dist/events/EventTypes.d.ts.map +1 -1
  25. package/dist/events/EventTypes.js +3 -2
  26. package/dist/events/EventTypes.js.map +1 -1
  27. package/dist/jobs/Jobs.js +3 -3
  28. package/dist/jobs/Jobs.js.map +1 -1
  29. package/dist/observation/toObserverRunningState.js +1 -1
  30. package/dist/observation/toObserverRunningState.js.map +1 -1
  31. package/dist/readModels/ReadModels.d.ts.map +1 -1
  32. package/dist/readModels/ReadModels.js +8 -6
  33. package/dist/readModels/ReadModels.js.map +1 -1
  34. package/dist/seeding/EventSeeding.d.ts.map +1 -1
  35. package/dist/seeding/EventSeeding.js +2 -1
  36. package/dist/seeding/EventSeeding.js.map +1 -1
  37. package/dist/webhooks/Webhooks.d.ts.map +1 -1
  38. package/dist/webhooks/Webhooks.js +22 -10
  39. package/dist/webhooks/Webhooks.js.map +1 -1
  40. package/eventSequences/EventSequence.spec.ts +83 -74
  41. package/eventSequences/EventSequence.ts +44 -63
  42. package/events/EventTypes.ts +3 -2
  43. package/jobs/Jobs.ts +3 -3
  44. package/observation/toObserverRunningState.ts +1 -1
  45. package/package.json +6 -6
  46. package/readModels/ReadModels.ts +8 -6
  47. package/seeding/EventSeeding.ts +2 -1
  48. package/webhooks/Webhooks.ts +24 -10
@@ -3,7 +3,7 @@
3
3
 
4
4
  import { ChronicleConnection } from '../connection';
5
5
  import { SpanStatusCode } from '@opentelemetry/api';
6
- import type { AppendedEvent as ContractsAppendedEvent } from '@cratis/chronicle.contracts';
6
+ import type { AppendedEventResponse as ContractsAppendedEvent } from '@cratis/chronicle.contracts';
7
7
  import { Constructor, Guid, JsonSerializer } from '@cratis/fundamentals';
8
8
  import { getEventTypeFor } from '../events/eventTypeDecorator';
9
9
  import type { AppendedEvent } from '../events/AppendedEvent';
@@ -40,6 +40,7 @@ import { identityProvider, Identity } from '../identity';
40
40
  import { causationManager, CausationType } from '../auditing';
41
41
  import { correlationIdManager } from '../correlation';
42
42
  import { fromContractsGuid, toContractsGuid } from '../connection/Guid';
43
+ import { ensureCommandResponse, ensureCommandSuccess, ensureQuerySuccess } from '../connection/callResults';
43
44
  import type { ConcurrencyScope } from './ConcurrencyScope';
44
45
  import { IUnitOfWorkManager } from '../transactions/IUnitOfWorkManager';
45
46
 
@@ -67,7 +68,7 @@ export class EventSequence implements IEventSequence {
67
68
  const correlationId = options?.correlationId === undefined
68
69
  ? Guid.as(correlationIdManager.current.value)
69
70
  : Guid.as(options.correlationId);
70
- const content = JsonSerializer.serialize(event);
71
+ const content = JSON.parse(JsonSerializer.serialize(event));
71
72
 
72
73
  // Merge static tags declared on the event type with tags supplied at append time.
73
74
  const tags = mergeTags(getTagsFor(event.constructor as Function), options?.tags);
@@ -119,12 +120,13 @@ export class EventSequence implements IEventSequence {
119
120
  Subject: eventSourceId
120
121
  });
121
122
 
123
+ const appendResponse = ensureCommandResponse('append event', response);
122
124
  const duration = Date.now() - startTime;
123
125
  const result = this.mapAppendResponse(
124
- response.SequenceNumber,
125
- response.ConstraintViolations ?? [],
126
- response.Errors ?? [],
127
- response.ConcurrencyViolation
126
+ appendResponse.SequenceNumber,
127
+ appendResponse.ConstraintViolations ?? [],
128
+ appendResponse.Errors ?? [],
129
+ appendResponse.ConcurrencyViolation
128
130
  );
129
131
  span.setAttribute('chronicle.sequence_number', result.sequenceNumber.value.toString());
130
132
  span.setStatus({ code: SpanStatusCode.OK });
@@ -247,13 +249,7 @@ export class EventSequence implements IEventSequence {
247
249
  Generation: eventType.generation.value,
248
250
  Tombstone: eventType.tombstone
249
251
  },
250
- Content: JsonSerializer.serialize(event),
251
- Causation: batchCausationChain.map(c => ({
252
- Occurred: { Value: c.occurred.toISOString() },
253
- Type: c.type.name,
254
- Properties: { ...c.properties }
255
- })),
256
- CausedBy: toContractsCausedBy(identity),
252
+ Content: JSON.parse(JsonSerializer.serialize(event)),
257
253
  Tags: tags,
258
254
  Occurred: undefined,
259
255
  Subject: subject ?? eventSourceId
@@ -279,7 +275,7 @@ export class EventSequence implements IEventSequence {
279
275
  span.setAttribute('chronicle.events_count', eventsForEventSourceIds.length);
280
276
  const startTime = Date.now();
281
277
  try {
282
- const response = await this._connection.eventSequences.appendMany({
278
+ const response = await this._connection.eventSequences.appendManyForEventSources({
283
279
  EventStore: this._eventStoreName,
284
280
  Namespace: this._namespace,
285
281
  EventSequenceId: this.id.value,
@@ -291,21 +287,23 @@ export class EventSequence implements IEventSequence {
291
287
  Properties: { ...c.properties }
292
288
  })),
293
289
  CausedBy: toContractsCausedBy(identity),
294
- ConcurrencyScopes: {
295
- ...Object.fromEntries(distinctEventSourceIds.map(eventSourceId => [eventSourceId, resolveConcurrencyScope(eventSourceId)]))
296
- }
290
+ ConcurrencyScopes: distinctEventSourceIds.map(eventSourceId => ({
291
+ EventSourceId: eventSourceId,
292
+ Scope: resolveConcurrencyScope(eventSourceId)
293
+ }))
297
294
  });
298
295
 
296
+ const appendManyResponse = ensureCommandResponse('append many events', response);
299
297
  const duration = Date.now() - startTime;
300
298
  // Mirrors the C# client: every per-event AppendResult in a batch carries all
301
299
  // constraint violations and the first concurrency violation of the whole batch —
302
300
  // the wire response doesn't correlate either back to a specific event index.
303
- const firstConcurrencyViolation = (response.ConcurrencyViolations ?? [])[0];
304
- const result = (response.SequenceNumbers ?? []).map((sequenceNumber: bigint, index: number) =>
301
+ const firstConcurrencyViolation = (appendManyResponse.ConcurrencyViolations ?? [])[0];
302
+ const result = (appendManyResponse.SequenceNumbers ?? []).map((sequenceNumber: bigint, index: number) =>
305
303
  this.mapAppendResponse(
306
304
  sequenceNumber,
307
- response.ConstraintViolations ?? [],
308
- (response.Errors ?? []).filter((_: string, errorIndex: number) => errorIndex === index),
305
+ appendManyResponse.ConstraintViolations ?? [],
306
+ (appendManyResponse.Errors ?? []).filter((_: string, errorIndex: number) => errorIndex === index),
309
307
  firstConcurrencyViolation
310
308
  )
311
309
  );
@@ -398,18 +396,19 @@ export class EventSequence implements IEventSequence {
398
396
  span.setAttribute('chronicle.event_source_id', eventSourceId);
399
397
  }
400
398
  try {
401
- const response = await this._connection.eventSequences.getTailSequenceNumber({
399
+ const response = await this._connection.eventSequences.tailSequenceNumber({
402
400
  EventStore: this._eventStoreName,
403
401
  Namespace: this._namespace,
404
402
  EventSequenceId: this.id.value,
405
403
  EventSourceId: eventSourceId ?? '',
406
- EventTypes: this.toContractEventTypes(filterEventTypes ?? []),
404
+ EventTypeIds: this.joinEventTypeIds(filterEventTypes ?? []),
407
405
  EventSourceType: eventSourceType ?? 'Default',
408
406
  EventStreamId: eventStreamId ?? '',
409
407
  EventStreamType: eventStreamType ?? 'Default'
410
408
  });
411
409
 
412
- const result = new EventSequenceNumber(response.SequenceNumber ?? 0n);
410
+ const data = ensureQuerySuccess('get tail sequence number', response);
411
+ const result = new EventSequenceNumber(data?.SequenceNumber ?? 0n);
413
412
  span.setAttribute('chronicle.sequence_number', result.value.toString());
414
413
  span.setStatus({ code: SpanStatusCode.OK });
415
414
  return result;
@@ -444,7 +443,7 @@ export class EventSequence implements IEventSequence {
444
443
  EventSourceId: eventSourceId
445
444
  });
446
445
 
447
- const result = response.HasEvents ?? false;
446
+ const result = ensureQuerySuccess('has events for event source', response)?.HasEvents ?? false;
448
447
  span.setAttribute('chronicle.has_events', result);
449
448
  span.setStatus({ code: SpanStatusCode.OK });
450
449
  return result;
@@ -464,7 +463,8 @@ export class EventSequence implements IEventSequence {
464
463
  eventTypes: Constructor[],
465
464
  eventStreamType?: string,
466
465
  eventStreamId?: string,
467
- eventSourceType?: string
466
+ // Kept for IEventSequence signature compatibility; the wire no longer carries an event source type for this query.
467
+ _eventSourceType?: string
468
468
  ): Promise<AppendedEvent[]> {
469
469
  return ChronicleTracer.startActiveSpan('chronicle.event_sequences.get_for_event_source_id_and_event_types', async span => {
470
470
  span.setAttribute('chronicle.event_store', this._eventStoreName);
@@ -472,18 +472,17 @@ export class EventSequence implements IEventSequence {
472
472
  span.setAttribute('chronicle.event_sequence_id', this.id.value);
473
473
  span.setAttribute('chronicle.event_source_id', eventSourceId);
474
474
  try {
475
- const response = await this._connection.eventSequences.getForEventSourceIdAndEventTypes({
475
+ const response = await this._connection.eventSequences.forEventSourceIdAndEventTypes({
476
476
  EventStore: this._eventStoreName,
477
477
  Namespace: this._namespace,
478
478
  EventSequenceId: this.id.value,
479
- EventSourceType: eventSourceType ?? 'Default',
480
479
  EventSourceId: eventSourceId,
481
480
  EventStreamType: eventStreamType ?? 'Default',
482
481
  EventStreamId: eventStreamId ?? '',
483
- EventTypes: this.toContractEventTypes(eventTypes)
482
+ EventTypeIds: this.joinEventTypeIds(eventTypes)
484
483
  });
485
484
 
486
- const result = (response.Events ?? []).map(event => this.toClientAppendedEvent(event));
485
+ const result = ensureQuerySuccess('get events for event source id and event types', response).map(event => this.toClientAppendedEvent(event));
487
486
  span.setStatus({ code: SpanStatusCode.OK });
488
487
  return result;
489
488
  } catch (error) {
@@ -508,17 +507,16 @@ export class EventSequence implements IEventSequence {
508
507
  span.setAttribute('chronicle.event_sequence_id', this.id.value);
509
508
  span.setAttribute('chronicle.sequence_number', sequenceNumber.value.toString());
510
509
  try {
511
- const response = await this._connection.eventSequences.getEventsFromEventSequenceNumber({
510
+ const response = await this._connection.eventSequences.fromSequenceNumber({
512
511
  EventStore: this._eventStoreName,
513
512
  Namespace: this._namespace,
514
513
  EventSequenceId: this.id.value,
515
514
  FromEventSequenceNumber: sequenceNumber.value,
516
- ToEventSequenceNumber: 0n,
517
515
  EventSourceId: eventSourceId ?? '',
518
- EventTypes: this.toContractEventTypes(filterEventTypes ?? [])
516
+ EventTypeIds: this.joinEventTypeIds(filterEventTypes ?? [])
519
517
  });
520
518
 
521
- const result = (response.Events ?? []).map(event => this.toClientAppendedEvent(event));
519
+ const result = ensureQuerySuccess('get events from sequence number', response).map(event => this.toClientAppendedEvent(event));
522
520
  span.setStatus({ code: SpanStatusCode.OK });
523
521
  return result;
524
522
  } catch (error) {
@@ -536,7 +534,6 @@ export class EventSequence implements IEventSequence {
536
534
  causationManager.add(CausationType.redact, { sequenceNumber: sequenceNumber.value.toString() });
537
535
  const causationChain = causationManager.getCurrentChain();
538
536
  const identity = identityProvider.getCurrent();
539
- const correlationId = Guid.as(correlationIdManager.current.value);
540
537
 
541
538
  return ChronicleTracer.startActiveSpan('chronicle.event_sequences.redact', async span => {
542
539
  span.setAttribute('chronicle.event_store', this._eventStoreName);
@@ -544,20 +541,19 @@ export class EventSequence implements IEventSequence {
544
541
  span.setAttribute('chronicle.event_sequence_id', this.id.value);
545
542
  span.setAttribute('chronicle.sequence_number', sequenceNumber.value.toString());
546
543
  try {
547
- await this._connection.eventSequences.redact({
544
+ ensureCommandSuccess('redact event', await this._connection.eventSequences.redact({
548
545
  EventStore: this._eventStoreName,
549
546
  Namespace: this._namespace,
550
547
  EventSequenceId: this.id.value,
551
548
  SequenceNumber: sequenceNumber.value,
552
549
  Reason: reason,
553
- CorrelationId: toContractsGuid(correlationId),
554
550
  Causation: causationChain.map(c => ({
555
551
  Occurred: { Value: c.occurred.toISOString() },
556
552
  Type: c.type.name,
557
553
  Properties: { ...c.properties }
558
554
  })),
559
555
  CausedBy: toContractsCausedBy(identity)
560
- });
556
+ }));
561
557
  span.setStatus({ code: SpanStatusCode.OK });
562
558
  } catch (error) {
563
559
  span.setStatus({ code: SpanStatusCode.ERROR, message: String(error) });
@@ -574,15 +570,7 @@ export class EventSequence implements IEventSequence {
574
570
  causationManager.add(CausationType.redactForEventSource, { eventSourceId });
575
571
  const causationChain = causationManager.getCurrentChain();
576
572
  const identity = identityProvider.getCurrent();
577
- const correlationId = Guid.as(correlationIdManager.current.value);
578
- const wireEventTypes = (eventTypes ?? []).map(constructor => {
579
- const eventType = getEventTypeFor(constructor as unknown as Function);
580
- return {
581
- Id: eventType.id.value,
582
- Generation: eventType.generation.value,
583
- Tombstone: eventType.tombstone
584
- };
585
- });
573
+ const wireEventTypeIds = (eventTypes ?? []).map(constructor => getEventTypeFor(constructor as unknown as Function).id.value);
586
574
 
587
575
  return ChronicleTracer.startActiveSpan('chronicle.event_sequences.redact_for_event_source', async span => {
588
576
  span.setAttribute('chronicle.event_store', this._eventStoreName);
@@ -590,21 +578,20 @@ export class EventSequence implements IEventSequence {
590
578
  span.setAttribute('chronicle.event_sequence_id', this.id.value);
591
579
  span.setAttribute('chronicle.event_source_id', eventSourceId);
592
580
  try {
593
- await this._connection.eventSequences.redactForEventSource({
581
+ ensureCommandSuccess('redact event source', await this._connection.eventSequences.redactForEventSource({
594
582
  EventStore: this._eventStoreName,
595
583
  Namespace: this._namespace,
596
584
  EventSequenceId: this.id.value,
597
585
  EventSourceId: eventSourceId,
598
586
  Reason: reason,
599
- EventTypes: wireEventTypes,
600
- CorrelationId: toContractsGuid(correlationId),
587
+ EventTypes: wireEventTypeIds,
601
588
  Causation: causationChain.map(c => ({
602
589
  Occurred: { Value: c.occurred.toISOString() },
603
590
  Type: c.type.name,
604
591
  Properties: { ...c.properties }
605
592
  })),
606
593
  CausedBy: toContractsCausedBy(identity)
607
- });
594
+ }));
608
595
  span.setStatus({ code: SpanStatusCode.OK });
609
596
  } catch (error) {
610
597
  span.setStatus({ code: SpanStatusCode.ERROR, message: String(error) });
@@ -649,9 +636,10 @@ export class EventSequence implements IEventSequence {
649
636
  EventStreamId: eventStreamId
650
637
  });
651
638
 
652
- const result: CompleteStreamResult = response.IsSuccess
653
- ? { isSuccess: true, sequenceNumber: new EventSequenceNumber(response.SequenceNumber ?? 0n) }
654
- : { isSuccess: false, error: this.toClientCompleteStreamError(response.Error) };
639
+ const completeStreamResponse = ensureCommandResponse('complete stream', response);
640
+ const result: CompleteStreamResult = completeStreamResponse.IsSuccess
641
+ ? { isSuccess: true, sequenceNumber: new EventSequenceNumber(completeStreamResponse.SequenceNumber ?? 0n) }
642
+ : { isSuccess: false, error: this.toClientCompleteStreamError(completeStreamResponse.Error) };
655
643
 
656
644
  span.setStatus({ code: SpanStatusCode.OK });
657
645
  return result;
@@ -671,15 +659,8 @@ export class EventSequence implements IEventSequence {
671
659
  return error === 1 ? CompleteStreamError.DefaultStreamCannotBeCompleted : CompleteStreamError.AlreadyCompleted;
672
660
  }
673
661
 
674
- private toContractEventTypes(eventTypes: Constructor[]) {
675
- return eventTypes.map(constructor => {
676
- const eventType = getEventTypeFor(constructor as unknown as Function);
677
- return {
678
- Id: eventType.id.value,
679
- Generation: eventType.generation.value,
680
- Tombstone: eventType.tombstone
681
- };
682
- });
662
+ private joinEventTypeIds(eventTypes: Constructor[]): string {
663
+ return eventTypes.map(constructor => getEventTypeFor(constructor as unknown as Function).id.value).join(',');
683
664
  }
684
665
 
685
666
  private toClientAppendedEvent(wireEvent: ContractsAppendedEvent): AppendedEvent {
@@ -4,6 +4,7 @@
4
4
  import { Constructor } from '@cratis/fundamentals';
5
5
  import { IClientArtifactsProvider } from '../artifacts';
6
6
  import { ChronicleConnection } from '../connection';
7
+ import { ensureCommandSuccess } from '../connection/callResults';
7
8
  import { EventTypeId } from './EventTypeId';
8
9
  import { IEventTypes } from './IEventTypes';
9
10
  import { getEventTypeMetadata, getEventTypeJsonSchemaFor } from './eventTypeDecorator';
@@ -163,11 +164,11 @@ export class EventTypes implements IEventTypes {
163
164
  return;
164
165
  }
165
166
 
166
- await this._connection.eventTypes.register({
167
+ ensureCommandSuccess('register event types', await this._connection.eventTypes.registerEventTypes({
167
168
  EventStore: this._eventStore,
168
169
  Types: registrations,
169
170
  DisableValidation: false
170
- });
171
+ }));
171
172
  }
172
173
 
173
174
  /** @inheritdoc */
package/jobs/Jobs.ts CHANGED
@@ -4,7 +4,7 @@
4
4
  import type { JobSummaryResponse, JobStepSummaryResponse } from '@cratis/chronicle.contracts';
5
5
  import { Guid } from '@cratis/fundamentals';
6
6
  import { ChronicleConnection } from '../connection';
7
- import { ensureCommandSuccess, ensureQuerySuccess, firstQueryResult } from '../connection/callResults';
7
+ import { ensureCommandSuccess, ensureQuerySuccess } from '../connection/callResults';
8
8
  import { fromContractsGuid, toContractsGuid } from '../connection/Guid';
9
9
  import { IJobs } from './IJobs';
10
10
  import { JobId } from './JobId';
@@ -49,10 +49,10 @@ export class Jobs implements IJobs {
49
49
 
50
50
  /** @inheritdoc */
51
51
  async getJobs(): Promise<JobSummaryResponse[]> {
52
- const response = await firstQueryResult('get jobs', this._connection.jobs.allJobs({
52
+ const response = await this._connection.jobs.allJobs({
53
53
  EventStore: this._eventStore,
54
54
  Namespace: this._namespace
55
- }));
55
+ });
56
56
 
57
57
  return ensureQuerySuccess('get jobs', response);
58
58
  }
@@ -17,7 +17,7 @@ export function toObserverRunningState(state: ContractObserverRunningState): Obs
17
17
  return ObserverRunningState.Suspended;
18
18
  case ContractObserverRunningState.Replaying:
19
19
  return ObserverRunningState.Replaying;
20
- case ContractObserverRunningState.Disconnected:
20
+ case ContractObserverRunningState.OBSERVER_RUNNING_STATE_Disconnected:
21
21
  return ObserverRunningState.Disconnected;
22
22
  case ContractObserverRunningState.Quarantined:
23
23
  return ObserverRunningState.Quarantined;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cratis/chronicle",
3
- "version": "4.0.0",
3
+ "version": "5.0.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",
@@ -160,19 +160,19 @@
160
160
  },
161
161
  "dependencies": {
162
162
  "@bufbuild/protobuf": "^2.14.1",
163
- "@cratis/chronicle.contracts": "17.0.0",
163
+ "@cratis/chronicle.contracts": "17.0.4",
164
164
  "@grpc/grpc-js": "^1.14.4",
165
165
  "@opentelemetry/api": "^1.9.1",
166
166
  "nice-grpc": "^2.1.17",
167
167
  "nice-grpc-common": "^2.0.4",
168
168
  "reflect-metadata": "^0.2.2",
169
- "undici": "^8.10.1"
169
+ "undici": "^8.10.2"
170
170
  },
171
171
  "devDependencies": {
172
- "@cratis/fundamentals": "7.18.2",
173
- "@types/node": "^26.4.0",
172
+ "@cratis/fundamentals": "7.18.3",
173
+ "@types/node": "^26.4.1",
174
174
  "typescript": "^6.0.3",
175
- "vitest": "^4.1.11"
175
+ "vitest": "^5.0.0"
176
176
  },
177
177
  "peerDependencies": {
178
178
  "@cratis/fundamentals": "^7.14.0"
@@ -13,6 +13,7 @@ import { Guid, JsonSerializer } from '@cratis/fundamentals';
13
13
  import { IClientArtifactsProvider } from '../artifacts';
14
14
  import { toContractsGuid } from '../connection/Guid';
15
15
  import { ChronicleConnection } from '../connection';
16
+ import { ensureQuerySuccess } from '../connection/callResults';
16
17
  import { EventSequenceId } from '../eventSequences/EventSequenceId';
17
18
  import { getProjectionMetadata } from '../projections/declarative/projection';
18
19
  import { hasFromEventMetadata } from '../projections/modelBound/fromEvent';
@@ -115,16 +116,17 @@ export class ReadModels implements IReadModels {
115
116
  /** @inheritdoc */
116
117
  async getSnapshotsById<TReadModel>(readModelType: Constructor<TReadModel>, key: string): Promise<ReadModelSnapshot<TReadModel>[]> {
117
118
  const readModel = this.resolveReadModel(readModelType);
118
- const response = await this._connection.readModels.getSnapshotsByKey({
119
+ const response = ensureQuerySuccess('get read model snapshots', await this._connection.readModelExplorer.allSnapshotsForReadModel({
119
120
  EventStore: this._eventStore,
120
121
  Namespace: this._namespace,
121
- ReadModelIdentifier: readModel.identifier,
122
+ ReadModel: readModel.identifier,
122
123
  EventSequenceId: readModel.eventSequenceId,
123
- ReadModelKey: key
124
- });
124
+ ReadModelKey: key,
125
+ Grouping: ''
126
+ }));
125
127
 
126
- const snapshots: ReadModelSnapshot<TReadModel>[] = response.Snapshots.map(snapshot => ({
127
- readModel: this.deserializeReadModel(readModelType, snapshot.ReadModel),
128
+ const snapshots: ReadModelSnapshot<TReadModel>[] = response.map(snapshot => ({
129
+ readModel: this.deserializeReadModel(readModelType, snapshot.Instance),
128
130
  events: (snapshot.Events ?? []) as AppendedEvent[],
129
131
  occurred: snapshot.Occurred?.Value ? new Date(snapshot.Occurred.Value) : undefined,
130
132
  correlationId: snapshot.CorrelationId
@@ -4,6 +4,7 @@
4
4
  import { diag } from '@opentelemetry/api';
5
5
  import { IClientArtifactsProvider } from '../artifacts';
6
6
  import { ChronicleConnection } from '../connection';
7
+ import { ensureCommandSuccess } from '../connection/callResults';
7
8
  import { EventStoreNamespaceName } from '../EventStoreNamespaceName';
8
9
  import { getEventTypeFor } from '../events/eventTypeDecorator';
9
10
  import { getTagsFor } from '../events/tagDecorator';
@@ -94,7 +95,7 @@ export class EventSeeding implements IEventSeeding {
94
95
  }))
95
96
  };
96
97
 
97
- await this._connection.eventSeeding.seed(request);
98
+ ensureCommandSuccess('seed events', await this._connection.eventSeeding.seedEvents(request));
98
99
  this._entries.length = 0;
99
100
  }
100
101
 
@@ -1,10 +1,11 @@
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 { ObserverOwner, type WebhookDefinition } from '@cratis/chronicle.contracts';
4
+ import { type WebhookDefinition } from '@cratis/chronicle.contracts';
5
5
  import { Constructor } from '@cratis/fundamentals';
6
6
  import { IClientArtifactsProvider } from '../artifacts';
7
7
  import { ChronicleConnection } from '../connection';
8
+ import { ensureCommandSuccess, ensureQuerySuccess } from '../connection/callResults';
8
9
  import { EventSequenceId } from '../eventSequences/EventSequenceId';
9
10
  import { IEventTypes } from '../events/IEventTypes';
10
11
  import { IWebhook } from './IWebhook';
@@ -59,11 +60,10 @@ export class Webhooks implements IWebhooks {
59
60
  return;
60
61
  }
61
62
 
62
- await this._connection.webhooks.add({
63
+ ensureCommandSuccess('register discovered webhooks', await this._connection.webhooks.addWebhooks({
63
64
  EventStore: this._eventStore,
64
- Owner: ObserverOwner.Client,
65
65
  Webhooks: [...this._discovered.values()]
66
- });
66
+ }));
67
67
  }
68
68
 
69
69
  /** @inheritdoc */
@@ -79,26 +79,40 @@ export class Webhooks implements IWebhooks {
79
79
  configure
80
80
  );
81
81
 
82
- await this._connection.webhooks.add({
82
+ ensureCommandSuccess('register webhook', await this._connection.webhooks.addWebhooks({
83
83
  EventStore: this._eventStore,
84
- Owner: ObserverOwner.Client,
85
84
  Webhooks: [definition]
86
- });
85
+ }));
87
86
  }
88
87
 
89
88
  /** @inheritdoc */
90
89
  async getWebhooks(): Promise<WebhookDefinition[]> {
91
90
  const response = await this._connection.webhooks.getWebhooks({ EventStore: this._eventStore });
92
- return response.items ?? [];
91
+ const details = ensureQuerySuccess('get webhooks', response) ?? [];
92
+
93
+ // The kernel does not return authorization details on read-back, so the reconstructed target
94
+ // always carries no authorization, mirroring the C# client's WebhookTarget mapping.
95
+ return details.map(webhook => ({
96
+ EventSequenceId: webhook.EventSequenceId,
97
+ Identifier: webhook.Identifier,
98
+ EventTypes: webhook.EventTypes,
99
+ Target: {
100
+ Url: webhook.Url,
101
+ Authorization: undefined,
102
+ Headers: webhook.Headers
103
+ },
104
+ IsReplayable: webhook.IsReplayable,
105
+ IsActive: webhook.IsActive
106
+ }));
93
107
  }
94
108
 
95
109
  /** @inheritdoc */
96
110
  async remove(webhookId: WebhookId | string): Promise<void> {
97
111
  const id = typeof webhookId === 'string' ? webhookId : webhookId.value;
98
- await this._connection.webhooks.remove({
112
+ ensureCommandSuccess('remove webhook', await this._connection.webhooks.removeWebhooks({
99
113
  EventStore: this._eventStore,
100
114
  Webhooks: [id]
101
- });
115
+ }));
102
116
  }
103
117
 
104
118
  private buildDefinition(