@aventara/nest 1.0.0-rc.10 → 1.0.0-rc.11
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/CHANGELOG.md +27 -0
- package/README.md +2 -2
- package/dist/express-protocol.mounter.js +6 -5
- package/dist/fastify-protocol.mounter.js +7 -6
- package/dist/node-exchange.translator.d.ts +29 -5
- package/dist/node-exchange.translator.js +82 -3
- package/dist/protocol-route.table.d.ts +5 -1
- package/dist/protocol-route.table.js +3 -0
- package/package.json +6 -6
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,32 @@
|
|
|
1
1
|
# @aventara/nest
|
|
2
2
|
|
|
3
|
+
## 1.0.0-rc.11
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- e0e89c1: `POST {api}/_all` now streams when the client asks for it: the hosts forward `Accept`, so with
|
|
8
|
+
`application/x-ndjson` each entry's line is written as it settles (Nest on Express and Fastify writes it to the response,
|
|
9
|
+
flushed through `compression` when present; Next returns a `ReadableStream`), and plain JSON stays the answer otherwise.
|
|
10
|
+
When the client disconnects, the set stops: entries not yet started never start.
|
|
11
|
+
- 186bc29: `POST {api}/_all` is mounted with the other protocol routes and answered by the binding's `handleAll`.
|
|
12
|
+
- 33b5f83: The hosts hand the request URL's query to the protocol, so a cached read's `GET` (a read with a `cache({ for, maxAge })` stage)
|
|
13
|
+
is mounted and answered like every other route in `protocol.surface()`, on Express, Fastify and Next.js.
|
|
14
|
+
- bedab57: A cached read's `Vary` joins the `Vary` the platform already set instead of replacing it. With `enableCors()` on, a
|
|
15
|
+
`for: "anonymous"` or `"user"` answer carries `Vary: Origin, Authorization, Cookie` on Express and Fastify, where it
|
|
16
|
+
carried only `Vary: Authorization, Cookie` and dropped CORS's `Vary: Origin`, so a CDN could serve one origin's
|
|
17
|
+
`Access-Control-Allow-Origin` to another. Each name appears once, compared without case, the platform's first.
|
|
18
|
+
- Updated dependencies [6197c08]
|
|
19
|
+
- Updated dependencies [e0e89c1]
|
|
20
|
+
- Updated dependencies [186bc29]
|
|
21
|
+
- Updated dependencies [33b5f83]
|
|
22
|
+
- Updated dependencies [6d8b589]
|
|
23
|
+
- Updated dependencies [11ece49]
|
|
24
|
+
- Updated dependencies [92fd093]
|
|
25
|
+
- Updated dependencies [e5e98e6]
|
|
26
|
+
- Updated dependencies [a05d970]
|
|
27
|
+
- @aventara/core@1.0.0-rc.11
|
|
28
|
+
- @aventara/mcp@1.0.0-rc.11
|
|
29
|
+
|
|
3
30
|
## 1.0.0-rc.10
|
|
4
31
|
|
|
5
32
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -140,7 +140,7 @@ rest of `<api>/_*`. Nest's `RouterExplorer` does not list platform routes, so th
|
|
|
140
140
|
own when it mounts them, through Nest's `Logger` (context `AventaraModule`; `logger: false` silences it like any other):
|
|
141
141
|
|
|
142
142
|
```text
|
|
143
|
-
[Nest] LOG [AventaraModule] Aventara mounted 10 operations at /api (+ GET /api/_contract, POST /api/_transactions)
|
|
143
|
+
[Nest] LOG [AventaraModule] Aventara mounted 10 operations at /api (+ GET /api/_contract, POST /api/_transactions, POST /api/_all)
|
|
144
144
|
```
|
|
145
145
|
|
|
146
146
|
An internal failure (`A3000`–`A3004`, answered as a 500) is logged as one error line through Nest's `Logger`
|
|
@@ -245,7 +245,7 @@ It is an optional peer dependency: an application without `mcp` does not need it
|
|
|
245
245
|
package refuses to start, naming it and the command, with the version filled in:
|
|
246
246
|
|
|
247
247
|
```text
|
|
248
|
-
AventaraModule: the configuration has `mcp`, and the package that serves it, @aventara/mcp, is not installed. Install it at @aventara/core's exact version (npm install --save-exact @aventara/mcp@1.0.0-rc.
|
|
248
|
+
AventaraModule: the configuration has `mcp`, and the package that serves it, @aventara/mcp, is not installed. Install it at @aventara/core's exact version (npm install --save-exact @aventara/mcp@1.0.0-rc.11), or remove `mcp` from the configuration.
|
|
249
249
|
```
|
|
250
250
|
As for the protocol's routes, the module only mounts: the endpoint's body is read
|
|
251
251
|
raw, the request's URL comes from the platform's `protocol` and `host` (set `trust proxy` on Express or `trustProxy` on
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { mcpRequest, NO_BYTES, pathnameOf, protocolRequest, writeAnswer, } from "./node-exchange.translator.js";
|
|
1
|
+
import { disconnectOf, mcpRequest, NO_BYTES, pathnameOf, protocolRequest, writeAnswer, } from "./node-exchange.translator.js";
|
|
2
2
|
import { MCP_ROUTES, PROTOCOL_ROUTES, } from "./protocol-route.table.js";
|
|
3
3
|
import { readRequestBody, unreadBodyAnswer, } from "./request-body.reader.js";
|
|
4
4
|
const REGISTER = { GET: "get", POST: "post", DELETE: "delete" };
|
|
@@ -27,7 +27,7 @@ export function createExpressProtocolHost(platform, binding, entrypoint, maxRequ
|
|
|
27
27
|
for (const method of route.methods) {
|
|
28
28
|
platform[REGISTER[method]](literalPath(route.path), exactly(route.path, async (request, response) => {
|
|
29
29
|
const body = bodyOf(request);
|
|
30
|
-
writeAnswer(response, await answer(mcpRequest(request.method, request, request.originalUrl, request, body.kind === "read" ? body.content : NO_BYTES, request.socket.remoteAddress), state === undefined ? undefined : () => state(request)));
|
|
30
|
+
await writeAnswer(response, await answer(mcpRequest(request.method, request, request.originalUrl, request, body.kind === "read" ? body.content : NO_BYTES, request.socket.remoteAddress), state === undefined ? undefined : () => state(request)));
|
|
31
31
|
}));
|
|
32
32
|
}
|
|
33
33
|
}
|
|
@@ -35,8 +35,9 @@ export function createExpressProtocolHost(platform, binding, entrypoint, maxRequ
|
|
|
35
35
|
const answer = PROTOCOL_ROUTES[route.kind](binding);
|
|
36
36
|
platform[REGISTER[route.method]](literalPath(`${entrypoint}${route.path}`), async (request, response) => {
|
|
37
37
|
const body = bodyOf(request);
|
|
38
|
-
|
|
39
|
-
|
|
38
|
+
const disconnect = disconnectOf(response);
|
|
39
|
+
await writeAnswer(response, body.kind === "read"
|
|
40
|
+
? await answer(translated(request, entrypoint, body.content), state === undefined ? undefined : () => state(request), disconnect)
|
|
40
41
|
: unreadBodyAnswer(binding, body));
|
|
41
42
|
});
|
|
42
43
|
}
|
|
@@ -51,7 +52,7 @@ export function createExpressProtocolHost(platform, binding, entrypoint, maxRequ
|
|
|
51
52
|
handOn(next);
|
|
52
53
|
return;
|
|
53
54
|
}
|
|
54
|
-
writeAnswer(response, absent);
|
|
55
|
+
void writeAnswer(response, absent);
|
|
55
56
|
});
|
|
56
57
|
},
|
|
57
58
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { mcpRequest, NO_BYTES, pathnameOf, protocolRequest, writeAnswer, } from "./node-exchange.translator.js";
|
|
1
|
+
import { disconnectOf, mcpRequest, NO_BYTES, pathnameOf, protocolRequest, writeAnswer, } from "./node-exchange.translator.js";
|
|
2
2
|
import { MCP_ROUTES, PROTOCOL_ROUTES } from "./protocol-route.table.js";
|
|
3
3
|
import { readRequestBody, unreadBodyAnswer } from "./request-body.reader.js";
|
|
4
4
|
const UNMATCHABLE = /\*|%(?:3A|2B|23|24|26|2C|2F|3B|3D|3F|40)/i;
|
|
@@ -37,7 +37,7 @@ export function createFastifyProtocolHost(platform, binding, entrypoint, maxRequ
|
|
|
37
37
|
exposeHeadRoute: false,
|
|
38
38
|
onRequest: async (request, reply) => {
|
|
39
39
|
const body = await readRequestBody(request.raw, undefined, mcp.maxRequestBytes);
|
|
40
|
-
write(reply, await answer(mcpRequest(request.raw.method, request, request.raw.url, request.raw, body.kind === "read" ? body.content : NO_BYTES, request.raw.socket.remoteAddress), state === undefined ? undefined : () => state(request)));
|
|
40
|
+
await write(reply, await answer(mcpRequest(request.raw.method, request, request.raw.url, request.raw, body.kind === "read" ? body.content : NO_BYTES, request.raw.socket.remoteAddress), state === undefined ? undefined : () => state(request)));
|
|
41
41
|
return reply;
|
|
42
42
|
},
|
|
43
43
|
handler: () => {
|
|
@@ -53,8 +53,9 @@ export function createFastifyProtocolHost(platform, binding, entrypoint, maxRequ
|
|
|
53
53
|
exposeHeadRoute: false,
|
|
54
54
|
onRequest: async (request, reply) => {
|
|
55
55
|
const body = await readRequestBody(request.raw, request.raw.headersDistinct["content-encoding"], maxRequestBytes);
|
|
56
|
-
|
|
57
|
-
|
|
56
|
+
const disconnect = disconnectOf(reply.raw);
|
|
57
|
+
await write(reply, body.kind === "read"
|
|
58
|
+
? await answer(translated(request, body.content), state === undefined ? undefined : () => state(request), disconnect)
|
|
58
59
|
: unreadBodyAnswer(binding, body));
|
|
59
60
|
return reply;
|
|
60
61
|
},
|
|
@@ -72,7 +73,7 @@ export function createFastifyProtocolHost(platform, binding, entrypoint, maxRequ
|
|
|
72
73
|
if (absent === undefined) {
|
|
73
74
|
return undefined;
|
|
74
75
|
}
|
|
75
|
-
write(reply, absent);
|
|
76
|
+
await write(reply, absent);
|
|
76
77
|
return reply;
|
|
77
78
|
});
|
|
78
79
|
},
|
|
@@ -83,5 +84,5 @@ function literalPath(path) {
|
|
|
83
84
|
}
|
|
84
85
|
function write(reply, answer) {
|
|
85
86
|
reply.hijack();
|
|
86
|
-
writeAnswer(reply.raw, answer, reply.getHeaders());
|
|
87
|
+
return writeAnswer(reply.raw, answer, reply.getHeaders());
|
|
87
88
|
}
|
|
@@ -1,11 +1,28 @@
|
|
|
1
|
-
import type { AvProtocolRequest
|
|
1
|
+
import type { AvProtocolRequest } from "@aventara/core/protocol";
|
|
2
2
|
import type { McpRequest } from "./mcp-binding.loader.js";
|
|
3
|
+
import type { RouteResponse } from "./protocol-route.table.js";
|
|
3
4
|
export type NodeIncoming = AsyncIterable<Uint8Array> & {
|
|
4
5
|
readonly headersDistinct: Readonly<Record<string, readonly string[]>>;
|
|
5
6
|
};
|
|
6
7
|
export type NodeOutgoing = {
|
|
7
8
|
writeHead(status: number, headers: Readonly<Record<string, string | number | readonly string[]>>): unknown;
|
|
8
|
-
end(body
|
|
9
|
+
end(body?: string): unknown;
|
|
10
|
+
/** A header already set on the response (Express's middleware sets its own here). */
|
|
11
|
+
getHeader(name: string): string | number | readonly string[] | undefined;
|
|
12
|
+
/** `false` when the socket's buffer is full: wait for `drain`. */
|
|
13
|
+
write(chunk: string): boolean;
|
|
14
|
+
once(event: "close" | "drain", listener: () => void): unknown;
|
|
15
|
+
removeListener(event: "close" | "drain", listener: () => void): unknown;
|
|
16
|
+
destroy(): unknown;
|
|
17
|
+
/** Sends the status line and headers now, before any body is written. */
|
|
18
|
+
flushHeaders(): void;
|
|
19
|
+
/** Whether the whole answer was handed to the socket. */
|
|
20
|
+
readonly writableFinished: boolean;
|
|
21
|
+
/** Whether the response was ended or the socket went away. */
|
|
22
|
+
readonly writableEnded: boolean;
|
|
23
|
+
readonly destroyed: boolean;
|
|
24
|
+
/** The `compression` middleware's: sends what it has compressed so far. */
|
|
25
|
+
flush?(): void;
|
|
9
26
|
};
|
|
10
27
|
/** Headers a platform's own hooks set on the reply before the protocol answered. */
|
|
11
28
|
export type PlatformHeaders = Readonly<Record<string, string | number | readonly string[] | undefined>>;
|
|
@@ -13,16 +30,23 @@ export type PlatformHeaders = Readonly<Record<string, string | number | readonly
|
|
|
13
30
|
export declare const NO_BYTES: Uint8Array<ArrayBuffer>;
|
|
14
31
|
/** A request URL's raw pathname: the query is dropped and nothing is URL-decoded. */
|
|
15
32
|
export declare function pathnameOf(url: string): string;
|
|
16
|
-
/** The request as the protocol reads it: path relative to the entrypoint, distinct headers, raw body. */
|
|
33
|
+
/** The request as the protocol reads it: path relative to the entrypoint, raw query, distinct headers, raw body. */
|
|
17
34
|
export declare function protocolRequest(method: string, url: string, incoming: NodeIncoming, entrypoint: string, content: Uint8Array): AvProtocolRequest;
|
|
18
35
|
/** The request as `@aventara/mcp` reads it: absolute URL, distinct headers, raw body, peer address. */
|
|
19
36
|
export declare function mcpRequest(method: string, origin: {
|
|
20
37
|
readonly protocol: string;
|
|
21
38
|
readonly host: string;
|
|
22
39
|
}, url: string, incoming: NodeIncoming, content: Uint8Array, remoteAddress: string | undefined): McpRequest;
|
|
40
|
+
/** Aborted when the client goes away before the answer was written. */
|
|
41
|
+
export declare function disconnectOf(response: NodeOutgoing): AbortSignal;
|
|
23
42
|
/**
|
|
24
43
|
* Writes the protocol's answer as it is. Headers the platform's hooks already
|
|
25
44
|
* set (CORS, say) go beneath it; a protocol header of the same name, in any
|
|
26
|
-
* case, wins
|
|
45
|
+
* case, wins, except `Vary`: the protocol's names join the platform's
|
|
46
|
+
* (`mergedVary`), which Express holds on the response and Fastify hands in
|
|
47
|
+
* `beneath`. A streamed body (`/_all` under NDJSON) is piped: each line
|
|
48
|
+
* written as core yields it, and flushed through `compression` when that
|
|
49
|
+
* middleware wraps the response. Writing stops when the client goes away,
|
|
50
|
+
* and the lines are no longer pulled (`return()`).
|
|
27
51
|
*/
|
|
28
|
-
export declare function writeAnswer(response: NodeOutgoing, answer:
|
|
52
|
+
export declare function writeAnswer(response: NodeOutgoing, answer: RouteResponse, beneath?: PlatformHeaders): Promise<void>;
|
|
@@ -3,10 +3,15 @@ export function pathnameOf(url) {
|
|
|
3
3
|
const query = url.indexOf("?");
|
|
4
4
|
return query === -1 ? url : url.slice(0, query);
|
|
5
5
|
}
|
|
6
|
+
function queryOf(url) {
|
|
7
|
+
const query = url.indexOf("?");
|
|
8
|
+
return query === -1 ? "" : url.slice(query + 1);
|
|
9
|
+
}
|
|
6
10
|
export function protocolRequest(method, url, incoming, entrypoint, content) {
|
|
7
11
|
return {
|
|
8
12
|
method,
|
|
9
13
|
path: pathnameOf(url).slice(entrypoint.length),
|
|
14
|
+
query: queryOf(url),
|
|
10
15
|
headers: incoming.headersDistinct,
|
|
11
16
|
body: { kind: "raw", content },
|
|
12
17
|
};
|
|
@@ -20,7 +25,35 @@ export function mcpRequest(method, origin, url, incoming, content, remoteAddress
|
|
|
20
25
|
remoteAddress,
|
|
21
26
|
};
|
|
22
27
|
}
|
|
23
|
-
export function
|
|
28
|
+
export function disconnectOf(response) {
|
|
29
|
+
const disconnect = new AbortController();
|
|
30
|
+
response.once("close", () => {
|
|
31
|
+
if (!response.writableFinished) {
|
|
32
|
+
disconnect.abort();
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
return disconnect.signal;
|
|
36
|
+
}
|
|
37
|
+
function textOf(value) {
|
|
38
|
+
return value === undefined
|
|
39
|
+
? ""
|
|
40
|
+
: typeof value === "object"
|
|
41
|
+
? value.join(", ")
|
|
42
|
+
: String(value);
|
|
43
|
+
}
|
|
44
|
+
function mergedVary(lists) {
|
|
45
|
+
const names = new Map();
|
|
46
|
+
for (const list of lists) {
|
|
47
|
+
for (const name of list.split(",")) {
|
|
48
|
+
const trimmed = name.trim();
|
|
49
|
+
if (trimmed !== "" && !names.has(trimmed.toLowerCase())) {
|
|
50
|
+
names.set(trimmed.toLowerCase(), trimmed);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return names.has("*") ? "*" : [...names.values()].join(", ");
|
|
55
|
+
}
|
|
56
|
+
export async function writeAnswer(response, answer, beneath = {}) {
|
|
24
57
|
const own = new Set(Object.keys(answer.headers).map((name) => name.toLowerCase()));
|
|
25
58
|
const headers = {};
|
|
26
59
|
for (const [name, value] of Object.entries(beneath)) {
|
|
@@ -28,6 +61,52 @@ export function writeAnswer(response, answer, beneath = {}) {
|
|
|
28
61
|
headers[name] = value;
|
|
29
62
|
}
|
|
30
63
|
}
|
|
31
|
-
|
|
32
|
-
|
|
64
|
+
const written = {
|
|
65
|
+
...headers,
|
|
66
|
+
...answer.headers,
|
|
67
|
+
};
|
|
68
|
+
const vary = Object.keys(answer.headers).find((name) => name.toLowerCase() === "vary");
|
|
69
|
+
if (vary !== undefined) {
|
|
70
|
+
const platform = Object.entries(beneath).flatMap(([name, value]) => name.toLowerCase() === "vary" ? [textOf(value)] : []);
|
|
71
|
+
written[vary] = mergedVary([
|
|
72
|
+
textOf(response.getHeader("vary")),
|
|
73
|
+
...platform,
|
|
74
|
+
textOf(answer.headers[vary]),
|
|
75
|
+
]);
|
|
76
|
+
}
|
|
77
|
+
response.writeHead(answer.status, written);
|
|
78
|
+
if (typeof answer.body === "string") {
|
|
79
|
+
response.end(answer.body);
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
response.flushHeaders();
|
|
83
|
+
try {
|
|
84
|
+
for await (const line of answer.body) {
|
|
85
|
+
if (response.destroyed || response.writableEnded) {
|
|
86
|
+
break;
|
|
87
|
+
}
|
|
88
|
+
if (!response.write(line)) {
|
|
89
|
+
await drained(response);
|
|
90
|
+
}
|
|
91
|
+
response.flush?.();
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
response.destroy();
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
if (!response.destroyed) {
|
|
99
|
+
response.end();
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
function drained(response) {
|
|
103
|
+
return new Promise((resolve) => {
|
|
104
|
+
const done = () => {
|
|
105
|
+
response.removeListener("drain", done);
|
|
106
|
+
response.removeListener("close", done);
|
|
107
|
+
resolve();
|
|
108
|
+
};
|
|
109
|
+
response.once("drain", done);
|
|
110
|
+
response.once("close", done);
|
|
111
|
+
});
|
|
33
112
|
}
|
|
@@ -5,8 +5,12 @@ import type { McpBinding, McpRequest, McpRoute } from "./mcp-binding.loader.js";
|
|
|
5
5
|
export type SurfaceRoute = ReturnType<AvProtocolBinding["surface"]>[number];
|
|
6
6
|
/** The developer's `state` option over one platform request: seeds its `ctx.$state`. */
|
|
7
7
|
type StateSeed = () => AvState | Promise<AvState>;
|
|
8
|
+
/** An answer a route writes: the protocol's, its body text or, for a streamed `/_all`, lines as they settle. */
|
|
9
|
+
export type RouteResponse = Awaited<ReturnType<AvProtocolBinding["handleAll"]>>;
|
|
8
10
|
/** What a mounted route answers its request with: a bound protocol member. */
|
|
9
|
-
export type RouteAnswer = (request: AvProtocolRequest, state: StateSeed | undefined
|
|
11
|
+
export type RouteAnswer = (request: AvProtocolRequest, state: StateSeed | undefined,
|
|
12
|
+
/** Aborted when the client goes away; only `/_all` reads it. */
|
|
13
|
+
disconnect: AbortSignal) => RouteResponse | Promise<RouteResponse>;
|
|
10
14
|
/** The bound member each kind of surface route is answered by. */
|
|
11
15
|
export type ProtocolRouteTable = {
|
|
12
16
|
readonly [K in SurfaceRoute["kind"]]: (binding: AvProtocolBinding) => RouteAnswer;
|
|
@@ -3,6 +3,9 @@ export const PROTOCOL_ROUTES = {
|
|
|
3
3
|
contract: (binding) => (request) => binding.encodeContract(request),
|
|
4
4
|
transactions: (binding) => (request, state) => binding.handleTransaction(request, state === undefined ? {} : { state }),
|
|
5
5
|
can: (binding) => (request, state) => binding.handleCan(request, state === undefined ? {} : { state }),
|
|
6
|
+
all: (binding) => (request, state, disconnect) => binding.handleAll(request, state === undefined
|
|
7
|
+
? { signal: disconnect }
|
|
8
|
+
: { state, signal: disconnect }),
|
|
6
9
|
};
|
|
7
10
|
export const MCP_ROUTES = {
|
|
8
11
|
endpoint: (binding) => (request, state) => binding.handleEndpoint(request, state === undefined ? {} : { state }),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aventara/nest",
|
|
3
|
-
"version": "1.0.0-rc.
|
|
3
|
+
"version": "1.0.0-rc.11",
|
|
4
4
|
"license": "SEE LICENSE IN LICENSE",
|
|
5
5
|
"description": "NestJS host integration for Aventara.",
|
|
6
6
|
"type": "module",
|
|
@@ -22,10 +22,10 @@
|
|
|
22
22
|
"CHANGELOG.md"
|
|
23
23
|
],
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@aventara/core": "1.0.0-rc.
|
|
25
|
+
"@aventara/core": "1.0.0-rc.11"
|
|
26
26
|
},
|
|
27
27
|
"peerDependencies": {
|
|
28
|
-
"@aventara/mcp": "1.0.0-rc.
|
|
28
|
+
"@aventara/mcp": "1.0.0-rc.11",
|
|
29
29
|
"@nestjs/common": "^12.0.0",
|
|
30
30
|
"@nestjs/core": "^12.0.0"
|
|
31
31
|
},
|
|
@@ -50,9 +50,9 @@
|
|
|
50
50
|
"access": "public"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
|
-
"@aventara/mcp": "1.0.0-rc.
|
|
54
|
-
"@aventara/prisma7-adapter": "1.0.0-rc.
|
|
55
|
-
"@aventara/testing": "1.0.0-rc.
|
|
53
|
+
"@aventara/mcp": "1.0.0-rc.11",
|
|
54
|
+
"@aventara/prisma7-adapter": "1.0.0-rc.11",
|
|
55
|
+
"@aventara/testing": "1.0.0-rc.11",
|
|
56
56
|
"@modelcontextprotocol/sdk": "1.32.2",
|
|
57
57
|
"@nestjs/common": "^12.2.0",
|
|
58
58
|
"@nestjs/core": "^12.2.0",
|