@event-driven-io/emmett-mongodb 0.23.0-alpha.9 → 0.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +295 -23
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +52 -21
- package/dist/index.d.ts +52 -21
- package/dist/index.js +281 -9
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.d.ts
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
import { Event,
|
|
1
|
+
import { Event, ProjectionHandler, TypedProjectionDefinition, ReadEvent, CanHandle, ThenThrows, ReadEventMetadataWithoutGlobalPosition, ProjectionRegistration, EventStore, Closeable } from '@event-driven-io/emmett';
|
|
2
2
|
import { UpdateFilter, Collection, Document, MongoClient, MongoClientOptions, Filter } from 'mongodb';
|
|
3
3
|
|
|
4
4
|
declare const MongoDBDefaultInlineProjectionName = "_default";
|
|
5
|
-
type MongoDBProjectionInlineHandlerContext<EventType extends Event = Event, EventMetaDataType extends
|
|
5
|
+
type MongoDBProjectionInlineHandlerContext<EventType extends Event = Event, EventMetaDataType extends MongoDBReadEventMetadata = MongoDBReadEventMetadata> = {
|
|
6
6
|
document: MongoDBReadModel | null;
|
|
7
7
|
streamId: string;
|
|
8
8
|
updates: UpdateFilter<EventStream<EventType, EventMetaDataType>>;
|
|
9
9
|
collection: Collection<EventStream<EventType, EventMetaDataType>>;
|
|
10
10
|
};
|
|
11
|
-
type MongoDBInlineProjectionHandler<EventType extends Event = Event, EventMetaDataType extends
|
|
12
|
-
type MongoDBInlineProjectionDefinition<EventType extends Event = Event, EventMetaDataType extends
|
|
11
|
+
type MongoDBInlineProjectionHandler<EventType extends Event = Event, EventMetaDataType extends MongoDBReadEventMetadata = MongoDBReadEventMetadata> = ProjectionHandler<EventType, EventMetaDataType, MongoDBProjectionInlineHandlerContext>;
|
|
12
|
+
type MongoDBInlineProjectionDefinition<EventType extends Event = Event, EventMetaDataType extends MongoDBReadEventMetadata = MongoDBReadEventMetadata> = TypedProjectionDefinition<EventType, EventMetaDataType, MongoDBProjectionInlineHandlerContext> & {
|
|
13
13
|
name: string;
|
|
14
14
|
};
|
|
15
|
-
type InlineProjectionHandlerOptions<EventType extends Event = Event, EventMetaDataType extends
|
|
15
|
+
type InlineProjectionHandlerOptions<EventType extends Event = Event, EventMetaDataType extends MongoDBReadEventMetadata = MongoDBReadEventMetadata> = {
|
|
16
16
|
readModels: Record<string, MongoDBReadModel>;
|
|
17
17
|
events: Array<ReadEvent<EventType, EventMetaDataType>>;
|
|
18
18
|
projections: MongoDBInlineProjectionDefinition<EventType, EventMetaDataType>[];
|
|
@@ -21,14 +21,10 @@ type InlineProjectionHandlerOptions<EventType extends Event = Event, EventMetaDa
|
|
|
21
21
|
updates: UpdateFilter<EventStream<Event>>;
|
|
22
22
|
client: {};
|
|
23
23
|
};
|
|
24
|
-
declare const handleInlineProjections: <EventType extends Event = Event, EventMetaDataType extends
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
}> & object>(options: InlineProjectionHandlerOptions<EventType, EventMetaDataType>) => Promise<void>;
|
|
29
|
-
type MongoDBWithNotNullDocumentEvolve<Doc extends Document, EventType extends Event, EventMetaDataType extends EventMetaDataOf<EventType> & MongoDBReadEventMetadata = EventMetaDataOf<EventType> & MongoDBReadEventMetadata> = ((document: Doc, event: ReadEvent<EventType, EventMetaDataType>) => Doc | null) | ((document: Doc, event: ReadEvent<EventType>) => Promise<Doc | null>);
|
|
30
|
-
type MongoDBWithNullableDocumentEvolve<Doc extends Document, EventType extends Event, EventMetaDataType extends EventMetaDataOf<EventType> & MongoDBReadEventMetadata = EventMetaDataOf<EventType> & MongoDBReadEventMetadata> = ((document: Doc | null, event: ReadEvent<EventType, EventMetaDataType>) => Doc | null) | ((document: Doc | null, event: ReadEvent<EventType>) => Promise<Doc | null>);
|
|
31
|
-
type MongoDBInlineProjectionOptions<Doc extends Document, EventType extends Event, EventMetaDataType extends EventMetaDataOf<EventType> & MongoDBReadEventMetadata = EventMetaDataOf<EventType> & MongoDBReadEventMetadata> = {
|
|
24
|
+
declare const handleInlineProjections: <EventType extends Event = Event, EventMetaDataType extends MongoDBReadEventMetadata = MongoDBReadEventMetadata>(options: InlineProjectionHandlerOptions<EventType, EventMetaDataType>) => Promise<void>;
|
|
25
|
+
type MongoDBWithNotNullDocumentEvolve<Doc extends Document, EventType extends Event, EventMetaDataType extends MongoDBReadEventMetadata = MongoDBReadEventMetadata> = ((document: Doc, event: ReadEvent<EventType, EventMetaDataType>) => Doc | null) | ((document: Doc, event: ReadEvent<EventType>) => Promise<Doc | null>);
|
|
26
|
+
type MongoDBWithNullableDocumentEvolve<Doc extends Document, EventType extends Event, EventMetaDataType extends MongoDBReadEventMetadata = MongoDBReadEventMetadata> = ((document: Doc | null, event: ReadEvent<EventType, EventMetaDataType>) => Doc | null) | ((document: Doc | null, event: ReadEvent<EventType>) => Promise<Doc | null>);
|
|
27
|
+
type MongoDBInlineProjectionOptions<Doc extends Document, EventType extends Event, EventMetaDataType extends MongoDBReadEventMetadata = MongoDBReadEventMetadata> = {
|
|
32
28
|
name?: string;
|
|
33
29
|
schemaVersion?: number;
|
|
34
30
|
canHandle: CanHandle<EventType>;
|
|
@@ -38,11 +34,45 @@ type MongoDBInlineProjectionOptions<Doc extends Document, EventType extends Even
|
|
|
38
34
|
evolve: MongoDBWithNotNullDocumentEvolve<Doc, EventType, EventMetaDataType>;
|
|
39
35
|
initialState: () => Doc;
|
|
40
36
|
});
|
|
41
|
-
declare const mongoDBInlineProjection: <Doc extends Document, EventType extends Event, EventMetaDataType extends
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
streamName:
|
|
45
|
-
|
|
37
|
+
declare const mongoDBInlineProjection: <Doc extends Document, EventType extends Event, EventMetaDataType extends MongoDBReadEventMetadata = MongoDBReadEventMetadata>(options: MongoDBInlineProjectionOptions<Doc, EventType, EventMetaDataType>) => MongoDBInlineProjectionDefinition;
|
|
38
|
+
|
|
39
|
+
type MongoDBInlineProjectionSpecGivenEvents<StreamNameType extends StreamName, EventType extends Event> = {
|
|
40
|
+
streamName: StreamNameType;
|
|
41
|
+
events: EventType[];
|
|
42
|
+
};
|
|
43
|
+
type MongoDBInlineProjectionAssertOptions<StreamNameType extends StreamName = StreamName> = {
|
|
44
|
+
streamName: StreamNameType;
|
|
45
|
+
eventStore: MongoDBEventStore;
|
|
46
|
+
};
|
|
47
|
+
type MongoDBInlineProjectionAssert<StreamNameType extends StreamName = StreamName> = (options: MongoDBInlineProjectionAssertOptions<StreamNameType>) => Promise<void | boolean>;
|
|
48
|
+
type MongoDBInlineProjectionSpecOptions = {
|
|
49
|
+
projection: MongoDBInlineProjectionDefinition;
|
|
50
|
+
} & MongoDBEventStoreConnectionOptions;
|
|
51
|
+
type MongoDBInlineProjectionSpec<StreamNameType extends StreamName, EventType extends Event> = (givenStream: MongoDBInlineProjectionSpecGivenEvents<StreamNameType, EventType>) => {
|
|
52
|
+
when: (events: EventType[]) => {
|
|
53
|
+
then: (assert: MongoDBInlineProjectionAssert, message?: string) => Promise<void>;
|
|
54
|
+
thenThrows: <ErrorType extends Error = Error>(...args: Parameters<ThenThrows<ErrorType>>) => Promise<void>;
|
|
55
|
+
};
|
|
56
|
+
};
|
|
57
|
+
declare const MongoDBInlineProjectionSpec: {
|
|
58
|
+
for: <StreamNameType extends StreamName, EventType extends Event>(options: MongoDBInlineProjectionSpecOptions) => MongoDBInlineProjectionSpec<StreamNameType, EventType>;
|
|
59
|
+
};
|
|
60
|
+
declare const eventInStream: <StreamNameType extends StreamName, EventType extends Event>(streamName: StreamNameType, event: EventType) => MongoDBInlineProjectionSpecGivenEvents<StreamNameType, EventType>;
|
|
61
|
+
declare const eventsInStream: <StreamNameType extends StreamName, EventType extends Event>(streamName: StreamNameType, events: EventType[]) => MongoDBInlineProjectionSpecGivenEvents<StreamNameType, EventType>;
|
|
62
|
+
declare const expectInlineReadModel: {
|
|
63
|
+
toHave: <Doc extends Document, StreamNameType extends StreamName = `${string}:${string}`>(expected: Partial<MongoDBReadModel<Doc>> | null) => MongoDBInlineProjectionAssert<StreamNameType>;
|
|
64
|
+
toDeepEquals: <Doc extends Document, StreamNameType extends StreamName = `${string}:${string}`>(expected: MongoDBReadModel<Doc> | null) => MongoDBInlineProjectionAssert<StreamNameType>;
|
|
65
|
+
toMatch: <Doc extends Document, StreamNameType extends StreamName = `${string}:${string}`>(match: (readModel: MongoDBReadModel<Doc> | null) => boolean) => MongoDBInlineProjectionAssert<StreamNameType>;
|
|
66
|
+
notToExist: <StreamNameType extends StreamName = `${string}:${string}`>() => MongoDBInlineProjectionAssert<StreamNameType>;
|
|
67
|
+
toExist: () => MongoDBInlineProjectionAssert;
|
|
68
|
+
withName: (name: string) => {
|
|
69
|
+
toHave: <Doc extends Document, StreamNameType extends StreamName = `${string}:${string}`>(expected: Partial<MongoDBReadModel<Doc>> | null) => MongoDBInlineProjectionAssert<StreamNameType>;
|
|
70
|
+
toDeepEquals: <Doc extends Document, StreamNameType extends StreamName = `${string}:${string}`>(expected: MongoDBReadModel<Doc> | null) => MongoDBInlineProjectionAssert<StreamNameType>;
|
|
71
|
+
toMatch: <Doc extends Document, StreamNameType extends StreamName = `${string}:${string}`>(match: (readModel: MongoDBReadModel<Doc> | null) => boolean) => MongoDBInlineProjectionAssert<StreamNameType>;
|
|
72
|
+
notToExist: <StreamNameType extends StreamName = `${string}:${string}`>() => MongoDBInlineProjectionAssert<StreamNameType>;
|
|
73
|
+
toExist: () => MongoDBInlineProjectionAssert;
|
|
74
|
+
};
|
|
75
|
+
};
|
|
46
76
|
|
|
47
77
|
type MongoDBEventStoreCollectionPerStreamTypeStorageOptions = {
|
|
48
78
|
/**
|
|
@@ -106,7 +136,7 @@ type MongoDBReadModelMetadata = {
|
|
|
106
136
|
type MongoDBReadModel<Doc extends Document = Document> = Doc & {
|
|
107
137
|
_metadata: MongoDBReadModelMetadata;
|
|
108
138
|
};
|
|
109
|
-
interface EventStream<EventType extends Event = Event, EventMetaDataType extends
|
|
139
|
+
interface EventStream<EventType extends Event = Event, EventMetaDataType extends MongoDBReadEventMetadata = MongoDBReadEventMetadata> {
|
|
110
140
|
streamName: string;
|
|
111
141
|
messages: Array<ReadEvent<EventType, EventMetaDataType>>;
|
|
112
142
|
metadata: {
|
|
@@ -187,10 +217,11 @@ type MongoDBEventStoreConnectionStringOptions = {
|
|
|
187
217
|
connectionString: string;
|
|
188
218
|
clientOptions?: MongoClientOptions;
|
|
189
219
|
};
|
|
220
|
+
type MongoDBEventStoreConnectionOptions = MongoDBEventStoreClientOptions | MongoDBEventStoreConnectionStringOptions;
|
|
190
221
|
type MongoDBEventStoreOptions = {
|
|
191
222
|
projections?: ProjectionRegistration<'inline', MongoDBReadEventMetadata, MongoDBProjectionInlineHandlerContext>[];
|
|
192
223
|
storage?: MongoDBEventStoreStorageOptions;
|
|
193
|
-
} &
|
|
224
|
+
} & MongoDBEventStoreConnectionOptions;
|
|
194
225
|
type MongoDBEventStore = EventStore<MongoDBReadEventMetadata> & {
|
|
195
226
|
projections: ProjectionQueries<StreamType>;
|
|
196
227
|
collectionFor: <EventType extends Event>(streamType: StreamType) => Promise<Collection<EventStream<EventType>>>;
|
|
@@ -226,4 +257,4 @@ declare function toStreamCollectionName<T extends StreamType>(streamType: T): St
|
|
|
226
257
|
*/
|
|
227
258
|
declare function fromStreamCollectionName<T extends StreamType>(streamCollectionName: StreamCollectionName<T>): StreamCollectionNameParts<T>;
|
|
228
259
|
|
|
229
|
-
export { DefaultMongoDBEventStoreCollectionName, DefaultMongoDBEventStoreStorageOptions, type EventStream, type InlineProjectionHandlerOptions, MongoDBDefaultInlineProjectionName, type MongoDBEventStore, type MongoDBEventStoreCollectionPerStreamTypeStorageOptions, type MongoDBEventStoreCollectionResolution, type MongoDBEventStoreCustomStorageOptions, MongoDBEventStoreDefaultStreamVersion, type MongoDBEventStoreOptions, type MongoDBEventStoreSingleCollectionStorageOptions, type MongoDBEventStoreStorage, type MongoDBEventStoreStorageOptions, type MongoDBInlineProjectionDefinition, type MongoDBInlineProjectionHandler, type MongoDBInlineProjectionOptions, type MongoDBProjectionInlineHandlerContext, type MongoDBReadEvent, type MongoDBReadEventMetadata, type MongoDBReadModel, type MongoDBReadModelMetadata, type MongoDBWithNotNullDocumentEvolve, type MongoDBWithNullableDocumentEvolve, type StreamCollectionName, type StreamCollectionNameParts, type StreamName, type StreamNameParts, type StreamType, fromStreamCollectionName, fromStreamName, getMongoDBEventStore, handleInlineProjections, mongoDBEventStoreStorage, mongoDBInlineProjection, prependMongoFilterWithProjectionPrefix, toStreamCollectionName, toStreamName };
|
|
260
|
+
export { DefaultMongoDBEventStoreCollectionName, DefaultMongoDBEventStoreStorageOptions, type EventStream, type InlineProjectionHandlerOptions, MongoDBDefaultInlineProjectionName, type MongoDBEventStore, type MongoDBEventStoreClientOptions, type MongoDBEventStoreCollectionPerStreamTypeStorageOptions, type MongoDBEventStoreCollectionResolution, type MongoDBEventStoreConnectionOptions, type MongoDBEventStoreConnectionStringOptions, type MongoDBEventStoreCustomStorageOptions, MongoDBEventStoreDefaultStreamVersion, type MongoDBEventStoreOptions, type MongoDBEventStoreSingleCollectionStorageOptions, type MongoDBEventStoreStorage, type MongoDBEventStoreStorageOptions, type MongoDBInlineProjectionAssert, type MongoDBInlineProjectionAssertOptions, type MongoDBInlineProjectionDefinition, type MongoDBInlineProjectionHandler, type MongoDBInlineProjectionOptions, MongoDBInlineProjectionSpec, type MongoDBInlineProjectionSpecGivenEvents, type MongoDBInlineProjectionSpecOptions, type MongoDBProjectionInlineHandlerContext, type MongoDBReadEvent, type MongoDBReadEventMetadata, type MongoDBReadModel, type MongoDBReadModelMetadata, type MongoDBWithNotNullDocumentEvolve, type MongoDBWithNullableDocumentEvolve, type StreamCollectionName, type StreamCollectionNameParts, type StreamName, type StreamNameParts, type StreamType, eventInStream, eventsInStream, expectInlineReadModel, fromStreamCollectionName, fromStreamName, getMongoDBEventStore, handleInlineProjections, mongoDBEventStoreStorage, mongoDBInlineProjection, prependMongoFilterWithProjectionPrefix, toStreamCollectionName, toStreamName };
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
|
-
// ../emmett/dist/chunk-
|
|
1
|
+
// ../emmett/dist/chunk-4E7QLAH5.js
|
|
2
2
|
var isNumber = (val) => typeof val === "number" && val === val;
|
|
3
3
|
var isString = (val) => typeof val === "string";
|
|
4
|
+
var isErrorConstructor = (expect) => {
|
|
5
|
+
return typeof expect === "function" && expect.prototype && // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
6
|
+
expect.prototype.constructor === expect;
|
|
7
|
+
};
|
|
4
8
|
var EmmettError = class _EmmettError extends Error {
|
|
5
9
|
errorCode;
|
|
6
10
|
constructor(options) {
|
|
@@ -101,6 +105,72 @@ var NotifyAboutNoActiveReadersStream = class extends TransformStream2 {
|
|
|
101
105
|
}
|
|
102
106
|
}
|
|
103
107
|
};
|
|
108
|
+
var hasDuplicates = (array, predicate) => {
|
|
109
|
+
const mapped = array.map(predicate);
|
|
110
|
+
const uniqueValues = new Set(mapped);
|
|
111
|
+
return uniqueValues.size < mapped.length;
|
|
112
|
+
};
|
|
113
|
+
var getDuplicates = (array, predicate) => {
|
|
114
|
+
const map2 = /* @__PURE__ */ new Map();
|
|
115
|
+
for (let i = 0; i < array.length; i++) {
|
|
116
|
+
const item = array[i];
|
|
117
|
+
const key = predicate(item, i, array);
|
|
118
|
+
if (!map2.has(key)) {
|
|
119
|
+
map2.set(key, []);
|
|
120
|
+
}
|
|
121
|
+
map2.get(key).push(item);
|
|
122
|
+
}
|
|
123
|
+
return Array.from(map2.values()).filter((group) => group.length > 1).flat();
|
|
124
|
+
};
|
|
125
|
+
var merge = (array, item, where, onExisting, onNotFound = () => void 0) => {
|
|
126
|
+
let wasFound = false;
|
|
127
|
+
const result = array.map((p) => {
|
|
128
|
+
if (!where(p)) return p;
|
|
129
|
+
wasFound = true;
|
|
130
|
+
return onExisting(p);
|
|
131
|
+
}).filter((p) => p !== void 0).map((p) => {
|
|
132
|
+
if (!p) throw Error("That should not happen");
|
|
133
|
+
return p;
|
|
134
|
+
});
|
|
135
|
+
if (!wasFound) {
|
|
136
|
+
const result2 = onNotFound();
|
|
137
|
+
if (result2 !== void 0) return [...array, item];
|
|
138
|
+
}
|
|
139
|
+
return result;
|
|
140
|
+
};
|
|
141
|
+
var arrayUtils = {
|
|
142
|
+
merge,
|
|
143
|
+
hasDuplicates,
|
|
144
|
+
getDuplicates
|
|
145
|
+
};
|
|
146
|
+
var deepEquals = (left, right) => {
|
|
147
|
+
if (isEquatable(left)) {
|
|
148
|
+
return left.equals(right);
|
|
149
|
+
}
|
|
150
|
+
if (Array.isArray(left)) {
|
|
151
|
+
return Array.isArray(right) && left.length === right.length && left.every((val, index) => deepEquals(val, right[index]));
|
|
152
|
+
}
|
|
153
|
+
if (typeof left !== "object" || typeof right !== "object" || left === null || right === null) {
|
|
154
|
+
return left === right;
|
|
155
|
+
}
|
|
156
|
+
if (Array.isArray(right)) return false;
|
|
157
|
+
const keys1 = Object.keys(left);
|
|
158
|
+
const keys2 = Object.keys(right);
|
|
159
|
+
if (keys1.length !== keys2.length || !keys1.every((key) => keys2.includes(key)))
|
|
160
|
+
return false;
|
|
161
|
+
for (const key in left) {
|
|
162
|
+
if (left[key] instanceof Function && right[key] instanceof Function)
|
|
163
|
+
continue;
|
|
164
|
+
const isEqual = deepEquals(left[key], right[key]);
|
|
165
|
+
if (!isEqual) {
|
|
166
|
+
return false;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
return true;
|
|
170
|
+
};
|
|
171
|
+
var isEquatable = (left) => {
|
|
172
|
+
return left && typeof left === "object" && "equals" in left && typeof left["equals"] === "function";
|
|
173
|
+
};
|
|
104
174
|
var asyncRetry = async (fn, opts) => {
|
|
105
175
|
if (opts === void 0 || opts.retries === 0) return fn();
|
|
106
176
|
return retry(
|
|
@@ -117,6 +187,47 @@ var asyncRetry = async (fn, opts) => {
|
|
|
117
187
|
opts ?? { retries: 0 }
|
|
118
188
|
);
|
|
119
189
|
};
|
|
190
|
+
var ParseError = class extends Error {
|
|
191
|
+
constructor(text) {
|
|
192
|
+
super(`Cannot parse! ${text}`);
|
|
193
|
+
}
|
|
194
|
+
};
|
|
195
|
+
var JSONParser = {
|
|
196
|
+
stringify: (value, options) => {
|
|
197
|
+
return JSON.stringify(
|
|
198
|
+
options?.map ? options.map(value) : value,
|
|
199
|
+
//TODO: Consider adding support to DateTime and adding specific format to mark that's a bigint
|
|
200
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
201
|
+
(_, v) => typeof v === "bigint" ? v.toString() : v
|
|
202
|
+
);
|
|
203
|
+
},
|
|
204
|
+
parse: (text, options) => {
|
|
205
|
+
const parsed = JSON.parse(text, options?.reviver);
|
|
206
|
+
if (options?.typeCheck && !options?.typeCheck(parsed))
|
|
207
|
+
throw new ParseError(text);
|
|
208
|
+
return options?.map ? options.map(parsed) : parsed;
|
|
209
|
+
}
|
|
210
|
+
};
|
|
211
|
+
var filterProjections = (type, projections2) => {
|
|
212
|
+
const inlineProjections2 = projections2.filter((projection2) => projection2.type === type).map(({ projection: projection2 }) => projection2);
|
|
213
|
+
const duplicateRegistrations = arrayUtils.getDuplicates(
|
|
214
|
+
inlineProjections2,
|
|
215
|
+
(proj) => proj.name
|
|
216
|
+
);
|
|
217
|
+
if (duplicateRegistrations.length > 0) {
|
|
218
|
+
throw new EmmettError(`You cannot register multiple projections with the same name (or without the name).
|
|
219
|
+
Ensure that:
|
|
220
|
+
${JSONParser.stringify(duplicateRegistrations)}
|
|
221
|
+
have different names`);
|
|
222
|
+
}
|
|
223
|
+
return inlineProjections2;
|
|
224
|
+
};
|
|
225
|
+
var inlineProjections = (definitions) => definitions.map((projection2) => ({ type: "inline", projection: projection2 }));
|
|
226
|
+
var asyncProjections = (definitions) => definitions.map((projection2) => ({ type: "async", projection: projection2 }));
|
|
227
|
+
var projections = {
|
|
228
|
+
inline: inlineProjections,
|
|
229
|
+
async: asyncProjections
|
|
230
|
+
};
|
|
120
231
|
var filter = (filter2) => new TransformStream3({
|
|
121
232
|
transform(chunk, controller) {
|
|
122
233
|
if (filter2(chunk)) {
|
|
@@ -258,14 +369,41 @@ var streamTransformations = {
|
|
|
258
369
|
waitAtMost
|
|
259
370
|
};
|
|
260
371
|
var { retry: retry2 } = streamTransformations;
|
|
372
|
+
var AssertionError = class extends Error {
|
|
373
|
+
constructor(message) {
|
|
374
|
+
super(message);
|
|
375
|
+
}
|
|
376
|
+
};
|
|
377
|
+
var isSubset = (superObj, subObj) => {
|
|
378
|
+
const sup = superObj;
|
|
379
|
+
const sub = subObj;
|
|
380
|
+
assertOk(sup);
|
|
381
|
+
assertOk(sub);
|
|
382
|
+
return Object.keys(sub).every((ele) => {
|
|
383
|
+
if (typeof sub[ele] == "object") {
|
|
384
|
+
return isSubset(sup[ele], sub[ele]);
|
|
385
|
+
}
|
|
386
|
+
return sub[ele] === sup[ele];
|
|
387
|
+
});
|
|
388
|
+
};
|
|
389
|
+
var assertFails = (message) => {
|
|
390
|
+
throw new AssertionError(message ?? "That should not ever happened, right?");
|
|
391
|
+
};
|
|
392
|
+
function assertTrue(condition, message) {
|
|
393
|
+
if (condition !== true)
|
|
394
|
+
throw new AssertionError(message ?? `Condition is false`);
|
|
395
|
+
}
|
|
396
|
+
function assertOk(obj, message) {
|
|
397
|
+
if (!obj) throw new AssertionError(message ?? `Condition is not truthy`);
|
|
398
|
+
}
|
|
261
399
|
|
|
262
400
|
// src/eventStore/mongoDBEventStore.ts
|
|
263
401
|
import {
|
|
264
|
-
MongoClient
|
|
402
|
+
MongoClient as MongoClient2
|
|
265
403
|
} from "mongodb";
|
|
266
404
|
import { v4 as uuid4 } from "uuid";
|
|
267
405
|
|
|
268
|
-
// src/eventStore/projections/
|
|
406
|
+
// src/eventStore/projections/mongoDBInlineProjection.ts
|
|
269
407
|
var MongoDBDefaultInlineProjectionName = "_default";
|
|
270
408
|
var handleInlineProjections = async (options) => {
|
|
271
409
|
const {
|
|
@@ -277,10 +415,10 @@ var handleInlineProjections = async (options) => {
|
|
|
277
415
|
readModels
|
|
278
416
|
} = options;
|
|
279
417
|
const eventTypes = events.map((e) => e.type);
|
|
280
|
-
const
|
|
418
|
+
const projections2 = allProjections.filter(
|
|
281
419
|
(p) => p.canHandle.some((type) => eventTypes.includes(type))
|
|
282
420
|
);
|
|
283
|
-
for (const projection of
|
|
421
|
+
for (const projection of projections2) {
|
|
284
422
|
await projection.handle(events, {
|
|
285
423
|
document: readModels[projection.name] ?? null,
|
|
286
424
|
streamId,
|
|
@@ -318,6 +456,135 @@ var mongoDBInlineProjection = (options) => {
|
|
|
318
456
|
};
|
|
319
457
|
};
|
|
320
458
|
|
|
459
|
+
// src/eventStore/projections/mongoDBInlineProjectionSpec.ts
|
|
460
|
+
import { MongoClient } from "mongodb";
|
|
461
|
+
var MongoDBInlineProjectionSpec = {
|
|
462
|
+
for: (options) => {
|
|
463
|
+
{
|
|
464
|
+
const { projection, ...connectionOptions } = options;
|
|
465
|
+
return (givenStream) => {
|
|
466
|
+
const { streamName, events: givenEvents } = givenStream;
|
|
467
|
+
return {
|
|
468
|
+
when: (events) => {
|
|
469
|
+
const allEvents = [...givenEvents, ...events];
|
|
470
|
+
const run = (eventStore) => eventStore.appendToStream(streamName, allEvents);
|
|
471
|
+
return {
|
|
472
|
+
then: async (assert, message) => {
|
|
473
|
+
const client = "client" in connectionOptions && connectionOptions.client ? connectionOptions.client : new MongoClient(
|
|
474
|
+
connectionOptions.connectionString,
|
|
475
|
+
connectionOptions.clientOptions
|
|
476
|
+
);
|
|
477
|
+
const eventStore = getMongoDBEventStore({
|
|
478
|
+
projections: projections.inline([projection]),
|
|
479
|
+
client
|
|
480
|
+
});
|
|
481
|
+
try {
|
|
482
|
+
await run(eventStore);
|
|
483
|
+
const succeeded = await assert({ eventStore, streamName });
|
|
484
|
+
if (succeeded !== void 0 && succeeded === false)
|
|
485
|
+
assertFails(
|
|
486
|
+
message ?? "Projection specification didn't match the criteria"
|
|
487
|
+
);
|
|
488
|
+
} finally {
|
|
489
|
+
await client.close();
|
|
490
|
+
}
|
|
491
|
+
},
|
|
492
|
+
thenThrows: async (...args) => {
|
|
493
|
+
const client = "client" in connectionOptions && connectionOptions.client ? connectionOptions.client : new MongoClient(
|
|
494
|
+
connectionOptions.connectionString,
|
|
495
|
+
connectionOptions.clientOptions
|
|
496
|
+
);
|
|
497
|
+
const eventStore = getMongoDBEventStore({
|
|
498
|
+
projections: projections.inline([projection]),
|
|
499
|
+
client
|
|
500
|
+
});
|
|
501
|
+
try {
|
|
502
|
+
await run(eventStore);
|
|
503
|
+
throw new AssertionError("Handler did not fail as expected");
|
|
504
|
+
} catch (error) {
|
|
505
|
+
if (error instanceof AssertionError) throw error;
|
|
506
|
+
if (args.length === 0) return;
|
|
507
|
+
if (!isErrorConstructor(args[0])) {
|
|
508
|
+
assertTrue(
|
|
509
|
+
args[0](error),
|
|
510
|
+
`Error didn't match the error condition: ${error?.toString()}`
|
|
511
|
+
);
|
|
512
|
+
return;
|
|
513
|
+
}
|
|
514
|
+
assertTrue(
|
|
515
|
+
error instanceof args[0],
|
|
516
|
+
`Caught error is not an instance of the expected type: ${error?.toString()}`
|
|
517
|
+
);
|
|
518
|
+
if (args[1]) {
|
|
519
|
+
assertTrue(
|
|
520
|
+
args[1](error),
|
|
521
|
+
`Error didn't match the error condition: ${error?.toString()}`
|
|
522
|
+
);
|
|
523
|
+
}
|
|
524
|
+
} finally {
|
|
525
|
+
await client.close();
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
};
|
|
529
|
+
}
|
|
530
|
+
};
|
|
531
|
+
};
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
};
|
|
535
|
+
var eventInStream = (streamName, event) => ({
|
|
536
|
+
streamName,
|
|
537
|
+
events: [event]
|
|
538
|
+
});
|
|
539
|
+
var eventsInStream = (streamName, events) => ({
|
|
540
|
+
streamName,
|
|
541
|
+
events
|
|
542
|
+
});
|
|
543
|
+
var expectReadModelToMatch = async (options) => {
|
|
544
|
+
const { streamName, projectionName, eventStore, match } = options;
|
|
545
|
+
const readModel = await eventStore.projections.inline.findOne({
|
|
546
|
+
streamName,
|
|
547
|
+
projectionName
|
|
548
|
+
});
|
|
549
|
+
return match(readModel);
|
|
550
|
+
};
|
|
551
|
+
var expectInlineReadModelWithName = (projectionName) => ({
|
|
552
|
+
toHave: (expected) => ({ eventStore, streamName }) => expectReadModelToMatch({
|
|
553
|
+
eventStore,
|
|
554
|
+
streamName,
|
|
555
|
+
projectionName,
|
|
556
|
+
match: (readModel) => isSubset(readModel, expected)
|
|
557
|
+
}),
|
|
558
|
+
toDeepEquals: (expected) => ({ eventStore, streamName }) => expectReadModelToMatch({
|
|
559
|
+
eventStore,
|
|
560
|
+
streamName,
|
|
561
|
+
projectionName,
|
|
562
|
+
match: (readModel) => deepEquals(readModel, expected)
|
|
563
|
+
}),
|
|
564
|
+
toMatch: (match) => ({ eventStore, streamName }) => expectReadModelToMatch({
|
|
565
|
+
eventStore,
|
|
566
|
+
streamName,
|
|
567
|
+
projectionName,
|
|
568
|
+
match
|
|
569
|
+
}),
|
|
570
|
+
notToExist: () => ({ eventStore, streamName }) => expectReadModelToMatch({
|
|
571
|
+
eventStore,
|
|
572
|
+
streamName,
|
|
573
|
+
projectionName,
|
|
574
|
+
match: (readModel) => readModel === null
|
|
575
|
+
}),
|
|
576
|
+
toExist: () => ({ eventStore, streamName }) => expectReadModelToMatch({
|
|
577
|
+
eventStore,
|
|
578
|
+
streamName,
|
|
579
|
+
projectionName,
|
|
580
|
+
match: (readModel) => readModel !== null
|
|
581
|
+
})
|
|
582
|
+
});
|
|
583
|
+
var expectInlineReadModel = {
|
|
584
|
+
withName: (name) => expectInlineReadModelWithName(name),
|
|
585
|
+
...expectInlineReadModelWithName(MongoDBDefaultInlineProjectionName)
|
|
586
|
+
};
|
|
587
|
+
|
|
321
588
|
// src/eventStore/storage/mongoDBEventStoreStorage.ts
|
|
322
589
|
var DefaultMongoDBEventStoreStorageOptions = "COLLECTION_PER_STREAM_TYPE";
|
|
323
590
|
var DefaultMongoDBEventStoreCollectionName = "emt:streams";
|
|
@@ -399,14 +666,15 @@ var MongoDBEventStoreImplementation = class {
|
|
|
399
666
|
projections;
|
|
400
667
|
storage;
|
|
401
668
|
constructor(options) {
|
|
402
|
-
this.client = "client" in options && options.client ? options.client : new
|
|
669
|
+
this.client = "client" in options && options.client ? options.client : new MongoClient2(options.connectionString, options.clientOptions);
|
|
403
670
|
this.shouldManageClientLifetime = !("client" in options);
|
|
404
671
|
this.storage = mongoDBEventStoreStorage({
|
|
405
672
|
storage: options.storage,
|
|
406
673
|
getConnectedClient: () => this.getConnectedClient()
|
|
407
674
|
});
|
|
408
|
-
this.inlineProjections = (
|
|
409
|
-
|
|
675
|
+
this.inlineProjections = filterProjections(
|
|
676
|
+
"inline",
|
|
677
|
+
options.projections ?? []
|
|
410
678
|
);
|
|
411
679
|
this.projections = {
|
|
412
680
|
inline: {
|
|
@@ -499,7 +767,7 @@ var MongoDBEventStoreImplementation = class {
|
|
|
499
767
|
data: event.data,
|
|
500
768
|
metadata: {
|
|
501
769
|
...metadata,
|
|
502
|
-
...event.metadata ?? {}
|
|
770
|
+
..."metadata" in event ? event.metadata ?? {} : {}
|
|
503
771
|
}
|
|
504
772
|
};
|
|
505
773
|
});
|
|
@@ -757,6 +1025,10 @@ export {
|
|
|
757
1025
|
DefaultMongoDBEventStoreStorageOptions,
|
|
758
1026
|
MongoDBDefaultInlineProjectionName,
|
|
759
1027
|
MongoDBEventStoreDefaultStreamVersion,
|
|
1028
|
+
MongoDBInlineProjectionSpec,
|
|
1029
|
+
eventInStream,
|
|
1030
|
+
eventsInStream,
|
|
1031
|
+
expectInlineReadModel,
|
|
760
1032
|
fromStreamCollectionName,
|
|
761
1033
|
fromStreamName,
|
|
762
1034
|
getMongoDBEventStore,
|