@nimbus-cqrs/core 2.1.1 → 2.2.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/README.md +31 -39
- package/esm/lib/exception/exception.d.ts +1 -1
- package/esm/lib/exception/exception.d.ts.map +1 -1
- package/esm/lib/exception/invalidInputException.d.ts +1 -1
- package/esm/lib/exception/invalidInputException.d.ts.map +1 -1
- package/esm/lib/message/command.d.ts +11 -1
- package/esm/lib/message/command.d.ts.map +1 -1
- package/esm/lib/message/command.js +17 -10
- package/esm/lib/message/event.d.ts +11 -1
- package/esm/lib/message/event.d.ts.map +1 -1
- package/esm/lib/message/event.js +17 -10
- package/esm/lib/message/message.d.ts +14 -0
- package/esm/lib/message/message.d.ts.map +1 -1
- package/esm/lib/message/message.js +47 -1
- package/esm/lib/message/query.d.ts +11 -1
- package/esm/lib/message/query.d.ts.map +1 -1
- package/esm/lib/message/query.js +16 -9
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -13,7 +13,7 @@ Refer to the [Nimbus main repository](https://github.com/overlap-dev/Nimbus) or
|
|
|
13
13
|
|
|
14
14
|
```bash
|
|
15
15
|
# Deno
|
|
16
|
-
deno add
|
|
16
|
+
deno add npm:@nimbus-cqrs/core
|
|
17
17
|
|
|
18
18
|
# NPM
|
|
19
19
|
npm install @nimbus-cqrs/core
|
|
@@ -30,17 +30,13 @@ For detailed documentation, please refer to the [Nimbus documentation](https://n
|
|
|
30
30
|
|
|
31
31
|
## Command
|
|
32
32
|
|
|
33
|
-
A **Command** asks the system to
|
|
33
|
+
A **Command** asks the system to _do_ something (a write). You declare a [Zod](https://zod.dev/) schema that extends Nimbus' built-in `commandSchema`, write a handler, and register both on the router. Incoming messages are validated against the schema before they reach your handler.
|
|
34
34
|
|
|
35
35
|
```typescript
|
|
36
|
-
import {
|
|
37
|
-
|
|
38
|
-
createCommand,
|
|
39
|
-
getRouter,
|
|
40
|
-
} from '@nimbus-cqrs/core';
|
|
41
|
-
import { z } from 'zod';
|
|
36
|
+
import { commandSchema, createCommand, getRouter } from "@nimbus-cqrs/core";
|
|
37
|
+
import { z } from "zod";
|
|
42
38
|
|
|
43
|
-
const ADD_TODO =
|
|
39
|
+
const ADD_TODO = "com.example.todo.add";
|
|
44
40
|
|
|
45
41
|
const addTodoSchema = commandSchema.extend({
|
|
46
42
|
type: z.literal(ADD_TODO),
|
|
@@ -52,7 +48,7 @@ type AddTodoCommand = z.infer<typeof addTodoSchema>;
|
|
|
52
48
|
|
|
53
49
|
const handleAddTodo = async (cmd: AddTodoCommand) => {
|
|
54
50
|
// ...persist the todo here...
|
|
55
|
-
return { id:
|
|
51
|
+
return { id: "todo-1", title: cmd.data.title, status: "open" };
|
|
56
52
|
};
|
|
57
53
|
|
|
58
54
|
const router = getRouter();
|
|
@@ -61,9 +57,9 @@ router.register(ADD_TODO, handleAddTodo, addTodoSchema);
|
|
|
61
57
|
const result = await router.route(
|
|
62
58
|
createCommand<AddTodoCommand>({
|
|
63
59
|
type: ADD_TODO,
|
|
64
|
-
source:
|
|
65
|
-
data: { title:
|
|
66
|
-
})
|
|
60
|
+
source: "https://app.example.com",
|
|
61
|
+
data: { title: "Write the README" },
|
|
62
|
+
})
|
|
67
63
|
);
|
|
68
64
|
|
|
69
65
|
console.log(result);
|
|
@@ -74,13 +70,13 @@ console.log(result);
|
|
|
74
70
|
|
|
75
71
|
## Query
|
|
76
72
|
|
|
77
|
-
A **Query** asks the system to
|
|
73
|
+
A **Query** asks the system to _read_ something. Mechanically it is identical to a Command — same router, same validation, same shape — only the intent differs.
|
|
78
74
|
|
|
79
75
|
```typescript
|
|
80
|
-
import { createQuery, getRouter, querySchema } from
|
|
81
|
-
import { z } from
|
|
76
|
+
import { createQuery, getRouter, querySchema } from "@nimbus-cqrs/core";
|
|
77
|
+
import { z } from "zod";
|
|
82
78
|
|
|
83
|
-
const GET_TODO =
|
|
79
|
+
const GET_TODO = "com.example.todo.get";
|
|
84
80
|
|
|
85
81
|
const getTodoSchema = querySchema.extend({
|
|
86
82
|
type: z.literal(GET_TODO),
|
|
@@ -90,7 +86,7 @@ type GetTodoQuery = z.infer<typeof getTodoSchema>;
|
|
|
90
86
|
|
|
91
87
|
const handleGetTodo = async (q: GetTodoQuery) => {
|
|
92
88
|
// ...load the todo from your read model...
|
|
93
|
-
return { id: q.data.id, title:
|
|
89
|
+
return { id: q.data.id, title: "Write the README", status: "open" };
|
|
94
90
|
};
|
|
95
91
|
|
|
96
92
|
const router = getRouter();
|
|
@@ -99,25 +95,21 @@ router.register(GET_TODO, handleGetTodo, getTodoSchema);
|
|
|
99
95
|
const todo = await router.route(
|
|
100
96
|
createQuery<GetTodoQuery>({
|
|
101
97
|
type: GET_TODO,
|
|
102
|
-
source:
|
|
103
|
-
data: { id:
|
|
104
|
-
})
|
|
98
|
+
source: "https://app.example.com",
|
|
99
|
+
data: { id: "todo-1" },
|
|
100
|
+
})
|
|
105
101
|
);
|
|
106
102
|
```
|
|
107
103
|
|
|
108
104
|
## Event
|
|
109
105
|
|
|
110
|
-
An **Event** announces that something
|
|
106
|
+
An **Event** announces that something _has happened_. Events are published to the in-process EventBus, which delivers them to every matching subscriber asynchronously, with exponential-backoff retries on handler errors and built-in OpenTelemetry traces and metrics.
|
|
111
107
|
|
|
112
108
|
```typescript
|
|
113
|
-
import {
|
|
114
|
-
|
|
115
|
-
eventSchema,
|
|
116
|
-
getEventBus,
|
|
117
|
-
} from '@nimbus-cqrs/core';
|
|
118
|
-
import { z } from 'zod';
|
|
109
|
+
import { createEvent, eventSchema, getEventBus } from "@nimbus-cqrs/core";
|
|
110
|
+
import { z } from "zod";
|
|
119
111
|
|
|
120
|
-
const TODO_ADDED =
|
|
112
|
+
const TODO_ADDED = "com.example.todo.added";
|
|
121
113
|
|
|
122
114
|
const todoAddedSchema = eventSchema.extend({
|
|
123
115
|
type: z.literal(TODO_ADDED),
|
|
@@ -143,10 +135,10 @@ eventBus.subscribeEvent<TodoAddedEvent>({
|
|
|
143
135
|
eventBus.putEvent(
|
|
144
136
|
createEvent<TodoAddedEvent>({
|
|
145
137
|
type: TODO_ADDED,
|
|
146
|
-
source:
|
|
147
|
-
subject:
|
|
148
|
-
data: { id:
|
|
149
|
-
})
|
|
138
|
+
source: "https://app.example.com",
|
|
139
|
+
subject: "/todos/todo-1",
|
|
140
|
+
data: { id: "todo-1", title: "Write the README" },
|
|
141
|
+
})
|
|
150
142
|
);
|
|
151
143
|
```
|
|
152
144
|
|
|
@@ -157,27 +149,27 @@ A typical flow is to publish an event from inside a command handler once the wri
|
|
|
157
149
|
A typical app configures a single named router at startup with cross-cutting concerns (logging, correlation IDs, …) and then resolves it from anywhere via `getRouter()`.
|
|
158
150
|
|
|
159
151
|
```typescript
|
|
160
|
-
import { getLogger, getRouter, setupRouter } from
|
|
152
|
+
import { getLogger, getRouter, setupRouter } from "@nimbus-cqrs/core";
|
|
161
153
|
|
|
162
|
-
setupRouter(
|
|
154
|
+
setupRouter("default", {
|
|
163
155
|
logInput: (input) => {
|
|
164
156
|
getLogger().debug({
|
|
165
|
-
category:
|
|
157
|
+
category: "Router",
|
|
166
158
|
message: `Routing ${input.type}`,
|
|
167
159
|
correlationId: input.correlationid,
|
|
168
160
|
});
|
|
169
161
|
},
|
|
170
162
|
logOutput: (output) => {
|
|
171
163
|
getLogger().debug({
|
|
172
|
-
category:
|
|
173
|
-
message:
|
|
164
|
+
category: "Router",
|
|
165
|
+
message: "Handler completed",
|
|
174
166
|
data: { output },
|
|
175
167
|
});
|
|
176
168
|
},
|
|
177
169
|
});
|
|
178
170
|
|
|
179
171
|
// Anywhere else in your app:
|
|
180
|
-
const router = getRouter(
|
|
172
|
+
const router = getRouter("default");
|
|
181
173
|
router.register(/* type, handler, schema */);
|
|
182
174
|
await router.route(/* command or query */);
|
|
183
175
|
```
|
|
@@ -5,6 +5,6 @@ export declare class Exception extends Error {
|
|
|
5
5
|
details?: Record<string, unknown>;
|
|
6
6
|
statusCode?: number;
|
|
7
7
|
constructor(name: string, message: string, details?: Record<string, unknown>, statusCode?: number);
|
|
8
|
-
fromError(error: Error):
|
|
8
|
+
fromError(error: Error): this;
|
|
9
9
|
}
|
|
10
10
|
//# sourceMappingURL=exception.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"exception.d.ts","sourceRoot":"","sources":["../../../src/lib/exception/exception.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,qBAAa,SAAU,SAAQ,KAAK;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,UAAU,CAAC,EAAE,MAAM,CAAC;gBAGvB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjC,UAAU,CAAC,EAAE,MAAM;IAmBhB,SAAS,CAAC,KAAK,EAAE,KAAK,GAAG,
|
|
1
|
+
{"version":3,"file":"exception.d.ts","sourceRoot":"","sources":["../../../src/lib/exception/exception.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,qBAAa,SAAU,SAAQ,KAAK;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,UAAU,CAAC,EAAE,MAAM,CAAC;gBAGvB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjC,UAAU,CAAC,EAAE,MAAM;IAmBhB,SAAS,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;CAMvC"}
|
|
@@ -13,6 +13,6 @@ export declare class InvalidInputException extends Exception {
|
|
|
13
13
|
*
|
|
14
14
|
* @returns {InvalidInputException} The InvalidInputException.
|
|
15
15
|
*/
|
|
16
|
-
fromZodError(error: ZodError):
|
|
16
|
+
fromZodError(error: ZodError): this;
|
|
17
17
|
}
|
|
18
18
|
//# sourceMappingURL=invalidInputException.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"invalidInputException.d.ts","sourceRoot":"","sources":["../../../src/lib/exception/invalidInputException.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C;;GAEG;AACH,qBAAa,qBAAsB,SAAQ,SAAS;gBACpC,OAAO,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAS/D;;;;;;;OAOG;IACI,YAAY,CAAC,KAAK,EAAE,QAAQ,GAAG,
|
|
1
|
+
{"version":3,"file":"invalidInputException.d.ts","sourceRoot":"","sources":["../../../src/lib/exception/invalidInputException.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C;;GAEG;AACH,qBAAa,qBAAsB,SAAQ,SAAS;gBACpC,OAAO,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAS/D;;;;;;;OAOG;IACI,YAAY,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI;CAa7C"}
|
|
@@ -20,6 +20,12 @@ import { z } from 'zod';
|
|
|
20
20
|
* @property {string} datacontenttype - A MIME type that indicates the format that the data is in (optional).
|
|
21
21
|
* @property {string} dataschema - An absolute URL to the schema that the data adheres to (optional).
|
|
22
22
|
*
|
|
23
|
+
* Commands may include additional CloudEvents extension attributes such as
|
|
24
|
+
* `metadata` or `authcontext`. Define them on a command-specific schema via
|
|
25
|
+
* {@link commandSchema.extend} or as an intersection type.
|
|
26
|
+
*
|
|
27
|
+
* @see https://github.com/cloudevents/spec/blob/main/cloudevents/spec.md#extension-context-attributes
|
|
28
|
+
*
|
|
23
29
|
* @template TData - The type of the data.
|
|
24
30
|
*
|
|
25
31
|
* @example
|
|
@@ -49,6 +55,10 @@ export type Command<TData = unknown> = {
|
|
|
49
55
|
datacontenttype?: string;
|
|
50
56
|
dataschema?: string;
|
|
51
57
|
};
|
|
58
|
+
/**
|
|
59
|
+
* Known command properties handled by {@link createCommand}.
|
|
60
|
+
*/
|
|
61
|
+
type CommandKnownProperty = 'specversion' | 'id' | 'correlationid' | 'time' | 'source' | 'type' | 'subject' | 'data' | 'datacontenttype' | 'dataschema';
|
|
52
62
|
/**
|
|
53
63
|
* Type alias for the command data field schema.
|
|
54
64
|
*/
|
|
@@ -90,7 +100,7 @@ export declare const commandSchema: CommandSchemaType;
|
|
|
90
100
|
* the input is validated against that type. This means fields like
|
|
91
101
|
* `type` and `data` must match the narrower types of `TCommand`.
|
|
92
102
|
*/
|
|
93
|
-
export type CreateCommandInput<TCommand extends Command = Command> = Partial<Pick<TCommand, 'id' | 'correlationid' | 'time' | 'subject' | 'datacontenttype' | 'dataschema'>> & Pick<TCommand, 'type' | 'source' | 'data'
|
|
103
|
+
export type CreateCommandInput<TCommand extends Command = Command> = Partial<Pick<TCommand, 'id' | 'correlationid' | 'time' | 'subject' | 'datacontenttype' | 'dataschema'>> & Pick<TCommand, 'type' | 'source' | 'data'> & Partial<Omit<TCommand, CommandKnownProperty>>;
|
|
94
104
|
/**
|
|
95
105
|
* Creates a command based on input data with the convenience
|
|
96
106
|
* to skip properties and use the defaults for the rest.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../../../src/lib/message/command.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../../../src/lib/message/command.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH,MAAM,MAAM,OAAO,CAAC,KAAK,GAAG,OAAO,IAAI;IACnC,WAAW,EAAE,KAAK,CAAC;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,aAAa,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,KAAK,CAAC;IACZ,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF;;GAEG;AACH,KAAK,oBAAoB,GACnB,aAAa,GACb,IAAI,GACJ,eAAe,GACf,MAAM,GACN,QAAQ,GACR,MAAM,GACN,SAAS,GACT,MAAM,GACN,iBAAiB,GACjB,YAAY,CAAC;AAEnB;;GAEG;AACH,KAAK,iBAAiB,GAAG,CAAC,CAAC,QAAQ,CAC/B;IACI,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,UAAU,CAAC;IACtC,CAAC,CAAC,SAAS;IACX,CAAC,CAAC,SAAS;IACX,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC;IACxB,CAAC,CAAC,UAAU;CACf,CACJ,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,SAAS,CAAC;IACxC,WAAW,EAAE,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;IACjC,EAAE,EAAE,CAAC,CAAC,SAAS,CAAC;IAChB,aAAa,EAAE,CAAC,CAAC,SAAS,CAAC;IAC3B,IAAI,EAAE,CAAC,CAAC,cAAc,CAAC;IACvB,MAAM,EAAE,CAAC,CAAC,SAAS,CAAC;IACpB,IAAI,EAAE,CAAC,CAAC,SAAS,CAAC;IAClB,OAAO,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IACpC,IAAI,EAAE,iBAAiB,CAAC;IACxB,eAAe,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IAC5C,UAAU,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;CACvC,CAAC,CAAC;AAEH;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa,EAAE,iBAiBL,CAAC;AAExB;;;;;;GAMG;AACH,MAAM,MAAM,kBAAkB,CAAC,QAAQ,SAAS,OAAO,GAAG,OAAO,IAC3D,OAAO,CACL,IAAI,CACA,QAAQ,EACN,IAAI,GACJ,eAAe,GACf,MAAM,GACN,SAAS,GACT,iBAAiB,GACjB,YAAY,CACjB,CACJ,GACC,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,QAAQ,GAAG,MAAM,CAAC,GAC1C,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,oBAAoB,CAAC,CAAC,CAAC;AAEpD;;;GAGG;AACH,eAAO,MAAM,aAAa,GAAI,QAAQ,SAAS,OAAO,EAClD,OAAO,kBAAkB,CAAC,QAAQ,CAAC,KACpC,QAuCF,CAAC"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ulid } from '../../deps/jsr.io/@std/ulid/1.0.0/mod.js';
|
|
2
2
|
import { z } from 'zod';
|
|
3
|
+
import { warnOnInvalidExtensionAttributeNames } from './message.js';
|
|
3
4
|
/**
|
|
4
5
|
* The Zod schema matching the Command type.
|
|
5
6
|
*
|
|
@@ -8,7 +9,7 @@ import { z } from 'zod';
|
|
|
8
9
|
* We do not infer the Command type from this schema because of
|
|
9
10
|
* slow type issues see https://jsr.io/docs/about-slow-types for more details.
|
|
10
11
|
*/
|
|
11
|
-
export const commandSchema = z.
|
|
12
|
+
export const commandSchema = z.looseObject({
|
|
12
13
|
specversion: z.literal('1.0'),
|
|
13
14
|
id: z.string(),
|
|
14
15
|
correlationid: z.string(),
|
|
@@ -31,17 +32,23 @@ export const commandSchema = z.object({
|
|
|
31
32
|
* to skip properties and use the defaults for the rest.
|
|
32
33
|
*/
|
|
33
34
|
export const createCommand = (input) => {
|
|
35
|
+
const { id, correlationid, time, source, type, subject, data, datacontenttype, dataschema, ...extensions } = input;
|
|
36
|
+
const correlationIdWithFallback = correlationid ?? ulid();
|
|
37
|
+
if (Object.keys(extensions).length > 0) {
|
|
38
|
+
warnOnInvalidExtensionAttributeNames(extensions, correlationIdWithFallback, createCommand);
|
|
39
|
+
}
|
|
34
40
|
const command = {
|
|
35
41
|
specversion: '1.0',
|
|
36
|
-
id:
|
|
37
|
-
correlationid:
|
|
38
|
-
time:
|
|
39
|
-
source
|
|
40
|
-
type
|
|
41
|
-
...(
|
|
42
|
-
data
|
|
43
|
-
datacontenttype:
|
|
44
|
-
...(
|
|
42
|
+
id: id ?? ulid(),
|
|
43
|
+
correlationid: correlationIdWithFallback,
|
|
44
|
+
time: time ?? new Date().toISOString(),
|
|
45
|
+
source,
|
|
46
|
+
type,
|
|
47
|
+
...(subject && { subject }),
|
|
48
|
+
data,
|
|
49
|
+
datacontenttype: datacontenttype ?? 'application/json',
|
|
50
|
+
...(dataschema && { dataschema }),
|
|
51
|
+
...extensions,
|
|
45
52
|
};
|
|
46
53
|
return command;
|
|
47
54
|
};
|
|
@@ -20,6 +20,12 @@ import { z } from 'zod';
|
|
|
20
20
|
* @property {string} datacontenttype - A MIME type that indicates the format that the data is in (optional).
|
|
21
21
|
* @property {string} dataschema - An absolute URL to the schema that the data adheres to (optional).
|
|
22
22
|
*
|
|
23
|
+
* Events may include additional CloudEvents extension attributes such as
|
|
24
|
+
* `metadata` or `authcontext`. Define them on an event-specific schema via
|
|
25
|
+
* {@link eventSchema.extend} or as an intersection type.
|
|
26
|
+
*
|
|
27
|
+
* @see https://github.com/cloudevents/spec/blob/main/cloudevents/spec.md#extension-context-attributes
|
|
28
|
+
*
|
|
23
29
|
* @template TData - The type of the data.
|
|
24
30
|
*
|
|
25
31
|
* @example
|
|
@@ -52,6 +58,10 @@ export type Event<TData = unknown> = {
|
|
|
52
58
|
datacontenttype?: string;
|
|
53
59
|
dataschema?: string;
|
|
54
60
|
};
|
|
61
|
+
/**
|
|
62
|
+
* Known event properties handled by {@link createEvent}.
|
|
63
|
+
*/
|
|
64
|
+
type EventKnownProperty = 'specversion' | 'id' | 'correlationid' | 'time' | 'source' | 'type' | 'subject' | 'data' | 'datacontenttype' | 'dataschema';
|
|
55
65
|
/**
|
|
56
66
|
* Type alias for the event data field schema.
|
|
57
67
|
*/
|
|
@@ -93,7 +103,7 @@ export declare const eventSchema: EventSchemaType;
|
|
|
93
103
|
* the input is validated against that type. This means fields like
|
|
94
104
|
* `type` and `data` must match the narrower types of `TEvent`.
|
|
95
105
|
*/
|
|
96
|
-
export type CreateEventInput<TEvent extends Event = Event> = Partial<Pick<TEvent, 'id' | 'correlationid' | 'time' | 'datacontenttype' | 'dataschema'>> & Pick<TEvent, 'type' | 'source' | 'subject' | 'data'
|
|
106
|
+
export type CreateEventInput<TEvent extends Event = Event> = Partial<Pick<TEvent, 'id' | 'correlationid' | 'time' | 'datacontenttype' | 'dataschema'>> & Pick<TEvent, 'type' | 'source' | 'subject' | 'data'> & Partial<Omit<TEvent, EventKnownProperty>>;
|
|
97
107
|
/**
|
|
98
108
|
* Creates an event based on input data with the convenience
|
|
99
109
|
* to skip properties and use the defaults for the rest.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"event.d.ts","sourceRoot":"","sources":["../../../src/lib/message/event.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"event.d.ts","sourceRoot":"","sources":["../../../src/lib/message/event.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AACH,MAAM,MAAM,KAAK,CAAC,KAAK,GAAG,OAAO,IAAI;IACjC,WAAW,EAAE,KAAK,CAAC;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,aAAa,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,KAAK,CAAC;IACZ,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF;;GAEG;AACH,KAAK,kBAAkB,GACjB,aAAa,GACb,IAAI,GACJ,eAAe,GACf,MAAM,GACN,QAAQ,GACR,MAAM,GACN,SAAS,GACT,MAAM,GACN,iBAAiB,GACjB,YAAY,CAAC;AAEnB;;GAEG;AACH,KAAK,eAAe,GAAG,CAAC,CAAC,QAAQ,CAC7B;IACI,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,UAAU,CAAC;IACtC,CAAC,CAAC,SAAS;IACX,CAAC,CAAC,SAAS;IACX,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC;IACxB,CAAC,CAAC,UAAU;CACf,CACJ,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,SAAS,CAAC;IACtC,WAAW,EAAE,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;IACjC,EAAE,EAAE,CAAC,CAAC,SAAS,CAAC;IAChB,aAAa,EAAE,CAAC,CAAC,SAAS,CAAC;IAC3B,IAAI,EAAE,CAAC,CAAC,cAAc,CAAC;IACvB,MAAM,EAAE,CAAC,CAAC,SAAS,CAAC;IACpB,IAAI,EAAE,CAAC,CAAC,SAAS,CAAC;IAClB,OAAO,EAAE,CAAC,CAAC,SAAS,CAAC;IACrB,IAAI,EAAE,eAAe,CAAC;IACtB,eAAe,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IAC5C,UAAU,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;CACvC,CAAC,CAAC;AAEH;;;;;;;GAOG;AACH,eAAO,MAAM,WAAW,EAAE,eAiBL,CAAC;AAEtB;;;;;;GAMG;AACH,MAAM,MAAM,gBAAgB,CAAC,MAAM,SAAS,KAAK,GAAG,KAAK,IACnD,OAAO,CACL,IAAI,CACA,MAAM,EACN,IAAI,GAAG,eAAe,GAAG,MAAM,GAAG,iBAAiB,GAAG,YAAY,CACrE,CACJ,GACC,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,CAAC,GACpD,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC,CAAC;AAEhD;;;GAGG;AACH,eAAO,MAAM,WAAW,GAAI,MAAM,SAAS,KAAK,EAC5C,OAAO,gBAAgB,CAAC,MAAM,CAAC,KAChC,MAuCF,CAAC"}
|
package/esm/lib/message/event.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ulid } from '../../deps/jsr.io/@std/ulid/1.0.0/mod.js';
|
|
2
2
|
import { z } from 'zod';
|
|
3
|
+
import { warnOnInvalidExtensionAttributeNames } from './message.js';
|
|
3
4
|
/**
|
|
4
5
|
* The Zod schema matching the Event type.
|
|
5
6
|
*
|
|
@@ -8,7 +9,7 @@ import { z } from 'zod';
|
|
|
8
9
|
* We do not infer the Event type from this schema because of
|
|
9
10
|
* slow type issues see https://jsr.io/docs/about-slow-types for more details.
|
|
10
11
|
*/
|
|
11
|
-
export const eventSchema = z.
|
|
12
|
+
export const eventSchema = z.looseObject({
|
|
12
13
|
specversion: z.literal('1.0'),
|
|
13
14
|
id: z.string(),
|
|
14
15
|
correlationid: z.string(),
|
|
@@ -31,17 +32,23 @@ export const eventSchema = z.object({
|
|
|
31
32
|
* to skip properties and use the defaults for the rest.
|
|
32
33
|
*/
|
|
33
34
|
export const createEvent = (input) => {
|
|
35
|
+
const { id, correlationid, time, source, type, subject, data, datacontenttype, dataschema, ...extensions } = input;
|
|
36
|
+
const correlationIdWithFallback = correlationid ?? ulid();
|
|
37
|
+
if (Object.keys(extensions).length > 0) {
|
|
38
|
+
warnOnInvalidExtensionAttributeNames(extensions, correlationIdWithFallback, createEvent);
|
|
39
|
+
}
|
|
34
40
|
const event = {
|
|
35
41
|
specversion: '1.0',
|
|
36
|
-
id:
|
|
37
|
-
correlationid:
|
|
38
|
-
time:
|
|
39
|
-
source
|
|
40
|
-
type
|
|
41
|
-
subject
|
|
42
|
-
data
|
|
43
|
-
datacontenttype:
|
|
44
|
-
...(
|
|
42
|
+
id: id ?? ulid(),
|
|
43
|
+
correlationid: correlationIdWithFallback,
|
|
44
|
+
time: time ?? new Date().toISOString(),
|
|
45
|
+
source,
|
|
46
|
+
type,
|
|
47
|
+
subject,
|
|
48
|
+
data,
|
|
49
|
+
datacontenttype: datacontenttype ?? 'application/json',
|
|
50
|
+
...(dataschema && { dataschema }),
|
|
51
|
+
...extensions,
|
|
45
52
|
};
|
|
46
53
|
return event;
|
|
47
54
|
};
|
|
@@ -15,4 +15,18 @@ import type { Query } from './query.js';
|
|
|
15
15
|
* @template TData - The type of the data.
|
|
16
16
|
*/
|
|
17
17
|
export type Message<TData = unknown> = Command<TData> | Event<TData> | Query<TData>;
|
|
18
|
+
/**
|
|
19
|
+
* Validates CloudEvents extension attribute names and logs a warning when invalid.
|
|
20
|
+
*
|
|
21
|
+
* Called by {@link createCommand}, {@link createEvent}, and {@link createQuery}
|
|
22
|
+
* to check extension attributes against the CloudEvents naming rules. Invalid
|
|
23
|
+
* names are logged with a stack trace anchored at the caller function.
|
|
24
|
+
*
|
|
25
|
+
* @see https://github.com/cloudevents/spec/blob/main/cloudevents/spec.md#extension-context-attributes
|
|
26
|
+
*
|
|
27
|
+
* @param {Record<string, unknown>} extensions - Extension attributes to validate, excluding known CloudEvents context attributes.
|
|
28
|
+
* @param {string | undefined} correlationId - Optional correlation ID included in the warning log for tracing.
|
|
29
|
+
* @param {(...args: never[]) => unknown} stackTraceAnchor - Function used to anchor the warning stack trace at the message factory caller (for example {@link createCommand}).
|
|
30
|
+
*/
|
|
31
|
+
export declare const warnOnInvalidExtensionAttributeNames: (extensions: Record<string, unknown>, correlationId: string | undefined, stackTraceAnchor: (...args: never[]) => unknown) => void;
|
|
18
32
|
//# sourceMappingURL=message.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"message.d.ts","sourceRoot":"","sources":["../../../src/lib/message/message.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"message.d.ts","sourceRoot":"","sources":["../../../src/lib/message/message.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAExC;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,OAAO,CAAC,KAAK,GAAG,OAAO,IAC7B,OAAO,CAAC,KAAK,CAAC,GACd,KAAK,CAAC,KAAK,CAAC,GACZ,KAAK,CAAC,KAAK,CAAC,CAAC;AAsCnB;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,oCAAoC,GAC7C,YAAY,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACnC,eAAe,MAAM,GAAG,SAAS,EACjC,kBAAkB,CAAC,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,OAAO,KAChD,IAkBF,CAAC"}
|
|
@@ -1 +1,47 @@
|
|
|
1
|
-
|
|
1
|
+
import { getLogger } from '../log/logger.js';
|
|
2
|
+
/**
|
|
3
|
+
* CloudEvents extension context attribute names must consist of lowercase
|
|
4
|
+
* ASCII letters or digits.
|
|
5
|
+
*
|
|
6
|
+
* @see https://github.com/cloudevents/spec/blob/main/cloudevents/spec.md#extension-context-attributes
|
|
7
|
+
*/
|
|
8
|
+
const getInvalidExtensionAttributeNames = (extensions) => {
|
|
9
|
+
const EXTENSION_ATTRIBUTE_NAME_PATTERN = /^[a-z0-9]+$/;
|
|
10
|
+
return Object.keys(extensions).filter((name) => !EXTENSION_ATTRIBUTE_NAME_PATTERN.test(name));
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Create an error object to capture the stack trace for better debugging.
|
|
14
|
+
*/
|
|
15
|
+
const createInvalidExtensionAttributeNamesError = (invalidNames, stackTraceAnchor) => {
|
|
16
|
+
const error = new Error(`Invalid CloudEvents extension attribute names: ${invalidNames.join(', ')}`);
|
|
17
|
+
if (typeof Error.captureStackTrace === 'function') {
|
|
18
|
+
Error.captureStackTrace(error, stackTraceAnchor);
|
|
19
|
+
}
|
|
20
|
+
return error;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Validates CloudEvents extension attribute names and logs a warning when invalid.
|
|
24
|
+
*
|
|
25
|
+
* Called by {@link createCommand}, {@link createEvent}, and {@link createQuery}
|
|
26
|
+
* to check extension attributes against the CloudEvents naming rules. Invalid
|
|
27
|
+
* names are logged with a stack trace anchored at the caller function.
|
|
28
|
+
*
|
|
29
|
+
* @see https://github.com/cloudevents/spec/blob/main/cloudevents/spec.md#extension-context-attributes
|
|
30
|
+
*
|
|
31
|
+
* @param {Record<string, unknown>} extensions - Extension attributes to validate, excluding known CloudEvents context attributes.
|
|
32
|
+
* @param {string | undefined} correlationId - Optional correlation ID included in the warning log for tracing.
|
|
33
|
+
* @param {(...args: never[]) => unknown} stackTraceAnchor - Function used to anchor the warning stack trace at the message factory caller (for example {@link createCommand}).
|
|
34
|
+
*/
|
|
35
|
+
export const warnOnInvalidExtensionAttributeNames = (extensions, correlationId, stackTraceAnchor) => {
|
|
36
|
+
const invalidNames = getInvalidExtensionAttributeNames(extensions);
|
|
37
|
+
if (invalidNames.length === 0) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
getLogger().warn({
|
|
41
|
+
category: 'Nimbus',
|
|
42
|
+
message: 'Extension attribute names must use lowercase ASCII letters or digits only per CloudEvents specification.',
|
|
43
|
+
data: { invalidAttributeNames: invalidNames },
|
|
44
|
+
error: createInvalidExtensionAttributeNamesError(invalidNames, stackTraceAnchor),
|
|
45
|
+
...(correlationId && { correlationId }),
|
|
46
|
+
});
|
|
47
|
+
};
|
|
@@ -18,6 +18,12 @@ import { z } from 'zod';
|
|
|
18
18
|
* @property {string} datacontenttype - A MIME type that indicates the format that the data is in (optional).
|
|
19
19
|
* @property {string} dataschema - An absolute URL to the schema that the data adheres to (optional).
|
|
20
20
|
*
|
|
21
|
+
* Queries may include additional CloudEvents extension attributes such as
|
|
22
|
+
* `metadata` or `authcontext`. Define them on a query-specific schema via
|
|
23
|
+
* {@link querySchema.extend} or as an intersection type.
|
|
24
|
+
*
|
|
25
|
+
* @see https://github.com/cloudevents/spec/blob/main/cloudevents/spec.md#extension-context-attributes
|
|
26
|
+
*
|
|
21
27
|
* @template TData - The type of the data.
|
|
22
28
|
*
|
|
23
29
|
* @example
|
|
@@ -45,6 +51,10 @@ export type Query<TData = unknown> = {
|
|
|
45
51
|
datacontenttype?: string;
|
|
46
52
|
dataschema?: string;
|
|
47
53
|
};
|
|
54
|
+
/**
|
|
55
|
+
* Known query properties handled by {@link createQuery}.
|
|
56
|
+
*/
|
|
57
|
+
type QueryKnownProperty = 'specversion' | 'id' | 'correlationid' | 'time' | 'source' | 'type' | 'data' | 'datacontenttype' | 'dataschema';
|
|
48
58
|
/**
|
|
49
59
|
* Type alias for the query data field schema.
|
|
50
60
|
*/
|
|
@@ -85,7 +95,7 @@ export declare const querySchema: QuerySchemaType;
|
|
|
85
95
|
* the input is validated against that type. This means fields like
|
|
86
96
|
* `type` and `data` must match the narrower types of `TQuery`.
|
|
87
97
|
*/
|
|
88
|
-
export type CreateQueryInput<TQuery extends Query = Query> = Partial<Pick<TQuery, 'id' | 'correlationid' | 'time' | 'datacontenttype' | 'dataschema'>> & Pick<TQuery, 'type' | 'source' | 'data'
|
|
98
|
+
export type CreateQueryInput<TQuery extends Query = Query> = Partial<Pick<TQuery, 'id' | 'correlationid' | 'time' | 'datacontenttype' | 'dataschema'>> & Pick<TQuery, 'type' | 'source' | 'data'> & Partial<Omit<TQuery, QueryKnownProperty>>;
|
|
89
99
|
/**
|
|
90
100
|
* Creates a query based on input data with the convenience
|
|
91
101
|
* to skip properties and use the defaults for the rest.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../../src/lib/message/query.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../../src/lib/message/query.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,MAAM,MAAM,KAAK,CAAC,KAAK,GAAG,OAAO,IAAI;IACjC,WAAW,EAAE,KAAK,CAAC;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,aAAa,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,KAAK,CAAC;IACZ,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF;;GAEG;AACH,KAAK,kBAAkB,GACjB,aAAa,GACb,IAAI,GACJ,eAAe,GACf,MAAM,GACN,QAAQ,GACR,MAAM,GACN,MAAM,GACN,iBAAiB,GACjB,YAAY,CAAC;AAEnB;;GAEG;AACH,KAAK,eAAe,GAAG,CAAC,CAAC,QAAQ,CAC7B;IACI,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,UAAU,CAAC;IACtC,CAAC,CAAC,SAAS;IACX,CAAC,CAAC,SAAS;IACX,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC;IACxB,CAAC,CAAC,UAAU;CACf,CACJ,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,SAAS,CAAC;IACtC,WAAW,EAAE,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;IACjC,EAAE,EAAE,CAAC,CAAC,SAAS,CAAC;IAChB,aAAa,EAAE,CAAC,CAAC,SAAS,CAAC;IAC3B,IAAI,EAAE,CAAC,CAAC,cAAc,CAAC;IACvB,MAAM,EAAE,CAAC,CAAC,SAAS,CAAC;IACpB,IAAI,EAAE,CAAC,CAAC,SAAS,CAAC;IAClB,IAAI,EAAE,eAAe,CAAC;IACtB,eAAe,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IAC5C,UAAU,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;CACvC,CAAC,CAAC;AAEH;;;;;;;GAOG;AACH,eAAO,MAAM,WAAW,EAAE,eAgBL,CAAC;AAEtB;;;;;;GAMG;AACH,MAAM,MAAM,gBAAgB,CAAC,MAAM,SAAS,KAAK,GAAG,KAAK,IACnD,OAAO,CACL,IAAI,CACA,MAAM,EACN,IAAI,GAAG,eAAe,GAAG,MAAM,GAAG,iBAAiB,GAAG,YAAY,CACrE,CACJ,GACC,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,QAAQ,GAAG,MAAM,CAAC,GACxC,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC,CAAC;AAEhD;;;GAGG;AACH,eAAO,MAAM,WAAW,GAAI,MAAM,SAAS,KAAK,EAC5C,OAAO,gBAAgB,CAAC,MAAM,CAAC,KAChC,MAqCF,CAAC"}
|
package/esm/lib/message/query.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ulid } from '../../deps/jsr.io/@std/ulid/1.0.0/mod.js';
|
|
2
2
|
import { z } from 'zod';
|
|
3
|
+
import { warnOnInvalidExtensionAttributeNames } from './message.js';
|
|
3
4
|
/**
|
|
4
5
|
* The Zod schema matching the Query type.
|
|
5
6
|
*
|
|
@@ -8,7 +9,7 @@ import { z } from 'zod';
|
|
|
8
9
|
* We do not infer the Query type from this schema because of
|
|
9
10
|
* slow type issues see https://jsr.io/docs/about-slow-types for more details.
|
|
10
11
|
*/
|
|
11
|
-
export const querySchema = z.
|
|
12
|
+
export const querySchema = z.looseObject({
|
|
12
13
|
specversion: z.literal('1.0'),
|
|
13
14
|
id: z.string(),
|
|
14
15
|
correlationid: z.string(),
|
|
@@ -30,16 +31,22 @@ export const querySchema = z.object({
|
|
|
30
31
|
* to skip properties and use the defaults for the rest.
|
|
31
32
|
*/
|
|
32
33
|
export const createQuery = (input) => {
|
|
34
|
+
const { id, correlationid, time, source, type, data, datacontenttype, dataschema, ...extensions } = input;
|
|
35
|
+
const correlationIdWithFallback = correlationid ?? ulid();
|
|
36
|
+
if (Object.keys(extensions).length > 0) {
|
|
37
|
+
warnOnInvalidExtensionAttributeNames(extensions, correlationIdWithFallback, createQuery);
|
|
38
|
+
}
|
|
33
39
|
const query = {
|
|
34
40
|
specversion: '1.0',
|
|
35
|
-
id:
|
|
36
|
-
correlationid:
|
|
37
|
-
time:
|
|
38
|
-
source
|
|
39
|
-
type
|
|
40
|
-
data
|
|
41
|
-
datacontenttype:
|
|
42
|
-
...(
|
|
41
|
+
id: id ?? ulid(),
|
|
42
|
+
correlationid: correlationIdWithFallback,
|
|
43
|
+
time: time ?? new Date().toISOString(),
|
|
44
|
+
source,
|
|
45
|
+
type,
|
|
46
|
+
data,
|
|
47
|
+
datacontenttype: datacontenttype ?? 'application/json',
|
|
48
|
+
...(dataschema && { dataschema }),
|
|
49
|
+
...extensions,
|
|
43
50
|
};
|
|
44
51
|
return query;
|
|
45
52
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nimbus-cqrs/core",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.0",
|
|
4
4
|
"description": "Simplify Event-Driven Applications - Core building blocks of the Nimbus framework.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"nimbus",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"@opentelemetry/api": "^1.9.1",
|
|
37
|
-
"zod": "^4.3
|
|
37
|
+
"zod": "^4.4.3"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@types/node": "^22.0.0"
|