@silkweave/nestjs 1.10.0 → 1.11.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/.turbo/turbo-build.log +6 -6
- package/README.md +10 -5
- package/build/index.d.mts +11 -5
- package/build/index.d.mts.map +1 -1
- package/build/index.mjs +20 -8
- package/build/index.mjs.map +1 -1
- package/package.json +7 -7
- package/src/lib/discovery.ts +13 -5
- package/src/lib/guards.ts +9 -3
- package/tsconfig.tsbuildinfo +1 -1
package/.turbo/turbo-build.log
CHANGED
|
@@ -9,9 +9,9 @@ $ tsdown
|
|
|
9
9
|
See more at [4mhttps://tsdown.dev/options/dependencies#deps-onlybundle[24m
|
|
10
10
|
Detected dependencies in bundle:
|
|
11
11
|
- [34mrxjs[39m
|
|
12
|
-
[34mℹ[39m [2mbuild/[22m[1mindex.mjs[22m [
|
|
13
|
-
[34mℹ[39m [2mbuild/[22mindex.mjs.map [
|
|
14
|
-
[34mℹ[39m [2mbuild/[22mindex.d.mts.map [2m 2.
|
|
15
|
-
[34mℹ[39m [2mbuild/[22m[32m[1mindex.d.mts[22m[39m [2m
|
|
16
|
-
[34mℹ[39m 4 files, total:
|
|
17
|
-
[32m✔[39m Build complete in [
|
|
12
|
+
[34mℹ[39m [2mbuild/[22m[1mindex.mjs[22m [2m338.49 kB[22m [2m│ gzip: 49.77 kB[22m
|
|
13
|
+
[34mℹ[39m [2mbuild/[22mindex.mjs.map [2m577.61 kB[22m [2m│ gzip: 87.77 kB[22m
|
|
14
|
+
[34mℹ[39m [2mbuild/[22mindex.d.mts.map [2m 2.99 kB[22m [2m│ gzip: 1.07 kB[22m
|
|
15
|
+
[34mℹ[39m [2mbuild/[22m[32m[1mindex.d.mts[22m[39m [2m 16.35 kB[22m [2m│ gzip: 5.75 kB[22m
|
|
16
|
+
[34mℹ[39m 4 files, total: 935.45 kB
|
|
17
|
+
[32m✔[39m Build complete in [32m742ms[39m
|
package/README.md
CHANGED
|
@@ -47,11 +47,10 @@ export class UserActions {
|
|
|
47
47
|
return this.db.getUser(input.id)
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
@UseGuards(AdminGuard)
|
|
50
|
+
@UseGuards(AdminGuard) // guard reads the request header on every transport, MCP included
|
|
51
51
|
@Action({
|
|
52
52
|
description: 'Ban a user',
|
|
53
|
-
input: BanInput
|
|
54
|
-
transports: ['rest', 'trpc'] // exclude from MCP tools
|
|
53
|
+
input: BanInput
|
|
55
54
|
})
|
|
56
55
|
ban(input: z.infer<typeof BanInput>) {
|
|
57
56
|
return this.db.banUser(input.id, input.reason)
|
|
@@ -98,7 +97,7 @@ The `users.list` and `users.get` actions are now reachable via:
|
|
|
98
97
|
- **tRPC:** `client.usersList.query({ activeOnly: true })` and `client.usersGet.query({ id: '1' })`
|
|
99
98
|
- **MCP:** tools `UsersList` and `UsersGet`
|
|
100
99
|
|
|
101
|
-
`users.ban`
|
|
100
|
+
`users.ban` is guarded by `@UseGuards(AdminGuard)` on **every** transport - REST, tRPC, **and** MCP. The guard reads its credential from the request header (`switchToHttp().getRequest().headers`); over MCP the inbound tool-call headers are surfaced the same way (see [Guards & DI](#guards--di)).
|
|
102
101
|
|
|
103
102
|
## Decorators
|
|
104
103
|
|
|
@@ -191,7 +190,13 @@ Mounts the MCP Streamable HTTP transport directly at `basePath`, with sideload (
|
|
|
191
190
|
|
|
192
191
|
## Guards & DI
|
|
193
192
|
|
|
194
|
-
Native NestJS `@UseGuards()` and `@UseInterceptors()` on `@Action` methods run for every
|
|
193
|
+
Native NestJS `@UseGuards()` and `@UseInterceptors()` on `@Action` methods run for **every** transport - REST, tRPC, and MCP. Guards receive an `ExecutionContext` with the request in `switchToHttp().getRequest()`. The `Reflector` is also wired up so guards can read custom metadata.
|
|
194
|
+
|
|
195
|
+
**Headers over MCP.** REST and tRPC pass the raw HTTP request to the guard. For MCP (Streamable HTTP), the inbound tool-call request is surfaced as a stand-in `{ headers, url, params, query }` object built from the MCP SDK's `extra.requestInfo`, so a header-based guard - e.g. one reading `getRequest().headers['x-api-key']` - works unchanged. `ExecutionContext.getType()` is `'http'` whenever a request is available (and `'rpc'` for transports with none, e.g. MCP stdio). Caveats:
|
|
196
|
+
|
|
197
|
+
- Only **headers** (and the request `url`) cross the MCP boundary. There are no path `params` or `query` on an MCP tool call, so `getRequest().params` / `.query` are empty objects - guards relying on them degrade to "deny" rather than crash.
|
|
198
|
+
- A guard that denies (returns `false` or throws) produces a clean MCP tool error (`ForbiddenException`), not an HTTP 500.
|
|
199
|
+
- For OAuth 2.1 / bearer-token MCP auth, prefer `mcp({ auth })` and read the resolved identity from the silkweave context (`ctx.get('auth')`) inside the action; the header stand-in is for custom request-reading guards.
|
|
195
200
|
|
|
196
201
|
Action methods are normal Nest provider methods - inject services via the constructor as usual.
|
|
197
202
|
|
package/build/index.d.mts
CHANGED
|
@@ -264,9 +264,10 @@ declare class ActionDiscovery {
|
|
|
264
264
|
* a list of core `Action` objects ready to feed into `silkweave().actions()`.
|
|
265
265
|
*
|
|
266
266
|
* Action invocation is wrapped to (a) run `@UseGuards` guards declared on the
|
|
267
|
-
* method or its class against the incoming
|
|
268
|
-
* `ctx.get('request')
|
|
269
|
-
*
|
|
267
|
+
* method or its class against the incoming request (read from
|
|
268
|
+
* `ctx.get('request')`, populated by REST/tRPC and by MCP-over-HTTP from the
|
|
269
|
+
* SDK's `extra.requestInfo`) and (b) bind `this` to the resolved Nest provider
|
|
270
|
+
* so DI-injected dependencies remain available.
|
|
270
271
|
*/
|
|
271
272
|
discover(): Action$1[];
|
|
272
273
|
private toAction;
|
|
@@ -294,14 +295,19 @@ type GuardRef = Type<CanActivate> | CanActivate;
|
|
|
294
295
|
*/
|
|
295
296
|
declare function collectGuards(reflector: Reflector, classRef: Type<unknown>, handler: (...args: unknown[]) => unknown): GuardRef[];
|
|
296
297
|
/**
|
|
297
|
-
* Run the configured guards against
|
|
298
|
+
* Run the configured guards against a request. Throws `ForbiddenException`
|
|
298
299
|
* if any guard rejects, mirroring Nest's HTTP request-pipeline behavior.
|
|
299
300
|
*
|
|
300
301
|
* Pass `null` for `response` when running on top of a tRPC or MCP request that
|
|
301
302
|
* doesn't surface a raw response object; guards that introspect the response
|
|
302
303
|
* will receive `null`.
|
|
304
|
+
*
|
|
305
|
+
* `contextType` is reflected through `ExecutionContext.getType()` so guards can
|
|
306
|
+
* branch on the transport. It is `'http'` for REST/tRPC and for MCP-over-HTTP
|
|
307
|
+
* (where a header-bearing request stand-in is available); transports without any
|
|
308
|
+
* HTTP request (e.g. MCP stdio) pass `'rpc'`.
|
|
303
309
|
*/
|
|
304
|
-
declare function runGuards(guards: GuardRef[], moduleRef: ModuleRef, reflector: Reflector, classRef: Type<unknown>, handler: (...args: unknown[]) => unknown, request: unknown, response: unknown): Promise<void>;
|
|
310
|
+
declare function runGuards(guards: GuardRef[], moduleRef: ModuleRef, reflector: Reflector, classRef: Type<unknown>, handler: (...args: unknown[]) => unknown, request: unknown, response: unknown, contextType?: 'http' | 'rpc'): Promise<void>;
|
|
305
311
|
//#endregion
|
|
306
312
|
//#region src/lib/silkweave.module.d.ts
|
|
307
313
|
/**
|
package/build/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/lib/types.ts","../src/adapter/mcp.ts","../src/adapter/rest.ts","../src/adapter/trpc.ts","../src/adapter/typegen.ts","../src/lib/metadata.ts","../src/decorator/action.ts","../src/decorator/actions.ts","../src/lib/discovery.ts","../src/lib/filter.ts","../src/lib/guards.ts","../src/lib/silkweave.module.ts"],"mappings":";;;;;;;;;;;;;;;;;UAUiB,0BAAA;EAAA;EAEf,WAAA,EAAa,WAAA,CAAY,eAAA;;EAEzB,gBAAA,EAAkB,gBAAA;EAFL;EAIb,WAAA,EAAa,gBAAA;EAAA;EAEb,OAAA,EAAS,QAAA;AAAA;;;;;;;;UAUM,oBAAA;EAVf;EAAA,SAYS,IAAA;EAZM;;AAUjB;;;;EAViB,SAmBN,UAAA;EAAA;EAET,QAAA,CAAS,GAAA,EAAK,0BAAA;AAAA;AAAA,UAGC,sBAAA;EAHyB;EAKxC,SAAA,EAAW,gBAAA;EAFI;EAIf,QAAA,EAAU,oBAAA;;EAEV,OAAA,GAAU,MAAA;AAAA;AAAA,cAGC,wBAAA;;;UCtCI,iBAAA;;EAEf,QAAA;;EAEA,IAAA,GAAO,UAAA;;EAEP,IAAA,GAAO,WAAA;EDTQ;ECWf,iBAAA;;EAEA,WAAA;AAAA;;;;;;;;;;;;;;;iBA6Bc,GAAA,CAAI,OAAA,GAAS,iBAAA,GAAyB,oBAAA;;;UChCrC,kBAAA;;EAEf,QAAA;;EAEA,IAAA,GAAO,UAAA;AAAA;;;AFdT;;;;;;;;;iBEwIgB,IAAA,CAAK,OAAA,GAAS,kBAAA,GAA0B,oBAAA;;;UC5IvC,kBAAA;;EAEf,QAAA;;EAEA,IAAA,GAAO,UAAA;AAAA;;;AHAT;;;;;;;;;iBGcgB,IAAA,CAAK,OAAA,GAAS,kBAAA,GAA0B,oBAAA;;;UCnBvC,qBAAA;;EAEf,IAAA;;;;;;AJGF;EIIE,MAAA,GAAS,aAAA;;;;;;EAMT,OAAA;AAAA;;;;;;;;;;iBAYc,OAAA,CAAQ,OAAA,EAAS,qBAAA,GAAwB,oBAAA;;;cC7B5C,eAAA;AAAA,cACA,gBAAA;AAAA,KAED,SAAA;AAAA,UAEK,cAAA;;EAEf,IAAA;;EAEA,WAAA;ELFe;EKIf,KAAA,EAAO,GAAA,CAAE,OAAA,CAAQ,CAAA;IAAO,KAAA,EAAO,MAAA,SAAe,GAAA,CAAE,UAAA;EAAA;ELFnC;EKIb,MAAA,GAAS,GAAA,CAAE,OAAA,CAAQ,CAAA;IAAO,KAAA,EAAO,MAAA,SAAe,GAAA,CAAE,UAAA;EAAA;ELEnC;;;;;;EKKf,KAAA,GAAQ,GAAA,CAAE,OAAA,CAAQ,CAAA;ELPlB;EKSA,IAAA,GAAO,UAAA;ELPP;EKSA,UAAA,GAAa,SAAA;ELTE;EKWf,SAAA,IAAa,OAAA,EAAS,gBAAA;ELDP;EKGf,UAAA,GAAa,QAAA,CAAO,CAAA,EAAG,CAAA;;EAEvB,IAAA,UAAc,CAAA;ELHL;EKKT,WAAA;AAAA;AAAA,UAGe,oBAAA;ELCN;EKCT,MAAA;ELDwC;EKGxC,UAAA,GAAa,SAAA;AAAA;AAAA,UAGE,gBAAA;EACf,UAAA,GAAa,QAAA,SAAe,CAAA;AAAA;AAAA,KAGlB,iBAAA,GAAoB,cAAA,mBAAiC,gBAAA;AAAA,cAEpD,mBAAA;;;;;;;;;;;;ALzCb;;;;;;;;;;;;;;;;;;;;;iBMuBgB,MAAA,mEAAA,CACd,OAAA,EAAS,cAAA,CAAe,CAAA,EAAG,CAAA,EAAG,CAAA,IAC7B,eAAA;;;;;;;;;;;;ANzBH;;;;;iBOOgB,OAAA,CAAQ,eAAA,YAA0B,oBAAA,GAA4B,cAAA;;;cCEjE,eAAA;EAAA,iBAEQ,SAAA;EAAA,iBACA,OAAA;EAAA,iBACA,SAAA;EAAA,iBACA,SAAA;cAHA,SAAA,EAAW,gBAAA,EACX,OAAA,EAAS,eAAA,EACT,SAAA,EAAW,SAAA,EACX,SAAA,EAAW,SAAA;;;ARdhC
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/lib/types.ts","../src/adapter/mcp.ts","../src/adapter/rest.ts","../src/adapter/trpc.ts","../src/adapter/typegen.ts","../src/lib/metadata.ts","../src/decorator/action.ts","../src/decorator/actions.ts","../src/lib/discovery.ts","../src/lib/filter.ts","../src/lib/guards.ts","../src/lib/silkweave.module.ts"],"mappings":"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"}
|
package/build/index.mjs
CHANGED
|
@@ -9035,16 +9035,21 @@ async function resolveGuard(ref, moduleRef) {
|
|
|
9035
9035
|
return ref;
|
|
9036
9036
|
}
|
|
9037
9037
|
/**
|
|
9038
|
-
* Run the configured guards against
|
|
9038
|
+
* Run the configured guards against a request. Throws `ForbiddenException`
|
|
9039
9039
|
* if any guard rejects, mirroring Nest's HTTP request-pipeline behavior.
|
|
9040
9040
|
*
|
|
9041
9041
|
* Pass `null` for `response` when running on top of a tRPC or MCP request that
|
|
9042
9042
|
* doesn't surface a raw response object; guards that introspect the response
|
|
9043
9043
|
* will receive `null`.
|
|
9044
|
+
*
|
|
9045
|
+
* `contextType` is reflected through `ExecutionContext.getType()` so guards can
|
|
9046
|
+
* branch on the transport. It is `'http'` for REST/tRPC and for MCP-over-HTTP
|
|
9047
|
+
* (where a header-bearing request stand-in is available); transports without any
|
|
9048
|
+
* HTTP request (e.g. MCP stdio) pass `'rpc'`.
|
|
9044
9049
|
*/
|
|
9045
|
-
async function runGuards(guards, moduleRef, reflector, classRef, handler, request, response) {
|
|
9050
|
+
async function runGuards(guards, moduleRef, reflector, classRef, handler, request, response, contextType = "http") {
|
|
9046
9051
|
if (guards.length === 0) return;
|
|
9047
|
-
const context = new SilkweaveExecutionContext([request, response], classRef, handler,
|
|
9052
|
+
const context = new SilkweaveExecutionContext([request, response], classRef, handler, contextType);
|
|
9048
9053
|
for (const ref of guards) {
|
|
9049
9054
|
const result = (await resolveGuard(ref, moduleRef)).canActivate(context);
|
|
9050
9055
|
if (!((0, import_cjs.isObservable)(result) ? await (0, import_cjs.lastValueFrom)(result) : await Promise.resolve(result))) throw new ForbiddenException("Forbidden resource");
|
|
@@ -9078,9 +9083,10 @@ let ActionDiscovery = class ActionDiscovery {
|
|
|
9078
9083
|
* a list of core `Action` objects ready to feed into `silkweave().actions()`.
|
|
9079
9084
|
*
|
|
9080
9085
|
* Action invocation is wrapped to (a) run `@UseGuards` guards declared on the
|
|
9081
|
-
* method or its class against the incoming
|
|
9082
|
-
* `ctx.get('request')
|
|
9083
|
-
*
|
|
9086
|
+
* method or its class against the incoming request (read from
|
|
9087
|
+
* `ctx.get('request')`, populated by REST/tRPC and by MCP-over-HTTP from the
|
|
9088
|
+
* SDK's `extra.requestInfo`) and (b) bind `this` to the resolved Nest provider
|
|
9089
|
+
* so DI-injected dependencies remain available.
|
|
9084
9090
|
*/
|
|
9085
9091
|
discover() {
|
|
9086
9092
|
const discovered = [];
|
|
@@ -9119,8 +9125,14 @@ let ActionDiscovery = class ActionDiscovery {
|
|
|
9119
9125
|
const applyGuards = async (context) => {
|
|
9120
9126
|
if (guards.length === 0) return;
|
|
9121
9127
|
const request = context.getOptional("request");
|
|
9122
|
-
const response = context.getOptional("response");
|
|
9123
|
-
|
|
9128
|
+
const response = context.getOptional("response") ?? null;
|
|
9129
|
+
const hasRequest = request != null;
|
|
9130
|
+
const guardRequest = hasRequest ? request : {
|
|
9131
|
+
headers: {},
|
|
9132
|
+
params: {},
|
|
9133
|
+
query: {}
|
|
9134
|
+
};
|
|
9135
|
+
await runGuards(guards, moduleRef, reflector, d.classRef, d.method, guardRequest, response, hasRequest ? "http" : "rpc");
|
|
9124
9136
|
};
|
|
9125
9137
|
if (d.method.constructor?.name === "AsyncGeneratorFunction") {
|
|
9126
9138
|
if (!d.meta.chunk) throw new Error(`@Action "${name}" is an async generator but has no \`chunk\` schema`);
|