@cratis/chronicle 0.2.0 → 0.2.2

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 (161) hide show
  1. package/EventStore.ts +8 -0
  2. package/IEventStore.ts +8 -0
  3. package/compliance/ComplianceContracts.ts +63 -0
  4. package/compliance/ComplianceMetadata.ts +19 -0
  5. package/compliance/ComplianceMetadataResolver.ts +51 -0
  6. package/compliance/ComplianceMetadataType.ts +36 -0
  7. package/compliance/index.ts +7 -0
  8. package/compliance/pii.ts +115 -0
  9. package/connection/ChronicleConnection.ts +19 -1
  10. package/connection/ChronicleServices.ts +6 -0
  11. package/dist/EventStore.d.ts +4 -0
  12. package/dist/EventStore.d.ts.map +1 -1
  13. package/dist/EventStore.js +6 -0
  14. package/dist/EventStore.js.map +1 -1
  15. package/dist/IEventStore.d.ts +6 -0
  16. package/dist/IEventStore.d.ts.map +1 -1
  17. package/dist/compliance/ComplianceContracts.d.ts +56 -0
  18. package/dist/compliance/ComplianceContracts.d.ts.map +1 -0
  19. package/dist/compliance/ComplianceContracts.js +25 -0
  20. package/dist/compliance/ComplianceContracts.js.map +1 -0
  21. package/dist/compliance/ComplianceMetadata.d.ts +15 -0
  22. package/dist/compliance/ComplianceMetadata.d.ts.map +1 -0
  23. package/dist/compliance/ComplianceMetadata.js +4 -0
  24. package/dist/compliance/ComplianceMetadata.js.map +1 -0
  25. package/dist/compliance/ComplianceMetadataResolver.d.ts +27 -0
  26. package/dist/compliance/ComplianceMetadataResolver.d.ts.map +1 -0
  27. package/dist/compliance/ComplianceMetadataResolver.js +45 -0
  28. package/dist/compliance/ComplianceMetadataResolver.js.map +1 -0
  29. package/dist/compliance/ComplianceMetadataType.d.ts +24 -0
  30. package/dist/compliance/ComplianceMetadataType.d.ts.map +1 -0
  31. package/dist/compliance/ComplianceMetadataType.js +32 -0
  32. package/dist/compliance/ComplianceMetadataType.js.map +1 -0
  33. package/dist/compliance/index.d.ts +5 -0
  34. package/dist/compliance/index.d.ts.map +1 -0
  35. package/dist/compliance/index.js +6 -0
  36. package/dist/compliance/index.js.map +1 -0
  37. package/dist/compliance/pii.d.ts +69 -0
  38. package/dist/compliance/pii.d.ts.map +1 -0
  39. package/dist/compliance/pii.js +106 -0
  40. package/dist/compliance/pii.js.map +1 -0
  41. package/dist/connection/ChronicleConnection.d.ts +3 -0
  42. package/dist/connection/ChronicleConnection.d.ts.map +1 -1
  43. package/dist/connection/ChronicleConnection.js +16 -2
  44. package/dist/connection/ChronicleConnection.js.map +1 -1
  45. package/dist/connection/ChronicleServices.d.ts +6 -1
  46. package/dist/connection/ChronicleServices.d.ts.map +1 -1
  47. package/dist/eventSequences/EventSequence.js +3 -3
  48. package/dist/eventSequences/EventSequence.js.map +1 -1
  49. package/dist/eventStoreSubscriptions/EventStoreSubscriptionBuilder.d.ts +20 -0
  50. package/dist/eventStoreSubscriptions/EventStoreSubscriptionBuilder.d.ts.map +1 -0
  51. package/dist/eventStoreSubscriptions/EventStoreSubscriptionBuilder.js +41 -0
  52. package/dist/eventStoreSubscriptions/EventStoreSubscriptionBuilder.js.map +1 -0
  53. package/dist/eventStoreSubscriptions/EventStoreSubscriptionDefinition.d.ts +12 -0
  54. package/dist/eventStoreSubscriptions/EventStoreSubscriptionDefinition.d.ts.map +1 -0
  55. package/dist/eventStoreSubscriptions/EventStoreSubscriptionDefinition.js +16 -0
  56. package/dist/eventStoreSubscriptions/EventStoreSubscriptionDefinition.js.map +1 -0
  57. package/dist/eventStoreSubscriptions/EventStoreSubscriptionId.d.ts +10 -0
  58. package/dist/eventStoreSubscriptions/EventStoreSubscriptionId.d.ts.map +1 -0
  59. package/dist/eventStoreSubscriptions/EventStoreSubscriptionId.js +16 -0
  60. package/dist/eventStoreSubscriptions/EventStoreSubscriptionId.js.map +1 -0
  61. package/dist/eventStoreSubscriptions/EventStoreSubscriptions.d.ts +21 -0
  62. package/dist/eventStoreSubscriptions/EventStoreSubscriptions.d.ts.map +1 -0
  63. package/dist/eventStoreSubscriptions/EventStoreSubscriptions.js +60 -0
  64. package/dist/eventStoreSubscriptions/EventStoreSubscriptions.js.map +1 -0
  65. package/dist/eventStoreSubscriptions/IEventStoreSubscriptionBuilder.d.ts +20 -0
  66. package/dist/eventStoreSubscriptions/IEventStoreSubscriptionBuilder.d.ts.map +1 -0
  67. package/dist/eventStoreSubscriptions/IEventStoreSubscriptionBuilder.js +4 -0
  68. package/dist/eventStoreSubscriptions/IEventStoreSubscriptionBuilder.js.map +1 -0
  69. package/dist/eventStoreSubscriptions/IEventStoreSubscriptions.d.ts +21 -0
  70. package/dist/eventStoreSubscriptions/IEventStoreSubscriptions.d.ts.map +1 -0
  71. package/dist/eventStoreSubscriptions/IEventStoreSubscriptions.js +4 -0
  72. package/dist/eventStoreSubscriptions/IEventStoreSubscriptions.js.map +1 -0
  73. package/dist/eventStoreSubscriptions/contracts.d.ts +71 -0
  74. package/dist/eventStoreSubscriptions/contracts.d.ts.map +1 -0
  75. package/dist/eventStoreSubscriptions/contracts.js +310 -0
  76. package/dist/eventStoreSubscriptions/contracts.js.map +1 -0
  77. package/dist/eventStoreSubscriptions/index.d.ts +7 -0
  78. package/dist/eventStoreSubscriptions/index.d.ts.map +1 -0
  79. package/dist/eventStoreSubscriptions/index.js +7 -0
  80. package/dist/eventStoreSubscriptions/index.js.map +1 -0
  81. package/dist/events/constraints/IUniqueConstraintBuilder.d.ts +3 -2
  82. package/dist/events/constraints/IUniqueConstraintBuilder.d.ts.map +1 -1
  83. package/dist/events/constraints/UniqueConstraintBuilder.d.ts +2 -8
  84. package/dist/events/constraints/UniqueConstraintBuilder.d.ts.map +1 -1
  85. package/dist/events/constraints/UniqueConstraintBuilder.js +4 -15
  86. package/dist/events/constraints/UniqueConstraintBuilder.js.map +1 -1
  87. package/dist/index.d.ts +5 -1
  88. package/dist/index.d.ts.map +1 -1
  89. package/dist/index.js +5 -1
  90. package/dist/index.js.map +1 -1
  91. package/dist/reactors/Reactors.js +1 -1
  92. package/dist/reactors/Reactors.js.map +1 -1
  93. package/dist/readModels/IMaterializedReadModels.d.ts +23 -0
  94. package/dist/readModels/IMaterializedReadModels.d.ts.map +1 -0
  95. package/dist/readModels/IMaterializedReadModels.js +4 -0
  96. package/dist/readModels/IMaterializedReadModels.js.map +1 -0
  97. package/dist/readModels/IReadModels.d.ts +75 -0
  98. package/dist/readModels/IReadModels.d.ts.map +1 -0
  99. package/dist/readModels/IReadModels.js +4 -0
  100. package/dist/readModels/IReadModels.js.map +1 -0
  101. package/dist/readModels/MaterializedReadModels.d.ts +25 -0
  102. package/dist/readModels/MaterializedReadModels.d.ts.map +1 -0
  103. package/dist/readModels/MaterializedReadModels.js +125 -0
  104. package/dist/readModels/MaterializedReadModels.js.map +1 -0
  105. package/dist/readModels/ReadModelChangeset.d.ts +14 -0
  106. package/dist/readModels/ReadModelChangeset.d.ts.map +1 -0
  107. package/dist/readModels/ReadModelChangeset.js +4 -0
  108. package/dist/readModels/ReadModelChangeset.js.map +1 -0
  109. package/dist/readModels/ReadModelSnapshot.d.ts +15 -0
  110. package/dist/readModels/ReadModelSnapshot.d.ts.map +1 -0
  111. package/dist/readModels/ReadModelSnapshot.js +4 -0
  112. package/dist/readModels/ReadModelSnapshot.js.map +1 -0
  113. package/dist/readModels/ReadModels.d.ts +43 -0
  114. package/dist/readModels/ReadModels.d.ts.map +1 -0
  115. package/dist/readModels/ReadModels.js +280 -0
  116. package/dist/readModels/ReadModels.js.map +1 -0
  117. package/dist/readModels/index.d.ts +6 -0
  118. package/dist/readModels/index.d.ts.map +1 -1
  119. package/dist/readModels/index.js +2 -0
  120. package/dist/readModels/index.js.map +1 -1
  121. package/dist/readModels/readModel.d.ts.map +1 -1
  122. package/dist/readModels/readModel.js +0 -20
  123. package/dist/readModels/readModel.js.map +1 -1
  124. package/dist/reducers/Reducers.d.ts +1 -0
  125. package/dist/reducers/Reducers.d.ts.map +1 -1
  126. package/dist/reducers/Reducers.js +10 -3
  127. package/dist/reducers/Reducers.js.map +1 -1
  128. package/dist/schemas/JsonSchemaGenerator.d.ts +9 -0
  129. package/dist/schemas/JsonSchemaGenerator.d.ts.map +1 -1
  130. package/dist/schemas/JsonSchemaGenerator.js +53 -1
  131. package/dist/schemas/JsonSchemaGenerator.js.map +1 -1
  132. package/dist/tsconfig.tsbuildinfo +1 -1
  133. package/dist/types/TypeIntrospector.d.ts +11 -1
  134. package/dist/types/TypeIntrospector.d.ts.map +1 -1
  135. package/dist/types/TypeIntrospector.js +29 -3
  136. package/dist/types/TypeIntrospector.js.map +1 -1
  137. package/eventSequences/EventSequence.ts +3 -3
  138. package/eventStoreSubscriptions/EventStoreSubscriptionBuilder.ts +52 -0
  139. package/eventStoreSubscriptions/EventStoreSubscriptionDefinition.ts +16 -0
  140. package/eventStoreSubscriptions/EventStoreSubscriptionId.ts +14 -0
  141. package/eventStoreSubscriptions/EventStoreSubscriptions.ts +74 -0
  142. package/eventStoreSubscriptions/IEventStoreSubscriptionBuilder.ts +24 -0
  143. package/eventStoreSubscriptions/IEventStoreSubscriptions.ts +29 -0
  144. package/eventStoreSubscriptions/contracts.ts +372 -0
  145. package/eventStoreSubscriptions/index.ts +9 -0
  146. package/events/constraints/IUniqueConstraintBuilder.ts +3 -2
  147. package/events/constraints/UniqueConstraintBuilder.ts +5 -17
  148. package/index.ts +6 -0
  149. package/package.json +17 -7
  150. package/reactors/Reactors.ts +1 -1
  151. package/readModels/IMaterializedReadModels.ts +27 -0
  152. package/readModels/IReadModels.ts +87 -0
  153. package/readModels/MaterializedReadModels.ts +151 -0
  154. package/readModels/ReadModelChangeset.ts +19 -0
  155. package/readModels/ReadModelSnapshot.ts +21 -0
  156. package/readModels/ReadModels.ts +348 -0
  157. package/readModels/index.ts +6 -0
  158. package/readModels/readModel.ts +0 -22
  159. package/reducers/Reducers.ts +12 -3
  160. package/schemas/JsonSchemaGenerator.ts +61 -1
  161. package/types/TypeIntrospector.ts +32 -3
@@ -0,0 +1,75 @@
1
+ import type { Constructor } from '@cratis/fundamentals';
2
+ import type { IMaterializedReadModels } from './IMaterializedReadModels';
3
+ import type { ReadModelChangeset } from './ReadModelChangeset';
4
+ import type { ReadModelSnapshot } from './ReadModelSnapshot';
5
+ /**
6
+ * Defines a system that works with read models in the event store.
7
+ */
8
+ export interface IReadModels {
9
+ /**
10
+ * Gets the {@link IMaterializedReadModels} for working with materialized read model instances from the sink.
11
+ */
12
+ readonly materialized: IMaterializedReadModels;
13
+ /**
14
+ * Registers all discovered read models.
15
+ * @returns A promise that resolves when registration completes.
16
+ */
17
+ register(): Promise<void>;
18
+ /**
19
+ * Registers a specific read model type.
20
+ * @param readModelType - The read model type to register.
21
+ * @returns A promise that resolves when registration completes.
22
+ */
23
+ register<TReadModel>(readModelType: Constructor<TReadModel>): Promise<void>;
24
+ /**
25
+ * Gets a read model instance by key.
26
+ * @param readModelType - The read model type to retrieve.
27
+ * @param key - The read model key.
28
+ * @param sessionId - Optional session identifier.
29
+ * @returns The read model instance.
30
+ */
31
+ getInstanceById<TReadModel>(readModelType: Constructor<TReadModel>, key: string, sessionId?: string): Promise<TReadModel>;
32
+ /**
33
+ * Gets all instances of a read model.
34
+ * @param readModelType - The read model type to retrieve.
35
+ * @param eventCount - Optional maximum number of events to process.
36
+ * @returns The read model instances.
37
+ */
38
+ getInstances<TReadModel>(readModelType: Constructor<TReadModel>, eventCount?: bigint): Promise<TReadModel[]>;
39
+ /**
40
+ * Gets snapshots for a read model instance by key.
41
+ * @param readModelType - The read model type to retrieve snapshots for.
42
+ * @param key - The read model key.
43
+ * @returns The read model snapshots.
44
+ */
45
+ getSnapshotsById<TReadModel>(readModelType: Constructor<TReadModel>, key: string): Promise<ReadModelSnapshot<TReadModel>[]>;
46
+ /**
47
+ * Watches changes for a specific read model type.
48
+ * @param readModelType - The read model type to observe.
49
+ * @returns An async iterable of read model changes.
50
+ */
51
+ watch<TReadModel>(readModelType: Constructor<TReadModel>): AsyncIterable<ReadModelChangeset<TReadModel>>;
52
+ /**
53
+ * Dehydrates a read model session.
54
+ * @param sessionId - The session identifier to dehydrate.
55
+ * @param readModelType - The read model type.
56
+ * @param key - The read model key.
57
+ * @returns A promise that resolves when dehydration completes.
58
+ */
59
+ dehydrateSession<TReadModel>(sessionId: string, readModelType: Constructor<TReadModel>, key: string): Promise<void>;
60
+ /**
61
+ * Releases (decrypts) PII properties in a read model instance.
62
+ * @param readModelType - The read model type.
63
+ * @param instance - The read model instance with encrypted PII.
64
+ * @returns The read model instance with decrypted PII values.
65
+ */
66
+ release<TReadModel>(readModelType: Constructor<TReadModel>, instance: TReadModel): Promise<TReadModel>;
67
+ /**
68
+ * Releases (decrypts) PII properties in multiple read model instances.
69
+ * @param readModelType - The read model type.
70
+ * @param instances - The read model instances with encrypted PII.
71
+ * @returns The read model instances with decrypted PII values.
72
+ */
73
+ releaseMany<TReadModel>(readModelType: Constructor<TReadModel>, instances: TReadModel[]): Promise<TReadModel[]>;
74
+ }
75
+ //# sourceMappingURL=IReadModels.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IReadModels.d.ts","sourceRoot":"","sources":["../../readModels/IReadModels.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AACzE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC/D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAE7D;;GAEG;AACH,MAAM,WAAW,WAAW;IACxB;;OAEG;IACH,QAAQ,CAAC,YAAY,EAAE,uBAAuB,CAAC;IAE/C;;;OAGG;IACH,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAE1B;;;;OAIG;IACH,QAAQ,CAAC,UAAU,EAAE,aAAa,EAAE,WAAW,CAAC,UAAU,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE5E;;;;;;OAMG;IACH,eAAe,CAAC,UAAU,EAAE,aAAa,EAAE,WAAW,CAAC,UAAU,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAE1H;;;;;OAKG;IACH,YAAY,CAAC,UAAU,EAAE,aAAa,EAAE,WAAW,CAAC,UAAU,CAAC,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;IAE7G;;;;;OAKG;IACH,gBAAgB,CAAC,UAAU,EAAE,aAAa,EAAE,WAAW,CAAC,UAAU,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;IAE5H;;;;OAIG;IACH,KAAK,CAAC,UAAU,EAAE,aAAa,EAAE,WAAW,CAAC,UAAU,CAAC,GAAG,aAAa,CAAC,kBAAkB,CAAC,UAAU,CAAC,CAAC,CAAC;IAEzG;;;;;;OAMG;IACH,gBAAgB,CAAC,UAAU,EAAE,SAAS,EAAE,MAAM,EAAE,aAAa,EAAE,WAAW,CAAC,UAAU,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEpH;;;;;OAKG;IACH,OAAO,CAAC,UAAU,EAAE,aAAa,EAAE,WAAW,CAAC,UAAU,CAAC,EAAE,QAAQ,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAEvG;;;;;OAKG;IACH,WAAW,CAAC,UAAU,EAAE,aAAa,EAAE,WAAW,CAAC,UAAU,CAAC,EAAE,SAAS,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;CACnH"}
@@ -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
+ export {};
4
+ //# sourceMappingURL=IReadModels.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IReadModels.js","sourceRoot":"","sources":["../../readModels/IReadModels.ts"],"names":[],"mappings":"AAAA,6CAA6C;AAC7C,qGAAqG"}
@@ -0,0 +1,25 @@
1
+ import type { Constructor } from '@cratis/fundamentals';
2
+ import { ChronicleConnection } from '../connection';
3
+ import type { IMaterializedReadModels } from './IMaterializedReadModels';
4
+ /**
5
+ * Implements {@link IMaterializedReadModels} by working with the Chronicle materialized read model gRPC service.
6
+ */
7
+ export declare class MaterializedReadModels implements IMaterializedReadModels {
8
+ private readonly _eventStore;
9
+ private readonly _namespace;
10
+ private readonly _connection;
11
+ constructor(_eventStore: string, _namespace: string, _connection: ChronicleConnection);
12
+ /** @inheritdoc */
13
+ getInstances<TReadModel>(readModelType: Constructor<TReadModel>, skip?: number, take?: number): Promise<TReadModel[]>;
14
+ /** @inheritdoc */
15
+ observeInstances<TReadModel>(readModelType: Constructor<TReadModel>, skip?: number, take?: number): AsyncIterable<TReadModel[]>;
16
+ private resolveIdentifier;
17
+ private toPageParams;
18
+ private deserialize;
19
+ private releaseInstances;
20
+ private releaseInstance;
21
+ private getSchema;
22
+ private schemaHasComplianceMetadata;
23
+ private extractSubject;
24
+ }
25
+ //# sourceMappingURL=MaterializedReadModels.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MaterializedReadModels.d.ts","sourceRoot":"","sources":["../../readModels/MaterializedReadModels.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAExD,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAGpD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AAIzE;;GAEG;AACH,qBAAa,sBAAuB,YAAW,uBAAuB;IAE9D,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC5B,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,WAAW;gBAFX,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,mBAAmB;IAGrD,kBAAkB;IACZ,YAAY,CAAC,UAAU,EAAE,aAAa,EAAE,WAAW,CAAC,UAAU,CAAC,EAAE,IAAI,GAAE,MAAU,EAAE,IAAI,GAAE,MAAoB,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAqB3I,kBAAkB;IACX,gBAAgB,CAAC,UAAU,EAAE,aAAa,EAAE,WAAW,CAAC,UAAU,CAAC,EAAE,IAAI,GAAE,MAAU,EAAE,IAAI,GAAE,MAAoB,GAAG,aAAa,CAAC,UAAU,EAAE,CAAC;IAqBtJ,OAAO,CAAC,iBAAiB;IAKzB,OAAO,CAAC,YAAY;IAWpB,OAAO,CAAC,WAAW;YAOL,gBAAgB;YAShB,eAAe;IAsB7B,OAAO,CAAC,SAAS;IAQjB,OAAO,CAAC,2BAA2B;IAenC,OAAO,CAAC,cAAc;CAOzB"}
@@ -0,0 +1,125 @@
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 { JsonSerializer } from '@cratis/fundamentals';
4
+ import { JsonSchemaGenerator } from '../schemas';
5
+ import { getReadModelMetadata } from './readModel';
6
+ const defaultTake = 50;
7
+ /**
8
+ * Implements {@link IMaterializedReadModels} by working with the Chronicle materialized read model gRPC service.
9
+ */
10
+ export class MaterializedReadModels {
11
+ _eventStore;
12
+ _namespace;
13
+ _connection;
14
+ constructor(_eventStore, _namespace, _connection) {
15
+ this._eventStore = _eventStore;
16
+ this._namespace = _namespace;
17
+ this._connection = _connection;
18
+ }
19
+ /** @inheritdoc */
20
+ async getInstances(readModelType, skip = 0, take = defaultTake) {
21
+ const readModelIdentifier = this.resolveIdentifier(readModelType);
22
+ const { page, pageSize, skipWithinPage } = this.toPageParams(skip, take);
23
+ const response = await this._connection.materializedReadModels.getInstances({
24
+ EventStore: this._eventStore,
25
+ Namespace: this._namespace,
26
+ ReadModel: readModelIdentifier,
27
+ Page: page,
28
+ PageSize: pageSize
29
+ });
30
+ let instances = response.Instances.map(json => this.deserialize(readModelType, json));
31
+ if (skipWithinPage > 0) {
32
+ instances = instances.slice(skipWithinPage);
33
+ }
34
+ return this.releaseInstances(readModelType, instances);
35
+ }
36
+ /** @inheritdoc */
37
+ async *observeInstances(readModelType, skip = 0, take = defaultTake) {
38
+ const readModelIdentifier = this.resolveIdentifier(readModelType);
39
+ const { page, pageSize, skipWithinPage } = this.toPageParams(skip, take);
40
+ for await (const response of this._connection.materializedReadModels.observeInstances({
41
+ EventStore: this._eventStore,
42
+ Namespace: this._namespace,
43
+ ReadModel: readModelIdentifier,
44
+ Page: page,
45
+ PageSize: pageSize
46
+ })) {
47
+ let instances = response.Instances.map(json => this.deserialize(readModelType, json));
48
+ if (skipWithinPage > 0) {
49
+ instances = instances.slice(skipWithinPage);
50
+ }
51
+ yield await this.releaseInstances(readModelType, instances);
52
+ }
53
+ }
54
+ resolveIdentifier(readModelType) {
55
+ const metadata = getReadModelMetadata(readModelType);
56
+ return metadata?.id.value ?? readModelType.name;
57
+ }
58
+ toPageParams(skip, take) {
59
+ if (take <= 0) {
60
+ return { page: 0, pageSize: Number.MAX_SAFE_INTEGER, skipWithinPage: 0 };
61
+ }
62
+ const page = skip > 0 ? Math.floor(skip / take) : 0;
63
+ const skipWithinPage = skip % take;
64
+ return { page, pageSize: take, skipWithinPage };
65
+ }
66
+ deserialize(readModelType, json) {
67
+ if (!json) {
68
+ return Object.create(readModelType.prototype);
69
+ }
70
+ return JsonSerializer.deserialize(readModelType, json);
71
+ }
72
+ async releaseInstances(readModelType, instances) {
73
+ const schema = this.getSchema(readModelType);
74
+ if (!this.schemaHasComplianceMetadata(schema)) {
75
+ return instances;
76
+ }
77
+ return Promise.all(instances.map(instance => this.releaseInstance(readModelType, instance, schema)));
78
+ }
79
+ async releaseInstance(readModelType, instance, schema) {
80
+ const subject = this.extractSubject(instance);
81
+ if (!subject) {
82
+ return instance;
83
+ }
84
+ const payload = JsonSerializer.serialize(instance);
85
+ const response = await this._connection.compliance.release({
86
+ EventStore: this._eventStore,
87
+ Namespace: this._namespace,
88
+ Subject: subject,
89
+ Schema: schema,
90
+ Payload: payload
91
+ });
92
+ if (response.HasError) {
93
+ return instance;
94
+ }
95
+ return this.deserialize(readModelType, response.Payload);
96
+ }
97
+ getSchema(readModelType) {
98
+ const metadata = getReadModelMetadata(readModelType);
99
+ if (metadata) {
100
+ return JSON.stringify(metadata.schema);
101
+ }
102
+ return JSON.stringify(JsonSchemaGenerator.generate(readModelType) ?? JsonSchemaGenerator.createEmptySchema(readModelType.name));
103
+ }
104
+ schemaHasComplianceMetadata(schema) {
105
+ try {
106
+ const parsed = JSON.parse(schema);
107
+ const properties = parsed.properties;
108
+ if (!properties) {
109
+ return false;
110
+ }
111
+ return Object.values(properties).some(property => Array.isArray(property.compliance) && property.compliance.length > 0);
112
+ }
113
+ catch {
114
+ return false;
115
+ }
116
+ }
117
+ extractSubject(instance) {
118
+ const anyInstance = instance;
119
+ if (anyInstance.id !== undefined && anyInstance.id !== null) {
120
+ return String(anyInstance.id);
121
+ }
122
+ return undefined;
123
+ }
124
+ }
125
+ //# sourceMappingURL=MaterializedReadModels.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MaterializedReadModels.js","sourceRoot":"","sources":["../../readModels/MaterializedReadModels.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Represents a change observed for a read model.
3
+ */
4
+ export interface ReadModelChangeset<TReadModel> {
5
+ /** The namespace the change belongs to. */
6
+ readonly namespace: string;
7
+ /** The read model key. */
8
+ readonly key: string;
9
+ /** The current read model state. */
10
+ readonly readModel: TReadModel;
11
+ /** Whether the read model was removed. */
12
+ readonly removed: boolean;
13
+ }
14
+ //# sourceMappingURL=ReadModelChangeset.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ReadModelChangeset.d.ts","sourceRoot":"","sources":["../../readModels/ReadModelChangeset.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,MAAM,WAAW,kBAAkB,CAAC,UAAU;IAC1C,2CAA2C;IAC3C,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAE3B,0BAA0B;IAC1B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IAErB,oCAAoC;IACpC,QAAQ,CAAC,SAAS,EAAE,UAAU,CAAC;IAE/B,0CAA0C;IAC1C,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;CAC7B"}
@@ -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
+ export {};
4
+ //# sourceMappingURL=ReadModelChangeset.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ReadModelChangeset.js","sourceRoot":"","sources":["../../readModels/ReadModelChangeset.ts"],"names":[],"mappings":"AAAA,6CAA6C;AAC7C,qGAAqG"}
@@ -0,0 +1,15 @@
1
+ import type { AppendedEvent, Guid as ContractsGuid } from '@cratis/chronicle.contracts';
2
+ /**
3
+ * Represents a read model snapshot together with the events that produced it.
4
+ */
5
+ export interface ReadModelSnapshot<TReadModel> {
6
+ /** The read model state at the snapshot. */
7
+ readonly readModel: TReadModel;
8
+ /** The events that were applied to reach the snapshot. */
9
+ readonly events: AppendedEvent[];
10
+ /** When the snapshot occurred. */
11
+ readonly occurred: Date | undefined;
12
+ /** The correlation identifier for the snapshot, when available. */
13
+ readonly correlationId: ContractsGuid | undefined;
14
+ }
15
+ //# sourceMappingURL=ReadModelSnapshot.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ReadModelSnapshot.d.ts","sourceRoot":"","sources":["../../readModels/ReadModelSnapshot.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,IAAI,IAAI,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAExF;;GAEG;AACH,MAAM,WAAW,iBAAiB,CAAC,UAAU;IACzC,4CAA4C;IAC5C,QAAQ,CAAC,SAAS,EAAE,UAAU,CAAC;IAE/B,0DAA0D;IAC1D,QAAQ,CAAC,MAAM,EAAE,aAAa,EAAE,CAAC;IAEjC,kCAAkC;IAClC,QAAQ,CAAC,QAAQ,EAAE,IAAI,GAAG,SAAS,CAAC;IAEpC,mEAAmE;IACnE,QAAQ,CAAC,aAAa,EAAE,aAAa,GAAG,SAAS,CAAC;CACrD"}
@@ -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
+ export {};
4
+ //# sourceMappingURL=ReadModelSnapshot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ReadModelSnapshot.js","sourceRoot":"","sources":["../../readModels/ReadModelSnapshot.ts"],"names":[],"mappings":"AAAA,6CAA6C;AAC7C,qGAAqG"}
@@ -0,0 +1,43 @@
1
+ import type { Constructor } from '@cratis/fundamentals';
2
+ import { IClientArtifactsProvider } from '../artifacts';
3
+ import { ChronicleConnection } from '../connection';
4
+ import type { IMaterializedReadModels } from './IMaterializedReadModels';
5
+ import type { IReadModels } from './IReadModels';
6
+ import type { ReadModelChangeset } from './ReadModelChangeset';
7
+ import type { ReadModelSnapshot } from './ReadModelSnapshot';
8
+ /**
9
+ * Implements {@link IReadModels} by working with the Chronicle read-model gRPC service.
10
+ */
11
+ export declare class ReadModels implements IReadModels {
12
+ private readonly _eventStore;
13
+ private readonly _namespace;
14
+ private readonly _connection;
15
+ private readonly _clientArtifacts;
16
+ readonly materialized: IMaterializedReadModels;
17
+ constructor(_eventStore: string, _namespace: string, _connection: ChronicleConnection, _clientArtifacts: IClientArtifactsProvider);
18
+ /** @inheritdoc */
19
+ register<TReadModel>(readModelType?: Constructor<TReadModel>): Promise<void>;
20
+ /** @inheritdoc */
21
+ getInstanceById<TReadModel>(readModelType: Constructor<TReadModel>, key: string, sessionId?: string): Promise<TReadModel>;
22
+ /** @inheritdoc */
23
+ getInstances<TReadModel>(readModelType: Constructor<TReadModel>, eventCount?: bigint): Promise<TReadModel[]>;
24
+ /** @inheritdoc */
25
+ getSnapshotsById<TReadModel>(readModelType: Constructor<TReadModel>, key: string): Promise<ReadModelSnapshot<TReadModel>[]>;
26
+ /** @inheritdoc */
27
+ watch<TReadModel>(readModelType: Constructor<TReadModel>): AsyncIterable<ReadModelChangeset<TReadModel>>;
28
+ /** @inheritdoc */
29
+ dehydrateSession<TReadModel>(sessionId: string, readModelType: Constructor<TReadModel>, key: string): Promise<void>;
30
+ /** @inheritdoc */
31
+ release<TReadModel>(readModelType: Constructor<TReadModel>, instance: TReadModel): Promise<TReadModel>;
32
+ /** @inheritdoc */
33
+ releaseMany<TReadModel>(readModelType: Constructor<TReadModel>, instances: TReadModel[]): Promise<TReadModel[]>;
34
+ private releaseSnapshotInstances;
35
+ private resolveReadModels;
36
+ private resolveReadModel;
37
+ private toDefinition;
38
+ private getReadModelSchema;
39
+ private deserializeReadModel;
40
+ private schemaHasComplianceMetadata;
41
+ private extractSubject;
42
+ }
43
+ //# sourceMappingURL=ReadModels.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ReadModels.d.ts","sourceRoot":"","sources":["../../readModels/ReadModels.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAExD,OAAO,EAAE,wBAAwB,EAAE,MAAM,cAAc,CAAC;AAExD,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAQpD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AAEzE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC/D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAa7D;;GAEG;AACH,qBAAa,UAAW,YAAW,WAAW;IAItC,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC5B,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC5B,OAAO,CAAC,QAAQ,CAAC,gBAAgB;IANrC,QAAQ,CAAC,YAAY,EAAE,uBAAuB,CAAC;gBAG1B,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,mBAAmB,EAChC,gBAAgB,EAAE,wBAAwB;IAK/D,kBAAkB;IACZ,QAAQ,CAAC,UAAU,EAAE,aAAa,CAAC,EAAE,WAAW,CAAC,UAAU,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAclF,kBAAkB;IACZ,eAAe,CAAC,UAAU,EAAE,aAAa,EAAE,WAAW,CAAC,UAAU,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAoB/H,kBAAkB;IACZ,YAAY,CAAC,UAAU,EAAE,aAAa,EAAE,WAAW,CAAC,UAAU,CAAC,EAAE,UAAU,GAAE,MAA4B,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAmBvI,kBAAkB;IACZ,gBAAgB,CAAC,UAAU,EAAE,aAAa,EAAE,WAAW,CAAC,UAAU,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC,UAAU,CAAC,EAAE,CAAC;IAwBjI,kBAAkB;IACX,KAAK,CAAC,UAAU,EAAE,aAAa,EAAE,WAAW,CAAC,UAAU,CAAC,GAAG,aAAa,CAAC,kBAAkB,CAAC,UAAU,CAAC,CAAC;IAkB/G,kBAAkB;IACZ,gBAAgB,CAAC,UAAU,EAAE,SAAS,EAAE,MAAM,EAAE,aAAa,EAAE,WAAW,CAAC,UAAU,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAYzH,kBAAkB;IACZ,OAAO,CAAC,UAAU,EAAE,aAAa,EAAE,WAAW,CAAC,UAAU,CAAC,EAAE,QAAQ,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;IAqB5G,kBAAkB;IACZ,WAAW,CAAC,UAAU,EAAE,aAAa,EAAE,WAAW,CAAC,UAAU,CAAC,EAAE,SAAS,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;YAKvG,wBAAwB;IAStC,OAAO,CAAC,iBAAiB;IA0EzB,OAAO,CAAC,gBAAgB;IASxB,OAAO,CAAC,YAAY;IAqBpB,OAAO,CAAC,kBAAkB;IAS1B,OAAO,CAAC,oBAAoB;IAO5B,OAAO,CAAC,2BAA2B;IAenC,OAAO,CAAC,cAAc;CAQzB"}
@@ -0,0 +1,280 @@
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 { ReadModelObserverType as ContractReadModelObserverType } from '@cratis/chronicle.contracts';
4
+ import { JsonSerializer } from '@cratis/fundamentals';
5
+ import { toContractsGuid } from '../connection/Guid';
6
+ import { EventSequenceId } from '../eventSequences/EventSequenceId';
7
+ import { getProjectionMetadata } from '../projections/declarative/projection';
8
+ import { hasFromEventMetadata } from '../projections/modelBound/fromEvent';
9
+ import { getReducerMetadata } from '../reducers/reducer';
10
+ import { JsonSchemaGenerator } from '../schemas';
11
+ import { WellKnownSinks } from '../sinks';
12
+ import { getReadModelMetadata } from './readModel';
13
+ import { MaterializedReadModels } from './MaterializedReadModels';
14
+ const unlimitedEventCount = BigInt('18446744073709551615');
15
+ /**
16
+ * Implements {@link IReadModels} by working with the Chronicle read-model gRPC service.
17
+ */
18
+ export class ReadModels {
19
+ _eventStore;
20
+ _namespace;
21
+ _connection;
22
+ _clientArtifacts;
23
+ materialized;
24
+ constructor(_eventStore, _namespace, _connection, _clientArtifacts) {
25
+ this._eventStore = _eventStore;
26
+ this._namespace = _namespace;
27
+ this._connection = _connection;
28
+ this._clientArtifacts = _clientArtifacts;
29
+ this.materialized = new MaterializedReadModels(_eventStore, _namespace, _connection);
30
+ }
31
+ /** @inheritdoc */
32
+ async register(readModelType) {
33
+ const readModels = this.resolveReadModels(readModelType);
34
+ if (readModels.length === 0) {
35
+ return;
36
+ }
37
+ await this._connection.readModels.registerMany({
38
+ EventStore: this._eventStore,
39
+ Owner: 1,
40
+ Source: 1,
41
+ ReadModels: readModels.map(readModel => this.toDefinition(readModel))
42
+ });
43
+ }
44
+ /** @inheritdoc */
45
+ async getInstanceById(readModelType, key, sessionId) {
46
+ const readModel = this.resolveReadModel(readModelType);
47
+ const response = await this._connection.readModels.getInstanceByKey({
48
+ EventStore: this._eventStore,
49
+ Namespace: this._namespace,
50
+ ReadModelIdentifier: readModel.identifier,
51
+ EventSequenceId: readModel.eventSequenceId,
52
+ ReadModelKey: key,
53
+ SessionId: sessionId ?? ''
54
+ });
55
+ const instance = this.deserializeReadModel(readModelType, response.ReadModel);
56
+ if (readModel.observerType === ContractReadModelObserverType.Reducer && this.schemaHasComplianceMetadata(readModel.schema)) {
57
+ return this.release(readModelType, instance);
58
+ }
59
+ return instance;
60
+ }
61
+ /** @inheritdoc */
62
+ async getInstances(readModelType, eventCount = unlimitedEventCount) {
63
+ const readModel = this.resolveReadModel(readModelType);
64
+ const response = await this._connection.readModels.getAllInstances({
65
+ EventStore: this._eventStore,
66
+ Namespace: this._namespace,
67
+ ReadModelIdentifier: readModel.identifier,
68
+ EventSequenceId: readModel.eventSequenceId,
69
+ EventCount: eventCount
70
+ });
71
+ const instances = response.Instances.map(instance => this.deserializeReadModel(readModelType, instance));
72
+ if (readModel.observerType === ContractReadModelObserverType.Reducer && this.schemaHasComplianceMetadata(readModel.schema)) {
73
+ return this.releaseMany(readModelType, instances);
74
+ }
75
+ return instances;
76
+ }
77
+ /** @inheritdoc */
78
+ async getSnapshotsById(readModelType, key) {
79
+ const readModel = this.resolveReadModel(readModelType);
80
+ const response = await this._connection.readModels.getSnapshotsByKey({
81
+ EventStore: this._eventStore,
82
+ Namespace: this._namespace,
83
+ ReadModelIdentifier: readModel.identifier,
84
+ EventSequenceId: readModel.eventSequenceId,
85
+ ReadModelKey: key
86
+ });
87
+ const snapshots = response.Snapshots.map(snapshot => ({
88
+ readModel: this.deserializeReadModel(readModelType, snapshot.ReadModel),
89
+ events: (snapshot.Events ?? []),
90
+ occurred: snapshot.Occurred?.Value ? new Date(snapshot.Occurred.Value) : undefined,
91
+ correlationId: snapshot.CorrelationId
92
+ }));
93
+ if (readModel.observerType === ContractReadModelObserverType.Reducer && this.schemaHasComplianceMetadata(readModel.schema)) {
94
+ return this.releaseSnapshotInstances(readModelType, snapshots);
95
+ }
96
+ return snapshots;
97
+ }
98
+ /** @inheritdoc */
99
+ async *watch(readModelType) {
100
+ const readModel = this.resolveReadModel(readModelType);
101
+ for await (const changeset of this._connection.readModels.watch({
102
+ EventStore: this._eventStore,
103
+ Namespace: this._namespace,
104
+ ReadModelIdentifier: readModel.identifier,
105
+ EventSequenceId: readModel.eventSequenceId
106
+ })) {
107
+ yield {
108
+ namespace: changeset.Namespace,
109
+ key: changeset.ModelKey,
110
+ readModel: this.deserializeReadModel(readModelType, changeset.ReadModel),
111
+ removed: changeset.Removed
112
+ };
113
+ }
114
+ }
115
+ /** @inheritdoc */
116
+ async dehydrateSession(sessionId, readModelType, key) {
117
+ const readModel = this.resolveReadModel(readModelType);
118
+ await this._connection.readModels.dehydrateSession({
119
+ EventStore: this._eventStore,
120
+ Namespace: this._namespace,
121
+ ReadModelIdentifier: readModel.identifier,
122
+ EventSequenceId: readModel.eventSequenceId,
123
+ ReadModelKey: key,
124
+ SessionId: sessionId
125
+ });
126
+ }
127
+ /** @inheritdoc */
128
+ async release(readModelType, instance) {
129
+ const readModel = this.resolveReadModel(readModelType);
130
+ const schema = this.getReadModelSchema(readModelType, readModel.identifier);
131
+ const payload = JsonSerializer.serialize(instance);
132
+ const subject = this.extractSubject(instance);
133
+ const response = await this._connection.compliance.release({
134
+ EventStore: this._eventStore,
135
+ Namespace: this._namespace,
136
+ Subject: subject,
137
+ Schema: schema,
138
+ Payload: payload
139
+ });
140
+ if (response.HasError) {
141
+ throw new Error(`Failed to release PII: ${response.Error}`);
142
+ }
143
+ return this.deserializeReadModel(readModelType, response.Payload);
144
+ }
145
+ /** @inheritdoc */
146
+ async releaseMany(readModelType, instances) {
147
+ const releasePromises = instances.map(instance => this.release(readModelType, instance));
148
+ return Promise.all(releasePromises);
149
+ }
150
+ async releaseSnapshotInstances(readModelType, snapshots) {
151
+ return Promise.all(snapshots.map(async (snapshot) => ({
152
+ ...snapshot,
153
+ readModel: await this.release(readModelType, snapshot.readModel)
154
+ })));
155
+ }
156
+ resolveReadModels(readModelType) {
157
+ const resolved = new Map();
158
+ for (const projectionType of this._clientArtifacts.projections) {
159
+ const metadata = getProjectionMetadata(projectionType);
160
+ if (!metadata?.readModelType) {
161
+ continue;
162
+ }
163
+ if (readModelType && metadata.readModelType !== readModelType) {
164
+ continue;
165
+ }
166
+ const readModelMetadata = getReadModelMetadata(metadata.readModelType);
167
+ const identifier = readModelMetadata?.id.value ?? metadata.readModelType.name;
168
+ resolved.set(identifier, {
169
+ type: metadata.readModelType,
170
+ identifier,
171
+ eventSequenceId: metadata.eventSequenceId ?? EventSequenceId.eventLog.value,
172
+ observerType: ContractReadModelObserverType.Projection,
173
+ observerIdentifier: metadata.id.value,
174
+ schema: this.getReadModelSchema(metadata.readModelType, identifier)
175
+ });
176
+ }
177
+ for (const modelBoundType of this._clientArtifacts.readModels) {
178
+ if (!hasFromEventMetadata(modelBoundType)) {
179
+ continue;
180
+ }
181
+ if (readModelType && modelBoundType !== readModelType) {
182
+ continue;
183
+ }
184
+ const metadata = getReadModelMetadata(modelBoundType);
185
+ if (!metadata) {
186
+ continue;
187
+ }
188
+ resolved.set(metadata.id.value, {
189
+ type: modelBoundType,
190
+ identifier: metadata.id.value,
191
+ eventSequenceId: EventSequenceId.eventLog.value,
192
+ observerType: ContractReadModelObserverType.Projection,
193
+ observerIdentifier: metadata.id.value,
194
+ schema: JSON.stringify(metadata.schema)
195
+ });
196
+ }
197
+ for (const reducerType of this._clientArtifacts.reducers) {
198
+ const metadata = getReducerMetadata(reducerType);
199
+ if (!metadata?.readModel) {
200
+ continue;
201
+ }
202
+ if (readModelType && metadata.readModel !== readModelType) {
203
+ continue;
204
+ }
205
+ const readModelMetadata = getReadModelMetadata(metadata.readModel);
206
+ const identifier = readModelMetadata?.id.value ?? metadata.readModel.name;
207
+ resolved.set(identifier, {
208
+ type: metadata.readModel,
209
+ identifier,
210
+ eventSequenceId: metadata.eventSequenceId ?? EventSequenceId.eventLog.value,
211
+ observerType: ContractReadModelObserverType.Reducer,
212
+ observerIdentifier: metadata.id.value,
213
+ schema: this.getReadModelSchema(metadata.readModel, identifier)
214
+ });
215
+ }
216
+ return Array.from(resolved.values());
217
+ }
218
+ resolveReadModel(readModelType) {
219
+ const [resolved] = this.resolveReadModels(readModelType);
220
+ if (!resolved) {
221
+ throw new Error(`Unknown read model '${readModelType.name}'. Make sure it is decorated and discoverable.`);
222
+ }
223
+ return resolved;
224
+ }
225
+ toDefinition(readModel) {
226
+ return {
227
+ Type: {
228
+ Identifier: readModel.identifier,
229
+ Generation: 1
230
+ },
231
+ ContainerName: readModel.identifier,
232
+ DisplayName: readModel.identifier,
233
+ Sink: {
234
+ ConfigurationId: toContractsGuid(WellKnownSinks.Null),
235
+ TypeId: toContractsGuid(WellKnownSinks.MongoDB)
236
+ },
237
+ Schema: readModel.schema,
238
+ Indexes: [],
239
+ ObserverType: readModel.observerType,
240
+ ObserverIdentifier: readModel.observerIdentifier,
241
+ Owner: 1,
242
+ Source: 1
243
+ };
244
+ }
245
+ getReadModelSchema(readModelType, identifier) {
246
+ const metadata = getReadModelMetadata(readModelType);
247
+ if (metadata) {
248
+ return JSON.stringify(metadata.schema);
249
+ }
250
+ return JSON.stringify(JsonSchemaGenerator.generate(readModelType) ?? JsonSchemaGenerator.createEmptySchema(identifier));
251
+ }
252
+ deserializeReadModel(readModelType, json) {
253
+ if (!json) {
254
+ return Object.create(readModelType.prototype);
255
+ }
256
+ return JsonSerializer.deserialize(readModelType, json);
257
+ }
258
+ schemaHasComplianceMetadata(schema) {
259
+ try {
260
+ const parsed = JSON.parse(schema);
261
+ const properties = parsed.properties;
262
+ if (!properties) {
263
+ return false;
264
+ }
265
+ return Object.values(properties).some(property => Array.isArray(property.compliance) && property.compliance.length > 0);
266
+ }
267
+ catch {
268
+ return false;
269
+ }
270
+ }
271
+ extractSubject(instance) {
272
+ // By convention, use the 'id' property as the subject
273
+ const anyInstance = instance;
274
+ if (anyInstance.id !== undefined && anyInstance.id !== null) {
275
+ return String(anyInstance.id);
276
+ }
277
+ throw new Error('Read model instance must have an "id" property to serve as the subject for PII release');
278
+ }
279
+ }
280
+ //# sourceMappingURL=ReadModels.js.map