Skip to content

Commit cbd6a4d

Browse files
feat: Add support for the isEventQlTrue precondition (#241)
* feat: add isEventQLTrue precondition and corresponding test * chore: adjsut precondition casing * chore: adjust readme * Update README.md Co-authored-by: Golo Roden <[email protected]> --------- Co-authored-by: Golo Roden <[email protected]>
1 parent 5ef011a commit cbd6a4d

File tree

5 files changed

+77
-1
lines changed

5 files changed

+77
-1
lines changed

README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,22 @@ const writtenEvents = await client.writeEvents([
9494

9595
*Note that according to the CloudEvents standard, event IDs must be of type string.*
9696

97+
#### Using the `isEventQlTrue` precondition
98+
99+
If you want to write events depending on an EventQL query, import the `isEventQlTrue` function and pass it as an array of preconditions in the second argument:
100+
101+
```typescript
102+
import { isEventQlTrue } from 'eventsourcingdb';
103+
104+
const writtenEvents = await client.writeEvents([
105+
// events
106+
], [
107+
isEventQlTrue(`FROM e IN events WHERE e.type == 'io.eventsourcingdb.library.book-borrowed' PROJECT INTO COUNT() < 10`)
108+
]);
109+
```
110+
111+
*Note that the query must return a single row with a single value, which is interpreted as a boolean.*
112+
97113
### Reading Events
98114

99115
To read all events of a subject, call the `readEvents` function with the subject as the first argument and an options object as the second argument. Set the `recursive` option to `false`. This ensures that only events of the given subject are returned, not events of nested subjects.

docker/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
FROM thenativeweb/eventsourcingdb:1.0.3
1+
FROM thenativeweb/eventsourcingdb:preview

src/Precondition.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ interface IsSubjectOnEventIdPrecondition {
77
eventId: string;
88
}
99

10+
interface IsEventQlTruePrecondition {
11+
query: string;
12+
}
13+
1014
type Precondition =
1115
| {
1216
type: 'isSubjectPristine';
@@ -15,6 +19,10 @@ type Precondition =
1519
| {
1620
type: 'isSubjectOnEventId';
1721
payload: IsSubjectOnEventIdPrecondition;
22+
}
23+
| {
24+
type: 'isEventQlTrue';
25+
payload: IsEventQlTruePrecondition;
1826
};
1927

2028
export type { Precondition };

src/isEventQlTrue.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import type { Precondition } from './Precondition.js';
2+
3+
const isEventQlTrue = (query: string): Precondition => {
4+
return {
5+
type: 'isEventQlTrue',
6+
payload: { query },
7+
};
8+
};
9+
10+
export { isEventQlTrue };

src/writeEvents.test.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { afterEach, beforeEach, suite, test } from 'node:test';
33
import { Container } from './Container.js';
44
import type { EventCandidate } from './EventCandidate.js';
55
import { getImageVersionFromDockerfile } from './getImageVersionFromDockerfile.js';
6+
import { isEventQlTrue } from './isEventQlTrue.js';
67
import { isSubjectOnEventId } from './isSubjectOnEventId.js';
78
import { isSubjectPristine } from './isSubjectPristine.js';
89

@@ -143,4 +144,45 @@ suite('writeEvents', { timeout: 30_000 }, () => {
143144
},
144145
);
145146
});
147+
148+
test('supports the isEventQlTrue precondition.', async (): Promise<void> => {
149+
const client = container.getClient();
150+
151+
const firstEvent: EventCandidate = {
152+
source: 'https://www.eventsourcingdb.io',
153+
subject: '/test',
154+
type: 'io.eventsourcingdb.test',
155+
data: {
156+
value: 23,
157+
},
158+
};
159+
160+
await client.writeEvents([firstEvent]);
161+
162+
const secondEvent: EventCandidate = {
163+
source: 'https://www.eventsourcingdb.io',
164+
subject: '/test',
165+
type: 'io.eventsourcingdb.test',
166+
data: {
167+
value: 42,
168+
},
169+
};
170+
171+
await assert.rejects(
172+
async () => {
173+
await client.writeEvents(
174+
[secondEvent],
175+
[isEventQlTrue('FROM e IN events PROJECT INTO COUNT() == 0')],
176+
);
177+
},
178+
error => {
179+
assert.ok(error instanceof Error);
180+
assert.equal(
181+
error.message,
182+
"Failed to write events, got HTTP status code '409', expected '200'.",
183+
);
184+
return true;
185+
},
186+
);
187+
});
146188
});

0 commit comments

Comments
 (0)