@cratis/chronicle 0.0.1 → 0.1.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/Auditing/Causation.ts +29 -0
- package/Auditing/CausationManager.ts +51 -0
- package/Auditing/CausationType.ts +38 -0
- package/Auditing/ICausationManager.ts +29 -0
- package/Auditing/index.ts +15 -0
- package/Correlation/CorrelationId.ts +33 -0
- package/Correlation/CorrelationIdManager.ts +30 -0
- package/Correlation/ICorrelationIdAccessor.ts +15 -0
- package/Correlation/ICorrelationIdSetter.ts +21 -0
- package/Correlation/index.ts +15 -0
- package/EventSequences/EventSequence.ts +48 -50
- package/Identity/IIdentityProvider.ts +26 -0
- package/Identity/Identity.ts +61 -0
- package/Identity/IdentityProvider.ts +28 -0
- package/Identity/index.ts +14 -0
- package/Projections/Projections.ts +75 -20
- package/Projections/declarative/ProjectionBuilderFor.ts +19 -2
- package/Projections/declarative/projection.ts +6 -2
- package/Projections/modelBound/index.ts +0 -2
- package/Projections/modelBound/setFromContext.ts +20 -2
- package/README.md +1 -1
- package/Reactors/Reactors.ts +1 -0
- package/Reducers/Reducers.ts +66 -2
- package/Schemas/JsonSchemaGenerator.ts +20 -3
- package/artifacts/DefaultClientArtifactsProvider.ts +0 -5
- package/artifacts/IClientArtifactsProvider.ts +0 -3
- package/connection/Guid.ts +29 -1
- package/dist/Auditing/Causation.d.ts +22 -0
- package/dist/Auditing/Causation.d.ts.map +1 -0
- package/dist/Auditing/Causation.js +30 -0
- package/dist/Auditing/Causation.js.map +1 -0
- package/dist/Auditing/CausationManager.d.ts +23 -0
- package/dist/Auditing/CausationManager.d.ts.map +1 -0
- package/dist/Auditing/CausationManager.js +45 -0
- package/dist/Auditing/CausationManager.js.map +1 -0
- package/dist/Auditing/CausationType.d.ts +30 -0
- package/dist/Auditing/CausationType.d.ts.map +1 -0
- package/dist/Auditing/CausationType.js +36 -0
- package/dist/Auditing/CausationType.js.map +1 -0
- package/dist/Auditing/ICausationManager.d.ts +24 -0
- package/dist/Auditing/ICausationManager.d.ts.map +1 -0
- package/dist/Auditing/ICausationManager.js +4 -0
- package/dist/Auditing/ICausationManager.js.map +1 -0
- package/dist/Auditing/index.d.ts +11 -0
- package/dist/Auditing/index.d.ts.map +1 -0
- package/dist/Auditing/index.js +12 -0
- package/dist/Auditing/index.js.map +1 -0
- package/dist/Correlation/CorrelationId.d.ts +23 -0
- package/dist/Correlation/CorrelationId.d.ts.map +1 -0
- package/dist/Correlation/CorrelationId.js +32 -0
- package/dist/Correlation/CorrelationId.js.map +1 -0
- package/dist/Correlation/CorrelationIdManager.d.ts +17 -0
- package/dist/Correlation/CorrelationIdManager.d.ts.map +1 -0
- package/dist/Correlation/CorrelationIdManager.js +24 -0
- package/dist/Correlation/CorrelationIdManager.js.map +1 -0
- package/dist/Correlation/ICorrelationIdAccessor.d.ts +12 -0
- package/dist/Correlation/ICorrelationIdAccessor.d.ts.map +1 -0
- package/dist/Correlation/ICorrelationIdAccessor.js +4 -0
- package/dist/Correlation/ICorrelationIdAccessor.js.map +1 -0
- package/dist/Correlation/ICorrelationIdSetter.d.ts +17 -0
- package/dist/Correlation/ICorrelationIdSetter.d.ts.map +1 -0
- package/dist/Correlation/ICorrelationIdSetter.js +4 -0
- package/dist/Correlation/ICorrelationIdSetter.js.map +1 -0
- package/dist/Correlation/index.d.ts +11 -0
- package/dist/Correlation/index.d.ts.map +1 -0
- package/dist/Correlation/index.js +11 -0
- package/dist/Correlation/index.js.map +1 -0
- package/dist/EventSequences/EventSequence.d.ts.map +1 -1
- package/dist/EventSequences/EventSequence.js +45 -46
- package/dist/EventSequences/EventSequence.js.map +1 -1
- package/dist/Identity/IIdentityProvider.d.ts +21 -0
- package/dist/Identity/IIdentityProvider.d.ts.map +1 -0
- package/dist/Identity/IIdentityProvider.js +4 -0
- package/dist/Identity/IIdentityProvider.js.map +1 -0
- package/dist/Identity/Identity.d.ts +37 -0
- package/dist/Identity/Identity.d.ts.map +1 -0
- package/dist/Identity/Identity.js +60 -0
- package/dist/Identity/Identity.js.map +1 -0
- package/dist/Identity/IdentityProvider.d.ts +15 -0
- package/dist/Identity/IdentityProvider.d.ts.map +1 -0
- package/dist/Identity/IdentityProvider.js +23 -0
- package/dist/Identity/IdentityProvider.js.map +1 -0
- package/dist/Identity/index.d.ts +10 -0
- package/dist/Identity/index.d.ts.map +1 -0
- package/dist/Identity/index.js +11 -0
- package/dist/Identity/index.js.map +1 -0
- package/dist/Projections/Projections.d.ts +9 -1
- package/dist/Projections/Projections.d.ts.map +1 -1
- package/dist/Projections/Projections.js +70 -19
- package/dist/Projections/Projections.js.map +1 -1
- package/dist/Projections/declarative/ProjectionBuilderFor.d.ts +6 -0
- package/dist/Projections/declarative/ProjectionBuilderFor.d.ts.map +1 -1
- package/dist/Projections/declarative/ProjectionBuilderFor.js +18 -2
- package/dist/Projections/declarative/ProjectionBuilderFor.js.map +1 -1
- package/dist/Projections/declarative/projection.d.ts +5 -1
- package/dist/Projections/declarative/projection.d.ts.map +1 -1
- package/dist/Projections/declarative/projection.js +3 -2
- package/dist/Projections/declarative/projection.js.map +1 -1
- package/dist/Projections/modelBound/index.d.ts +0 -2
- package/dist/Projections/modelBound/index.d.ts.map +1 -1
- package/dist/Projections/modelBound/index.js +0 -1
- package/dist/Projections/modelBound/index.js.map +1 -1
- package/dist/Projections/modelBound/setFromContext.d.ts +4 -1
- package/dist/Projections/modelBound/setFromContext.d.ts.map +1 -1
- package/dist/Projections/modelBound/setFromContext.js +12 -7
- package/dist/Projections/modelBound/setFromContext.js.map +1 -1
- package/dist/Reactors/Reactors.d.ts.map +1 -1
- package/dist/Reactors/Reactors.js +1 -0
- package/dist/Reactors/Reactors.js.map +1 -1
- package/dist/Reducers/Reducers.d.ts +2 -0
- package/dist/Reducers/Reducers.d.ts.map +1 -1
- package/dist/Reducers/Reducers.js +60 -2
- package/dist/Reducers/Reducers.js.map +1 -1
- package/dist/Schemas/JsonSchemaGenerator.d.ts.map +1 -1
- package/dist/Schemas/JsonSchemaGenerator.js +17 -3
- package/dist/Schemas/JsonSchemaGenerator.js.map +1 -1
- package/dist/artifacts/DefaultClientArtifactsProvider.d.ts +0 -2
- package/dist/artifacts/DefaultClientArtifactsProvider.d.ts.map +1 -1
- package/dist/artifacts/DefaultClientArtifactsProvider.js +0 -4
- package/dist/artifacts/DefaultClientArtifactsProvider.js.map +1 -1
- package/dist/artifacts/IClientArtifactsProvider.d.ts +0 -2
- package/dist/artifacts/IClientArtifactsProvider.d.ts.map +1 -1
- package/dist/connection/Guid.d.ts +8 -1
- package/dist/connection/Guid.d.ts.map +1 -1
- package/dist/connection/Guid.js +24 -1
- package/dist/connection/Guid.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/sinks/WellKnownSinks.d.ts +15 -0
- package/dist/sinks/WellKnownSinks.d.ts.map +1 -0
- package/dist/sinks/WellKnownSinks.js +17 -0
- package/dist/sinks/WellKnownSinks.js.map +1 -0
- package/dist/sinks/index.d.ts +2 -0
- package/dist/sinks/index.d.ts.map +1 -0
- package/dist/sinks/index.js +4 -0
- package/dist/sinks/index.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/DecoratorType.d.ts +1 -3
- package/dist/types/DecoratorType.d.ts.map +1 -1
- package/dist/types/DecoratorType.js +0 -2
- package/dist/types/DecoratorType.js.map +1 -1
- package/index.ts +4 -0
- package/package.json +2 -2
- package/sinks/WellKnownSinks.ts +21 -0
- package/sinks/index.ts +4 -0
- package/types/DecoratorType.ts +1 -4
- package/Projections/modelBound/modelBound.ts +0 -59
- package/dist/Grpc.d.ts +0 -19
- package/dist/Grpc.d.ts.map +0 -1
- package/dist/Grpc.js +0 -33
- package/dist/Grpc.js.map +0 -1
- package/dist/Projections/modelBound/modelBound.d.ts +0 -31
- package/dist/Projections/modelBound/modelBound.d.ts.map +0 -1
- package/dist/Projections/modelBound/modelBound.js +0 -39
- package/dist/Projections/modelBound/modelBound.js.map +0 -1
|
@@ -1,6 +1,7 @@
|
|
|
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 { diag } from '@opentelemetry/api';
|
|
4
5
|
import {
|
|
5
6
|
AutoMap,
|
|
6
7
|
ProjectionOwner
|
|
@@ -8,9 +9,11 @@ import {
|
|
|
8
9
|
import { Constructor } from '@cratis/fundamentals';
|
|
9
10
|
import { IClientArtifactsProvider } from '../artifacts';
|
|
10
11
|
import { ChronicleConnection } from '../connection';
|
|
12
|
+
import { toContractsGuid } from '../connection/Guid';
|
|
11
13
|
import { EventSequenceId } from '../EventSequences/EventSequenceId';
|
|
12
14
|
import { getEventTypeFor } from '../Events/eventTypeDecorator';
|
|
13
15
|
import { getReadModelMetadata } from '../ReadModels';
|
|
16
|
+
import { WellKnownSinks } from '../sinks';
|
|
14
17
|
import { TypeIntrospector } from '../types';
|
|
15
18
|
import { IProjections } from './IProjections';
|
|
16
19
|
import { getProjectionMetadata } from './declarative/projection';
|
|
@@ -51,6 +54,8 @@ export class Projections implements IProjections {
|
|
|
51
54
|
private readonly _declarative = new Map<string, Constructor>();
|
|
52
55
|
private readonly _modelBound = new Map<string, Constructor>();
|
|
53
56
|
|
|
57
|
+
private readonly _logger = diag.createComponentLogger({ namespace: '@cratis/chronicle/Projections' });
|
|
58
|
+
|
|
54
59
|
/**
|
|
55
60
|
* Creates a new {@link Projections} instance.
|
|
56
61
|
* @param _clientArtifacts - Provider for discovered client artifact types.
|
|
@@ -66,27 +71,36 @@ export class Projections implements IProjections {
|
|
|
66
71
|
this._declarative.clear();
|
|
67
72
|
this._modelBound.clear();
|
|
68
73
|
|
|
69
|
-
|
|
74
|
+
const declarativeTypes = this._clientArtifacts.projections;
|
|
75
|
+
const readModelTypes = this._clientArtifacts.readModels;
|
|
76
|
+
this._logger.debug('Discovering projections', { declarativeCount: declarativeTypes.length, readModelCount: readModelTypes.length });
|
|
77
|
+
|
|
78
|
+
for (const type of declarativeTypes) {
|
|
70
79
|
const metadata = getProjectionMetadata(type);
|
|
71
80
|
if (metadata) {
|
|
81
|
+
this._logger.debug('Discovered declarative projection', { projectionId: metadata.id.value, type: type.name });
|
|
72
82
|
this._declarative.set(metadata.id.value, type);
|
|
73
83
|
}
|
|
74
84
|
}
|
|
75
85
|
|
|
76
|
-
for (const type of
|
|
86
|
+
for (const type of readModelTypes) {
|
|
77
87
|
if (!hasFromEventMetadata(type)) {
|
|
78
88
|
continue;
|
|
79
89
|
}
|
|
80
90
|
|
|
81
91
|
const metadata = this.resolveModelBoundMetadata(type);
|
|
82
92
|
if (!metadata) {
|
|
93
|
+
this._logger.debug('Read model has @fromEvent but no model-bound metadata resolved', { type: type.name });
|
|
83
94
|
continue;
|
|
84
95
|
}
|
|
85
96
|
|
|
97
|
+
this._logger.debug('Discovered model-bound projection', { projectionId: metadata.id.value, type: type.name });
|
|
86
98
|
if (!this._modelBound.has(metadata.id.value)) {
|
|
87
99
|
this._modelBound.set(metadata.id.value, type);
|
|
88
100
|
}
|
|
89
101
|
}
|
|
102
|
+
|
|
103
|
+
this._logger.debug('Projection discovery complete', { declarativeCount: this._declarative.size, modelBoundCount: this._modelBound.size });
|
|
90
104
|
}
|
|
91
105
|
|
|
92
106
|
/** @inheritdoc */
|
|
@@ -95,12 +109,15 @@ export class Projections implements IProjections {
|
|
|
95
109
|
await this.discover();
|
|
96
110
|
}
|
|
97
111
|
|
|
112
|
+
this._logger.info('Registering projections', { declarativeCount: this._declarative.size, modelBoundCount: this._modelBound.size });
|
|
113
|
+
|
|
98
114
|
const projections = [
|
|
99
115
|
...Array.from(this._declarative.values()).map(type => this.buildDeclarativeDefinition(type)),
|
|
100
116
|
...Array.from(this._modelBound.values()).map(type => this.buildModelBoundDefinition(type))
|
|
101
117
|
];
|
|
102
118
|
|
|
103
119
|
if (projections.length === 0) {
|
|
120
|
+
this._logger.info('No projections to register');
|
|
104
121
|
return;
|
|
105
122
|
}
|
|
106
123
|
|
|
@@ -115,15 +132,37 @@ export class Projections implements IProjections {
|
|
|
115
132
|
}
|
|
116
133
|
|
|
117
134
|
for (const projection of projections) {
|
|
135
|
+
const identifier = String((projection as { Identifier?: unknown }).Identifier ?? '<unknown>');
|
|
136
|
+
await this.registerWithRetry(projection, identifier);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
private async registerWithRetry(projection: unknown, identifier: string, maxAttempts = 5): Promise<void> {
|
|
141
|
+
let delay = 2000;
|
|
142
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
118
143
|
try {
|
|
144
|
+
this._logger.info('Registering projection', { identifier, readModel: (projection as any).ReadModel, attempt });
|
|
119
145
|
await this._connection.projections.register({
|
|
120
146
|
EventStore: this._eventStore,
|
|
121
147
|
Owner: ProjectionOwner.PROJECTION_OWNER_Client,
|
|
122
|
-
Projections: [projection]
|
|
148
|
+
Projections: [projection as any]
|
|
123
149
|
});
|
|
150
|
+
this._logger.info('Projection registered successfully', { identifier });
|
|
151
|
+
return;
|
|
124
152
|
} catch (error) {
|
|
125
|
-
const
|
|
126
|
-
|
|
153
|
+
const msg = String(error);
|
|
154
|
+
const isTransient = msg.includes('UNKNOWN') || msg.includes('UNAVAILABLE') || msg.includes('INTERNAL');
|
|
155
|
+
if (!isTransient || attempt === maxAttempts) {
|
|
156
|
+
throw new Error(`Failed to register projection '${identifier}' after ${attempt} attempt(s): ${msg}`);
|
|
157
|
+
}
|
|
158
|
+
this._logger.warn('Projection registration failed with transient error, retrying', {
|
|
159
|
+
identifier,
|
|
160
|
+
attempt,
|
|
161
|
+
nextAttemptInMs: delay,
|
|
162
|
+
error: msg
|
|
163
|
+
});
|
|
164
|
+
await new Promise(resolve => setTimeout(resolve, delay));
|
|
165
|
+
delay = Math.min(delay * 2, 15000);
|
|
127
166
|
}
|
|
128
167
|
}
|
|
129
168
|
}
|
|
@@ -145,8 +184,8 @@ export class Projections implements IProjections {
|
|
|
145
184
|
ContainerName: readModelIdentifier,
|
|
146
185
|
DisplayName: readModelIdentifier,
|
|
147
186
|
Sink: {
|
|
148
|
-
ConfigurationId:
|
|
149
|
-
TypeId:
|
|
187
|
+
ConfigurationId: toContractsGuid(WellKnownSinks.Null),
|
|
188
|
+
TypeId: toContractsGuid(WellKnownSinks.MongoDB)
|
|
150
189
|
},
|
|
151
190
|
Schema: this.getReadModelSchema(readModelIdentifier),
|
|
152
191
|
Indexes: [],
|
|
@@ -188,12 +227,19 @@ export class Projections implements IProjections {
|
|
|
188
227
|
|
|
189
228
|
const explicitReadModelIdentifier = definition.ReadModel as string;
|
|
190
229
|
if (explicitReadModelIdentifier === type.name) {
|
|
191
|
-
|
|
192
|
-
if (
|
|
193
|
-
|
|
230
|
+
// Use explicit readModelType from decorator if provided
|
|
231
|
+
if (metadata.readModelType) {
|
|
232
|
+
const rm = getReadModelMetadata(metadata.readModelType);
|
|
233
|
+
definition.ReadModel = rm?.id.value ?? (metadata.readModelType as Function).name;
|
|
234
|
+
} else {
|
|
235
|
+
const inferredReadModelIdentifier = this.inferReadModelIdentifier(builder.getMappedReadModelProperties());
|
|
236
|
+
if (inferredReadModelIdentifier) {
|
|
237
|
+
definition.ReadModel = inferredReadModelIdentifier;
|
|
238
|
+
}
|
|
194
239
|
}
|
|
195
240
|
}
|
|
196
241
|
|
|
242
|
+
definition.LastUpdated = { Value: this.computeStableLastUpdated(definition) };
|
|
197
243
|
return definition;
|
|
198
244
|
}
|
|
199
245
|
|
|
@@ -324,7 +370,7 @@ export class Projections implements IProjections {
|
|
|
324
370
|
}
|
|
325
371
|
}
|
|
326
372
|
|
|
327
|
-
|
|
373
|
+
const definition: Record<string, unknown> = {
|
|
328
374
|
EventSequenceId: metadata.eventSequenceId ?? EventSequenceId.eventLog.value,
|
|
329
375
|
Identifier: metadata.id.value,
|
|
330
376
|
ReadModel: metadata.readModelIdentifier,
|
|
@@ -340,14 +386,15 @@ export class Projections implements IProjections {
|
|
|
340
386
|
IncludeChildren: false,
|
|
341
387
|
AutoMap: AutoMap.Inherit
|
|
342
388
|
},
|
|
343
|
-
FromEventProperty: undefined,
|
|
344
389
|
RemovedWith: Array.from(removedWithByEventType.values()),
|
|
345
390
|
RemovedWithJoin: Array.from(removedWithJoinByEventType.values()),
|
|
346
|
-
LastUpdated: { Value:
|
|
391
|
+
LastUpdated: { Value: '' },
|
|
347
392
|
Tags: [],
|
|
348
|
-
AutoMap: AutoMap.
|
|
393
|
+
AutoMap: AutoMap.Enabled,
|
|
349
394
|
Nested: {}
|
|
350
395
|
};
|
|
396
|
+
definition.LastUpdated = { Value: this.computeStableLastUpdated(definition) };
|
|
397
|
+
return definition;
|
|
351
398
|
}
|
|
352
399
|
|
|
353
400
|
private resolveModelBoundMetadata(type: Constructor): ResolvedModelBoundMetadata | undefined {
|
|
@@ -453,11 +500,19 @@ export class Projections implements IProjections {
|
|
|
453
500
|
return `${eventType.Id}:${eventType.Generation}:${eventType.Tombstone ? '1' : '0'}`;
|
|
454
501
|
}
|
|
455
502
|
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
503
|
+
/**
|
|
504
|
+
* Computes a stable, deterministic ISO timestamp from the projection definition content,
|
|
505
|
+
* excluding the LastUpdated field itself. This ensures the server does not interpret
|
|
506
|
+
* a repeated registration of an unchanged definition as a definition change, which
|
|
507
|
+
* would otherwise trigger an unnecessary auto-replay.
|
|
508
|
+
*/
|
|
509
|
+
private computeStableLastUpdated(definition: Record<string, unknown>): string {
|
|
510
|
+
const { LastUpdated: _omit, ...rest } = definition;
|
|
511
|
+
const content = JSON.stringify(rest, Object.keys(rest).sort());
|
|
512
|
+
let hash = 5381;
|
|
513
|
+
for (let i = 0; i < content.length; i++) {
|
|
514
|
+
hash = ((hash << 5) + hash + content.charCodeAt(i)) >>> 0;
|
|
515
|
+
}
|
|
516
|
+
return new Date(hash * 1000).toISOString();
|
|
462
517
|
}
|
|
463
518
|
}
|
|
@@ -215,7 +215,7 @@ export class ProjectionBuilderFor<TReadModel> implements IProjectionBuilderFor<T
|
|
|
215
215
|
* @returns The projection definition object ready to send to the kernel.
|
|
216
216
|
*/
|
|
217
217
|
build(identifier: string, readModelName: string): Record<string, unknown> {
|
|
218
|
-
|
|
218
|
+
const definition: Record<string, unknown> = {
|
|
219
219
|
EventSequenceId: this._eventSequenceId,
|
|
220
220
|
Identifier: identifier,
|
|
221
221
|
ReadModel: this._containerName ?? readModelName,
|
|
@@ -230,11 +230,13 @@ export class ProjectionBuilderFor<TReadModel> implements IProjectionBuilderFor<T
|
|
|
230
230
|
FromEventProperty: undefined,
|
|
231
231
|
RemovedWith: this._removedWith,
|
|
232
232
|
RemovedWithJoin: this._removedWithJoin,
|
|
233
|
-
LastUpdated: { Value:
|
|
233
|
+
LastUpdated: { Value: '' },
|
|
234
234
|
Tags: [],
|
|
235
235
|
AutoMap: this._autoMap,
|
|
236
236
|
Nested: {}
|
|
237
237
|
};
|
|
238
|
+
definition.LastUpdated = { Value: this.computeStableLastUpdated(definition) };
|
|
239
|
+
return definition;
|
|
238
240
|
}
|
|
239
241
|
|
|
240
242
|
/**
|
|
@@ -274,4 +276,19 @@ export class ProjectionBuilderFor<TReadModel> implements IProjectionBuilderFor<T
|
|
|
274
276
|
Tombstone: false
|
|
275
277
|
};
|
|
276
278
|
}
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Computes a stable, deterministic ISO timestamp from the projection definition content,
|
|
282
|
+
* excluding the LastUpdated field itself. This ensures the server does not interpret
|
|
283
|
+
* a repeated registration of an unchanged definition as a definition change.
|
|
284
|
+
*/
|
|
285
|
+
private computeStableLastUpdated(definition: Record<string, unknown>): string {
|
|
286
|
+
const { LastUpdated: _omit, ...rest } = definition;
|
|
287
|
+
const content = JSON.stringify(rest, Object.keys(rest).sort());
|
|
288
|
+
let hash = 5381;
|
|
289
|
+
for (let i = 0; i < content.length; i++) {
|
|
290
|
+
hash = ((hash << 5) + hash + content.charCodeAt(i)) >>> 0;
|
|
291
|
+
}
|
|
292
|
+
return new Date(hash * 1000).toISOString();
|
|
293
|
+
}
|
|
277
294
|
}
|
|
@@ -18,19 +18,23 @@ export interface ProjectionMetadata {
|
|
|
18
18
|
|
|
19
19
|
/** The optional explicit event sequence identifier. */
|
|
20
20
|
readonly eventSequenceId: string | undefined;
|
|
21
|
+
|
|
22
|
+
/** The optional explicit read model constructor. */
|
|
23
|
+
readonly readModelType: Constructor | undefined;
|
|
21
24
|
}
|
|
22
25
|
|
|
23
26
|
/**
|
|
24
27
|
* TypeScript decorator that marks a class as a declarative projection.
|
|
25
28
|
* @param id - The unique identifier for the projection. Defaults to the class name if omitted.
|
|
29
|
+
* @param readModelType - Optional explicit read model constructor (needed when TypeScript generic inference is insufficient).
|
|
26
30
|
* @param eventSequenceId - Optional explicit event sequence identifier.
|
|
27
31
|
* @returns A class decorator.
|
|
28
32
|
*/
|
|
29
|
-
export function projection(id: string = '', eventSequenceId?: string): ClassDecorator {
|
|
33
|
+
export function projection(id: string = '', readModelType?: Constructor, eventSequenceId?: string): ClassDecorator {
|
|
30
34
|
return (target: object) => {
|
|
31
35
|
const constructor = target as Function;
|
|
32
36
|
const projectionId = new ProjectionId(id || constructor.name);
|
|
33
|
-
const metadata: ProjectionMetadata = { id: projectionId, eventSequenceId };
|
|
37
|
+
const metadata: ProjectionMetadata = { id: projectionId, eventSequenceId, readModelType };
|
|
34
38
|
Reflect.defineMetadata(PROJECTION_METADATA_KEY, metadata, target);
|
|
35
39
|
TypeDiscoverer.default.register(
|
|
36
40
|
DecoratorType.Projection,
|
|
@@ -1,8 +1,6 @@
|
|
|
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
|
-
export { modelBound, getModelBoundMetadata, isModelBound } from './modelBound';
|
|
5
|
-
export type { ModelBoundMetadata } from './modelBound';
|
|
6
4
|
export { fromEvent, getFromEventMetadata, hasFromEventMetadata } from './fromEvent';
|
|
7
5
|
export type { FromEventOptions } from './FromEventOptions';
|
|
8
6
|
export type { FromEventMetadata } from './FromEventMetadata';
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
3
3
|
|
|
4
4
|
import 'reflect-metadata';
|
|
5
|
+
import { PropertyAccessor, PropertyPathResolverProxyHandler } from '@cratis/fundamentals';
|
|
6
|
+
import type { EventContext } from '../../Events';
|
|
5
7
|
import { TypeIntrospector } from '../../types';
|
|
6
8
|
|
|
7
9
|
/** Metadata stored by the setFromContext property decorator. */
|
|
@@ -17,14 +19,30 @@ const METADATA_KEY = 'chronicle:projection:setFromContext';
|
|
|
17
19
|
/**
|
|
18
20
|
* Property decorator that maps a value from an event context property onto the decorated read model property.
|
|
19
21
|
* @param eventType - The event constructor.
|
|
20
|
-
* @param
|
|
22
|
+
* @param contextPropertyOrAccessor - Optional event context property name or property accessor. Defaults to the property name.
|
|
21
23
|
* @returns A property decorator.
|
|
22
24
|
*/
|
|
23
|
-
export function setFromContext(eventType: Function, contextPropertyName?: string): PropertyDecorator
|
|
25
|
+
export function setFromContext(eventType: Function, contextPropertyName?: string): PropertyDecorator;
|
|
26
|
+
export function setFromContext(eventType: Function, contextPropertyAccessor?: PropertyAccessor<EventContext>): PropertyDecorator;
|
|
27
|
+
export function setFromContext(
|
|
28
|
+
eventType: Function,
|
|
29
|
+
contextPropertyOrAccessor?: string | PropertyAccessor<EventContext>
|
|
30
|
+
): PropertyDecorator {
|
|
24
31
|
return (target: object, propertyKey: string | symbol) => {
|
|
25
32
|
const key = propertyKey.toString();
|
|
26
33
|
TypeIntrospector.trackProperty((target as { constructor: Function }).constructor, key);
|
|
27
34
|
const existing: SetFromContextMetadata[] = Reflect.getMetadata(METADATA_KEY, target, key) ?? [];
|
|
35
|
+
|
|
36
|
+
let contextPropertyName: string | undefined;
|
|
37
|
+
if (typeof contextPropertyOrAccessor === 'string') {
|
|
38
|
+
contextPropertyName = contextPropertyOrAccessor;
|
|
39
|
+
} else if (typeof contextPropertyOrAccessor === 'function') {
|
|
40
|
+
const handler = new PropertyPathResolverProxyHandler();
|
|
41
|
+
const proxy = new Proxy({}, handler);
|
|
42
|
+
contextPropertyOrAccessor(proxy as EventContext);
|
|
43
|
+
contextPropertyName = handler.property;
|
|
44
|
+
}
|
|
45
|
+
|
|
28
46
|
const metadata: SetFromContextMetadata = { eventType, contextPropertyName };
|
|
29
47
|
Reflect.defineMetadata(METADATA_KEY, [...existing, metadata], target, key);
|
|
30
48
|
};
|
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@ A TypeScript-idiomatic client for [Cratis Chronicle](https://github.com/Cratis/C
|
|
|
6
6
|
|
|
7
7
|
`@cratis/chronicle` provides a clean, type-safe TypeScript API for interacting with the Chronicle Kernel. It builds on top of [`@cratis/chronicle.contracts`](https://www.npmjs.com/package/@cratis/chronicle.contracts) (the gRPC contracts package) and exposes idiomatic TypeScript constructs including:
|
|
8
8
|
|
|
9
|
-
- **Decorators** — `@eventType`, `@readModel`, `@reactor`, `@reducer`, `@constraint`, `@projection`, `@
|
|
9
|
+
- **Decorators** — `@eventType`, `@readModel`, `@reactor`, `@reducer`, `@constraint`, `@projection`, and model-bound decorators such as `@fromEvent`
|
|
10
10
|
- **Value objects** — `EventSequenceNumber`, `EventTypeId`, `EventStoreName`, etc.
|
|
11
11
|
- **Fluent client** — `ChronicleClient` → `EventStore` → `EventLog` → `append()`
|
|
12
12
|
|
package/Reactors/Reactors.ts
CHANGED
|
@@ -233,6 +233,7 @@ export class Reactors implements IReactors {
|
|
|
233
233
|
}
|
|
234
234
|
|
|
235
235
|
const content = JSON.parse(event.Content) as Record<string, unknown>;
|
|
236
|
+
this._logger.debug('Event content', { reactorId: id, eventTypeId, contentKeys: Object.keys(content), rawContent: event.Content.substring(0, 200) });
|
|
236
237
|
const context: EventContext = {
|
|
237
238
|
sequenceNumber: event.Context!.SequenceNumber,
|
|
238
239
|
eventSourceId: event.Context!.EventSourceId,
|
package/Reducers/Reducers.ts
CHANGED
|
@@ -4,14 +4,18 @@
|
|
|
4
4
|
import 'reflect-metadata';
|
|
5
5
|
import { diag } from '@opentelemetry/api';
|
|
6
6
|
import { Constructor } from '@cratis/fundamentals';
|
|
7
|
-
import { ObservationState, ReducerMessage } from '@cratis/chronicle.contracts';
|
|
7
|
+
import { ObservationState, ReadModelObserverType, ReducerMessage } from '@cratis/chronicle.contracts';
|
|
8
8
|
import { IClientArtifactsProvider } from '../artifacts';
|
|
9
9
|
import { ChronicleConnection } from '../connection';
|
|
10
|
+
import { toContractsGuid } from '../connection/Guid';
|
|
10
11
|
import { ConnectionLifecycle } from '../connection/ConnectionLifecycle';
|
|
11
12
|
import { getEventTypeMetadata } from '../Events/eventTypeDecorator';
|
|
12
13
|
import { EventSequenceId } from '../EventSequences/EventSequenceId';
|
|
14
|
+
import { WellKnownSinks } from '../sinks';
|
|
13
15
|
import { IReducers } from './IReducers';
|
|
14
16
|
import { getReducerMetadata } from './reducer';
|
|
17
|
+
import { getReadModelMetadata } from '../ReadModels';
|
|
18
|
+
import { JsonSchemaGenerator } from '../Schemas';
|
|
15
19
|
|
|
16
20
|
/** Expression used to partition reducer observations by event source ID. */
|
|
17
21
|
const EVENT_SOURCE_ID_KEY = '$eventSourceId';
|
|
@@ -139,6 +143,8 @@ export class Reducers implements IReducers {
|
|
|
139
143
|
await this.discover();
|
|
140
144
|
}
|
|
141
145
|
|
|
146
|
+
await this.registerReadModels();
|
|
147
|
+
|
|
142
148
|
this._logger.info('Registering reducers', { count: this._reducers.size });
|
|
143
149
|
for (const [id, reducerType] of this._reducers) {
|
|
144
150
|
this.startObservation(id, reducerType);
|
|
@@ -147,6 +153,61 @@ export class Reducers implements IReducers {
|
|
|
147
153
|
this._registered = true;
|
|
148
154
|
}
|
|
149
155
|
|
|
156
|
+
private async registerReadModels(): Promise<void> {
|
|
157
|
+
if (this._reducers.size === 0) {
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const readModels = Array.from(this._reducers.entries()).map(([id, reducerType]) => {
|
|
162
|
+
const readModelName = (reducerType as Function).name;
|
|
163
|
+
return {
|
|
164
|
+
Type: {
|
|
165
|
+
Identifier: readModelName,
|
|
166
|
+
Generation: 1
|
|
167
|
+
},
|
|
168
|
+
ContainerName: readModelName,
|
|
169
|
+
DisplayName: readModelName,
|
|
170
|
+
Sink: {
|
|
171
|
+
ConfigurationId: toContractsGuid(WellKnownSinks.Null),
|
|
172
|
+
TypeId: toContractsGuid(WellKnownSinks.MongoDB)
|
|
173
|
+
},
|
|
174
|
+
Schema: this.getReducerSchema(reducerType, readModelName),
|
|
175
|
+
Indexes: [],
|
|
176
|
+
ObserverType: ReadModelObserverType.Reducer,
|
|
177
|
+
ObserverIdentifier: id,
|
|
178
|
+
Owner: 1,
|
|
179
|
+
Source: 1
|
|
180
|
+
};
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
this._logger.info('Registering read models for reducers', { count: readModels.length });
|
|
184
|
+
await this._connection.readModels.registerMany({
|
|
185
|
+
EventStore: this._eventStoreName,
|
|
186
|
+
Owner: 1,
|
|
187
|
+
ReadModels: readModels,
|
|
188
|
+
Source: 1
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
private getReducerSchema(reducerType: Constructor, readModelName: string): string {
|
|
193
|
+
const metadata = getReducerMetadata(reducerType);
|
|
194
|
+
if (metadata?.readModel) {
|
|
195
|
+
const readModelMeta = getReadModelMetadata(metadata.readModel);
|
|
196
|
+
if (readModelMeta?.schema) {
|
|
197
|
+
return JSON.stringify(readModelMeta.schema);
|
|
198
|
+
}
|
|
199
|
+
// No @readModel() decorator — generate from instance
|
|
200
|
+
return JSON.stringify(JsonSchemaGenerator.generate(metadata.readModel));
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// No read model type declared — generate from a minimal schema
|
|
204
|
+
const minimalSchema = {
|
|
205
|
+
...JsonSchemaGenerator.createEmptySchema(readModelName),
|
|
206
|
+
additionalProperties: true
|
|
207
|
+
};
|
|
208
|
+
return JSON.stringify(minimalSchema);
|
|
209
|
+
}
|
|
210
|
+
|
|
150
211
|
private startObservation(id: string, reducerType: Constructor): void {
|
|
151
212
|
const metadata = getReducerMetadata(reducerType)!;
|
|
152
213
|
const eventSequenceId = metadata.eventSequenceId ?? EventSequenceId.eventLog.value;
|
|
@@ -191,7 +252,10 @@ export class Reducers implements IReducers {
|
|
|
191
252
|
})),
|
|
192
253
|
ReadModel: readModelName,
|
|
193
254
|
IsActive: true,
|
|
194
|
-
Sink: {
|
|
255
|
+
Sink: {
|
|
256
|
+
TypeId: toContractsGuid(WellKnownSinks.MongoDB),
|
|
257
|
+
ConfigurationId: toContractsGuid(WellKnownSinks.Null)
|
|
258
|
+
},
|
|
195
259
|
Tags: [],
|
|
196
260
|
Filters: {
|
|
197
261
|
FilterTags: [],
|
|
@@ -44,14 +44,27 @@ export class JsonSchemaGenerator {
|
|
|
44
44
|
static generate(target: Function, members?: ReadonlyMap<string, Function | undefined>): JsonSchema {
|
|
45
45
|
const membersToUse = members ?? TypeIntrospector.getMembers(target);
|
|
46
46
|
const schemaProperties: Record<string, JsonSchema> = {};
|
|
47
|
+
|
|
47
48
|
for (const [memberName, memberType] of membersToUse.entries()) {
|
|
48
|
-
|
|
49
|
+
const propertySchema = this.mapRuntimeTypeToSchema(memberType);
|
|
50
|
+
// Only include properties whose type was resolved. An empty schema ({}) means
|
|
51
|
+
// the runtime type was unavailable (e.g. esbuild/tsx omits design:paramtypes).
|
|
52
|
+
if (Object.keys(propertySchema).length > 0) {
|
|
53
|
+
schemaProperties[memberName] = propertySchema;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// When no property types could be resolved, return a minimal schema with empty
|
|
58
|
+
// properties so the server uses its fallback path that preserves all event
|
|
59
|
+
// content as-is via ConvertUnknownSchemaTypeToClrType.
|
|
60
|
+
if (Object.keys(schemaProperties).length === 0) {
|
|
61
|
+
return this.createEmptySchema(target.name);
|
|
49
62
|
}
|
|
50
63
|
|
|
51
64
|
return {
|
|
52
65
|
...this.createEmptySchema(target.name),
|
|
53
66
|
properties: schemaProperties,
|
|
54
|
-
required:
|
|
67
|
+
required: Object.keys(schemaProperties),
|
|
55
68
|
};
|
|
56
69
|
}
|
|
57
70
|
|
|
@@ -77,7 +90,11 @@ export class JsonSchemaGenerator {
|
|
|
77
90
|
return { type: 'array', items: { type: 'object' } };
|
|
78
91
|
}
|
|
79
92
|
|
|
80
|
-
if (runtimeType
|
|
93
|
+
if (!runtimeType) {
|
|
94
|
+
return {};
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (runtimeType !== Object) {
|
|
81
98
|
return this.generate(runtimeType);
|
|
82
99
|
}
|
|
83
100
|
|
|
@@ -48,9 +48,4 @@ export class DefaultClientArtifactsProvider implements IClientArtifactsProvider
|
|
|
48
48
|
get projections(): Constructor[] {
|
|
49
49
|
return this.discoverer.getTypesByDecoratorType(DecoratorType.Projection);
|
|
50
50
|
}
|
|
51
|
-
|
|
52
|
-
/** @inheritdoc */
|
|
53
|
-
get modelBoundProjections(): Constructor[] {
|
|
54
|
-
return this.discoverer.getTypesByDecoratorType(DecoratorType.ModelBoundProjection);
|
|
55
|
-
}
|
|
56
51
|
}
|
|
@@ -24,7 +24,4 @@ export interface IClientArtifactsProvider {
|
|
|
24
24
|
|
|
25
25
|
/** Gets discovered declarative projection constructors. */
|
|
26
26
|
readonly projections: Constructor[];
|
|
27
|
-
|
|
28
|
-
/** Gets discovered model-bound projection constructors. */
|
|
29
|
-
readonly modelBoundProjections: Constructor[];
|
|
30
27
|
}
|
package/connection/Guid.ts
CHANGED
|
@@ -1,4 +1,32 @@
|
|
|
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
|
-
|
|
4
|
+
import type { Guid as ContractsGuid } from '@cratis/chronicle.contracts';
|
|
5
|
+
import { Guid as FundamentalGuid } from '@cratis/fundamentals';
|
|
6
|
+
|
|
7
|
+
export { Guid } from '@cratis/fundamentals';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Converts a Chronicle Guid into the protobuf-net bcl.Guid shape used by the
|
|
11
|
+
* contracts package.
|
|
12
|
+
*/
|
|
13
|
+
export function toContractsGuid(guid: FundamentalGuid): ContractsGuid {
|
|
14
|
+
const bytes = guid.bytes ?? FundamentalGuid.empty.bytes ?? [];
|
|
15
|
+
if (bytes.length !== 16) {
|
|
16
|
+
throw new Error(`Invalid Guid '${guid.toString()}'. Expected 16 bytes.`);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
let lo = 0n;
|
|
20
|
+
let hi = 0n;
|
|
21
|
+
for (let index = 0; index < 8; index++) {
|
|
22
|
+
lo |= BigInt(bytes[index]) << BigInt(index * 8);
|
|
23
|
+
hi |= BigInt(bytes[index + 8]) << BigInt(index * 8);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// The runtime accepts strings for fixed64 values, which preserves the exact
|
|
27
|
+
// 64-bit payload instead of truncating through Number.
|
|
28
|
+
return {
|
|
29
|
+
lo: lo.toString() as unknown as number,
|
|
30
|
+
hi: hi.toString() as unknown as number
|
|
31
|
+
};
|
|
32
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { CausationType } from './CausationType';
|
|
2
|
+
/**
|
|
3
|
+
* Represents a causation instance.
|
|
4
|
+
*/
|
|
5
|
+
export declare class Causation {
|
|
6
|
+
readonly occurred: Date;
|
|
7
|
+
readonly type: CausationType;
|
|
8
|
+
readonly properties: Readonly<Record<string, string>>;
|
|
9
|
+
/**
|
|
10
|
+
* Creates an unknown causation instance.
|
|
11
|
+
* @returns A new {@link Causation} with the current time, type set to {@link CausationType.unknown}, and empty properties.
|
|
12
|
+
*/
|
|
13
|
+
static unknown(): Causation;
|
|
14
|
+
/**
|
|
15
|
+
* Initializes a new instance of the {@link Causation} class.
|
|
16
|
+
* @param occurred - When it occurred.
|
|
17
|
+
* @param type - Type of causation.
|
|
18
|
+
* @param properties - Any properties associated with the causation.
|
|
19
|
+
*/
|
|
20
|
+
constructor(occurred: Date, type: CausationType, properties: Readonly<Record<string, string>>);
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=Causation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Causation.d.ts","sourceRoot":"","sources":["../../Auditing/Causation.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD;;GAEG;AACH,qBAAa,SAAS;IAgBd,QAAQ,CAAC,QAAQ,EAAE,IAAI;IACvB,QAAQ,CAAC,IAAI,EAAE,aAAa;IAC5B,QAAQ,CAAC,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAjBzD;;;OAGG;IACH,MAAM,CAAC,OAAO,IAAI,SAAS;IAI3B;;;;;OAKG;gBAEU,QAAQ,EAAE,IAAI,EACd,IAAI,EAAE,aAAa,EACnB,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAE5D"}
|
|
@@ -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
|
+
import { CausationType } from './CausationType';
|
|
4
|
+
/**
|
|
5
|
+
* Represents a causation instance.
|
|
6
|
+
*/
|
|
7
|
+
export class Causation {
|
|
8
|
+
occurred;
|
|
9
|
+
type;
|
|
10
|
+
properties;
|
|
11
|
+
/**
|
|
12
|
+
* Creates an unknown causation instance.
|
|
13
|
+
* @returns A new {@link Causation} with the current time, type set to {@link CausationType.unknown}, and empty properties.
|
|
14
|
+
*/
|
|
15
|
+
static unknown() {
|
|
16
|
+
return new Causation(new Date(), CausationType.unknown, {});
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Initializes a new instance of the {@link Causation} class.
|
|
20
|
+
* @param occurred - When it occurred.
|
|
21
|
+
* @param type - Type of causation.
|
|
22
|
+
* @param properties - Any properties associated with the causation.
|
|
23
|
+
*/
|
|
24
|
+
constructor(occurred, type, properties) {
|
|
25
|
+
this.occurred = occurred;
|
|
26
|
+
this.type = type;
|
|
27
|
+
this.properties = properties;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=Causation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Causation.js","sourceRoot":"","sources":["../../Auditing/Causation.ts"],"names":[],"mappings":"AAAA,6CAA6C;AAC7C,qGAAqG;AAErG,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD;;GAEG;AACH,MAAM,OAAO,SAAS;IAgBL;IACA;IACA;IAjBb;;;OAGG;IACH,MAAM,CAAC,OAAO;QACV,OAAO,IAAI,SAAS,CAAC,IAAI,IAAI,EAAE,EAAE,aAAa,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IAChE,CAAC;IAED;;;;;OAKG;IACH,YACa,QAAc,EACd,IAAmB,EACnB,UAA4C;QAF5C,aAAQ,GAAR,QAAQ,CAAM;QACd,SAAI,GAAJ,IAAI,CAAe;QACnB,eAAU,GAAV,UAAU,CAAkC;IACtD,CAAC;CACP"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Causation } from './Causation';
|
|
2
|
+
import { CausationType } from './CausationType';
|
|
3
|
+
import { ICausationManager } from './ICausationManager';
|
|
4
|
+
/**
|
|
5
|
+
* Implements {@link ICausationManager} using {@link AsyncLocalStorage} to scope the causation chain to the active async call context.
|
|
6
|
+
*/
|
|
7
|
+
export declare class CausationManager implements ICausationManager {
|
|
8
|
+
private readonly _storage;
|
|
9
|
+
private _root;
|
|
10
|
+
/** @inheritdoc */
|
|
11
|
+
get root(): Causation;
|
|
12
|
+
/** @inheritdoc */
|
|
13
|
+
getCurrentChain(): ReadonlyArray<Causation>;
|
|
14
|
+
/** @inheritdoc */
|
|
15
|
+
add(type: CausationType, properties: Record<string, string>): void;
|
|
16
|
+
/**
|
|
17
|
+
* Defines the root causation for the current process.
|
|
18
|
+
* @param properties - Properties associated with the root causation.
|
|
19
|
+
*/
|
|
20
|
+
defineRoot(properties: Record<string, string>): void;
|
|
21
|
+
private _getOrInitChain;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=CausationManager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CausationManager.d.ts","sourceRoot":"","sources":["../../Auditing/CausationManager.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAExD;;GAEG;AACH,qBAAa,gBAAiB,YAAW,iBAAiB;IACtD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAwC;IACjE,OAAO,CAAC,KAAK,CAAgE;IAE7E,kBAAkB;IAClB,IAAI,IAAI,IAAI,SAAS,CAEpB;IAED,kBAAkB;IAClB,eAAe,IAAI,aAAa,CAAC,SAAS,CAAC;IAK3C,kBAAkB;IAClB,GAAG,CAAC,IAAI,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI;IAKlE;;;OAGG;IACH,UAAU,CAAC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI;IAIpD,OAAO,CAAC,eAAe;CAU1B"}
|