@silkweave/nestjs 2.6.1 → 3.1.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 +3 -3
- package/build/{index-C1W-O7EX.d.mts → index-ByAnTJu5.d.mts} +15 -4
- package/build/index-ByAnTJu5.d.mts.map +1 -0
- package/build/index.d.mts.map +1 -1
- package/build/index.mjs +43 -20
- package/build/index.mjs.map +1 -1
- package/build/mcp.d.mts +1 -1
- package/build/mcp.mjs +0 -2
- package/build/mcp.mjs.map +1 -1
- package/build/trpc.d.mts +1 -1
- package/package.json +13 -11
- package/build/index-C1W-O7EX.d.mts.map +0 -1
package/README.md
CHANGED
|
@@ -333,9 +333,9 @@ A `@Get`/`@Post` is inherently a public REST route. To expose a method over **tR
|
|
|
333
333
|
|
|
334
334
|
Native NestJS `@UseGuards()` on `@Mcp`/`@Trpc` methods run before the handler is invoked. Guards receive an `ExecutionContext` with the request in `switchToHttp().getRequest()`, and the `Reflector` is wired up so guards can read custom metadata.
|
|
335
335
|
|
|
336
|
-
**Headers over MCP.** 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:
|
|
336
|
+
**Headers over MCP.** The inbound tool-call request is surfaced as a stand-in `{ headers, url, params, query, body }` 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:
|
|
337
337
|
|
|
338
|
-
- **Headers**, the request `url`, and **
|
|
338
|
+
- **Headers**, the request `url`, and the **validated tool input** cross the MCP boundary. Before guards run, the input is reconstructed into `getRequest().params`/`query`/`body` per each field's reflected source (path/`@Param` -> `params`, `@Query` -> `query`, `@Body` -> `body`; path and query stringified like Express delivers them, body kept as parsed values; only absent keys are filled). So a scope-enforcing guard reading `getRequest().params['id']`, `req.query['…']`, or `req.body['sessionId']` - e.g. one fencing a key to one resource/session - decides the same over MCP as over REST. The **request-fidelity contract**: whichever request slot a guard reads, it sees the value it would over HTTP.
|
|
339
339
|
- A guard that denies (returns `false` or throws) produces a clean MCP tool error (`ForbiddenException`), not an HTTP 500.
|
|
340
340
|
- For OAuth 2.1 / bearer-token MCP auth, prefer `mcp({ auth })` and read the resolved identity from the silkweave context (`ctx.get('auth')`); the header stand-in is for custom request-reading guards.
|
|
341
341
|
|
|
@@ -349,7 +349,7 @@ SilkweaveModule.forRoot({
|
|
|
349
349
|
})
|
|
350
350
|
```
|
|
351
351
|
|
|
352
|
-
The allow-list is explicit-by-class on purpose - a blanket "run every global" would also fire unrelated globals (e.g. a `ThrottlerGuard`, which assumes a writable response MCP doesn't provide). Listed guards run **before** the method/class `@UseGuards`, mirroring Nest's request pipeline. They see the same request stand-in as method guards: headers, `url`, and
|
|
352
|
+
The allow-list is explicit-by-class on purpose - a blanket "run every global" would also fire unrelated globals (e.g. a `ThrottlerGuard`, which assumes a writable response MCP doesn't provide). Listed guards run **before** the method/class `@UseGuards`, mirroring Nest's request pipeline. They see the same request stand-in as method guards: headers, `url`, and `params`/`query`/`body` reconstructed from the validated input; only IP-derived logic won't apply over MCP.
|
|
353
353
|
|
|
354
354
|
Controllers are normal Nest providers - inject services via the constructor as usual.
|
|
355
355
|
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { SilkweaveContext } from "@silkweave/core";
|
|
2
2
|
|
|
3
|
-
//#region ../auth/build/
|
|
4
|
-
//#endregion
|
|
3
|
+
//#region ../auth/build/types-BFhAEzlP.d.mts
|
|
5
4
|
//#region src/provider/types.d.ts
|
|
6
5
|
interface AuthInfo {
|
|
7
6
|
token: string;
|
|
@@ -37,10 +36,22 @@ interface AuthConfig {
|
|
|
37
36
|
resourceUrl?: string;
|
|
38
37
|
authorizationServers?: string[];
|
|
39
38
|
requiredScopes?: string[];
|
|
39
|
+
/**
|
|
40
|
+
* Expected token audience (RFC 8707 Resource Indicators / SEP-2352). When a
|
|
41
|
+
* verified token carries an `aud` claim, it must include one of these values -
|
|
42
|
+
* this is the resource-server confused-deputy defence (reject a token minted
|
|
43
|
+
* for a *different* resource). Defaults to `resourceUrl`; set `false` to skip.
|
|
44
|
+
*/
|
|
45
|
+
audience?: string | string[] | false;
|
|
46
|
+
/**
|
|
47
|
+
* Expected token issuer (RFC 9207 / SEP-2468). When set, a verified token whose
|
|
48
|
+
* `iss` claim differs is rejected, binding the credential to the issuing
|
|
49
|
+
* authorization server.
|
|
50
|
+
*/
|
|
51
|
+
issuer?: string;
|
|
40
52
|
provider?: OAuthProvider;
|
|
41
53
|
callbackPath?: string;
|
|
42
54
|
} //#endregion
|
|
43
|
-
//#region src/provider/store.d.ts
|
|
44
55
|
//#endregion
|
|
45
56
|
export { AuthConfig as t };
|
|
46
|
-
//# sourceMappingURL=index-
|
|
57
|
+
//# sourceMappingURL=index-ByAnTJu5.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-ByAnTJu5.d.mts","names":["SilkweaveContext","AuthInfo","token","clientId","scopes","expiresAt","key","OAuthRequest","URL","Record","method","url","headers","body","OAuthResponse","status","OAuthProvider","Promise","authorize","req","callback","register","metadata","verifyToken","VerifyToken","context","AuthConfig","required","resourceUrl","authorizationServers","requiredScopes","audience","issuer","provider","callbackPath","a","i","n","o","r","t"],"sources":["../../auth/build/types-BFhAEzlP.d.mts"],"mappings":";;;;UAGUC,QAAAA;EACRC,KAAAA;EACAC,QAAAA;EACAC,MAAAA;EACAC,SAAAA;EAAAA,CACCC,GAAAA;AAAAA;AAAAA,UAEOC,YAAAA;EACRG,MAAAA;EACAC,GAAAA,EAAKH,GAAAA;EACLI,OAAAA,EAASH,MAAAA;EACTI,IAAAA,GAAOJ,MAAAA;AAAAA;AAAAA,UAECK,aAAAA;EACRC,MAAAA;EACAH,OAAAA,EAASH,MAAAA;EACTI,IAAAA,YAAgBJ,MAAAA;AAAAA;AAAAA,UAERO,aAAAA;EACRE,SAAAA,CAAUC,GAAAA,EAAKZ,YAAAA,GAAeU,OAAAA,CAAQH,aAAAA;EACtCM,QAAAA,CAASD,GAAAA,EAAKZ,YAAAA,GAAeU,OAAAA,CAAQH,aAAAA;EACrCZ,KAAAA,CAAMiB,GAAAA,EAAKZ,YAAAA,GAAeU,OAAAA,CAAQH,aAAAA;EAClCO,QAAAA,CAASF,GAAAA,EAAKZ,YAAAA,GAAeU,OAAAA,CAAQH,aAAAA;EACrCQ,QAAAA,IAAYR,aAAAA;EACZS,WAAAA,CAAYrB,KAAAA,WAAgBe,OAAAA,CAAQhB,QAAAA;AAAAA;AAAAA;AAAAA,KAIjCuB,WAAAA,IAAetB,KAAAA,UAAeuB,OAAAA,EAASzB,gBAAAA,KAAqBiB,OAAAA,CAAQhB,QAAAA;AAAAA,UAC/DyB,UAAAA;EACRH,WAAAA,EAAaC,WAAAA;EACbG,QAAAA;EACAC,WAAAA;EACAC,oBAAAA;EACAC,cAAAA;EAlBAjB;;;;AAAsB;;EAyBtBkB,QAAAA;EAtBexB;;;;;EA4BfyB,MAAAA;EACAC,QAAAA,GAAWjB,aAAAA;EACXkB,YAAAA;AAAAA"}
|
package/build/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/lib/metadata.ts","../src/decorator/mcp.ts","../src/decorator/trpc.ts","../src/lib/controllerDiscovery.ts","../src/lib/guards.ts","../src/lib/rebind.ts","../src/lib/silkweave.module.ts"],"mappings":";;;;;;;;cAIa,YAAA;;cAGA,aAAA;;AAHb;;;;;AAGA;;UAUiB,WAAA;EAVS;;AAU1B;;EAKE,IAAA;EAgByB;;;;EAXzB,WAAA;EALA;;;;;;;;;;EAgBA,KAAA,GAAQ,MAAA,SAAe,CAAA,CAAE,OAAA,IAAW,CAAA,CAAE,SAAA;EAehC;AAIR;;;;;EAZE,KAAA;EAwB2B;;;;;;;EAhB3B,MAAA;AAAA;;KAIU,QAAA;;;;;;;;;;;UAYK,YAAA;EAyBf;;;;;EAnBA,IAAA;EAmB6C;;;;EAd7C,WAAA;EA6BA;;;;;;EAtBA,KAAA,GAAQ,MAAA,SAAe,CAAA,CAAE,OAAA,IAAW,CAAA,CAAE,SAAA;;ACnDxC;;;;;ED0DE,MAAA,GAAS,CAAA,CAAE,OAAA,GAAU,IAAA,GAAO,MAAA,SAAe,CAAA,CAAE,OAAA;EC1DC;;;;;;EDiE9C,KAAA,GAAQ,CAAA,CAAE,OAAA,GAAU,IAAA;EEjEF;;;;;;;EFyElB,IAAA,GAAO,QAAA;;;;
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/lib/metadata.ts","../src/decorator/mcp.ts","../src/decorator/trpc.ts","../src/lib/controllerDiscovery.ts","../src/lib/guards.ts","../src/lib/rebind.ts","../src/lib/silkweave.module.ts"],"mappings":";;;;;;;;cAIa,YAAA;;cAGA,aAAA;;AAHb;;;;;AAGA;;UAUiB,WAAA;EAVS;;AAU1B;;EAKE,IAAA;EAgByB;;;;EAXzB,WAAA;EALA;;;;;;;;;;EAgBA,KAAA,GAAQ,MAAA,SAAe,CAAA,CAAE,OAAA,IAAW,CAAA,CAAE,SAAA;EAehC;AAIR;;;;;EAZE,KAAA;EAwB2B;;;;;;;EAhB3B,MAAA;AAAA;;KAIU,QAAA;;;;;;;;;;;UAYK,YAAA;EAyBf;;;;;EAnBA,IAAA;EAmB6C;;;;EAd7C,WAAA;EA6BA;;;;;;EAtBA,KAAA,GAAQ,MAAA,SAAe,CAAA,CAAE,OAAA,IAAW,CAAA,CAAE,SAAA;;ACnDxC;;;;;ED0DE,MAAA,GAAS,CAAA,CAAE,OAAA,GAAU,IAAA,GAAO,MAAA,SAAe,CAAA,CAAE,OAAA;EC1DC;;;;;;EDiE9C,KAAA,GAAQ,CAAA,CAAE,OAAA,GAAU,IAAA;EEjEF;;;;;;;EFyElB,IAAA,GAAO,QAAA;;;;AG9DT;EHmEE,KAAA;AAAA;;;;;;;;;AA9GF;;;;;AAGA;;;;;AAUA;;;;;;;;;;;;;;;;;iBCmBgB,GAAA,CAAI,OAAA,GAAS,WAAA,GAAmB,eAAA;;;;;;;;;ADhChD;;;;;AAGA;;;;;AAUA;;;;;;;;;;;;;;;;;iBEmBgB,IAAA,CAAK,OAAA,GAAS,YAAA,GAAoB,eAAA;;;UCWjC,eAAA;EACf,OAAA,GAAU,eAAA;EACV,YAAA,GAAe,IAAA,CAAK,WAAA;EACpB,aAAA;AAAA;AAAA,cAIW,mBAAA;EAAA,iBAEQ,SAAA;EAAA,iBACA,OAAA;EAAA,iBACA,SAAA;EAAA,iBACA,SAAA;EAAA,iBACA,SAAA;cAJA,SAAA,EAAW,gBAAA,EACX,OAAA,EAAS,eAAA,EACT,SAAA,EAAW,SAAA,EACX,SAAA,EAAW,SAAA,EACX,SAAA,EAAW,iBAAA;EHrDN;AAU1B;;;;;;;;;EGwDE,QAAA,CAAS,OAAA,GAAS,eAAA,GAAuB,MAAA;EHnCzC;EAAA,QGiEQ,OAAA;EHjEe;EAAA,QGwFf,WAAA;EHxF4B;EAAA,QG2G5B,SAAA;EHpGR;EAAA,QGmIQ,UAAA;AAAA;;;KC1KL,QAAA,GAAW,IAAA,CAAK,WAAA,IAAe,WAAA;;;;;AJFpC;;;;;AAGA;;;;;AAUA;;iBIOgB,mBAAA,CACd,SAAA,EAAW,iBAAA,EACX,SAAA,EAAW,IAAA,CAAK,WAAA,MACf,WAAA;;;;;;iBAca,aAAA,CACd,SAAA,EAAW,SAAA,EACX,QAAA,EAAU,IAAA,WACV,OAAA,MAAa,IAAA,0BACZ,QAAA;;;;;;;;;;;;AJYH;;iBIkBsB,SAAA,CACpB,MAAA,EAAQ,QAAA,IACR,SAAA,EAAW,SAAA,EACX,SAAA,EAAW,SAAA,EACX,QAAA,EAAU,IAAA,WACV,OAAA,MAAa,IAAA,yBACb,OAAA,WACA,QAAA,WACA,WAAA,oBACC,OAAA;;;;;;;KC7ES,OAAA;EACN,IAAA;EAAe,KAAA;EAAe,MAAA;EAAmC,QAAA;EAAoB,KAAA;AAAA;EACrF,IAAA;EAAgB,MAAA;EAA0B,MAAA;EAAkB,QAAA;EAAoB,KAAA;AAAA;EAChF,IAAA;EAAgB,MAAA;AAAA;EAChB,IAAA;AAAA;EACA,IAAA;AAAA;EACA,IAAA;EAAiB,IAAA;AAAA;EACjB,IAAA;AAAA;EACA,IAAA;EAAc,IAAA;AAAA;EACd,IAAA;AAAA;AAAA,UAEI,WAAA;EACR,OAAA,GAAU,MAAA;EACV,EAAA;EACA,KAAA,GAAQ,MAAA;AAAA;;;;ALgDV;;iBKsBsB,aAAA,CACpB,MAAA,MAAY,IAAA,iBACZ,QAAA,UACA,KAAA,EAAO,MAAA,mBACP,QAAA,EAAU,OAAA,IACV,OAAA,EAAS,WAAA,cACT,QAAA,WACA,eAAA,YACC,OAAA;;iBASa,cAAA,CAAe,SAAA,UAAmB,IAAA,uBAA2B,OAAA;;;;;;ALxG7E;;;;;AAGA;;;;;AAUA;;;;;;;;;;;;;;;;cMmBa,eAAA,YAA2B,UAAA;EAAA,iBAEe,OAAA;EAAA,iBAClC,SAAA;EAAA,iBACA,eAAA;cAFkC,OAAA,EAAS,sBAAA,EAC3C,SAAA,EAAW,mBAAA,EACX,eAAA,EAAiB,eAAA;EAAA,OAG7B,OAAA,CAAQ,OAAA,EAAS,sBAAA,GAAyB,aAAA;EAajD,SAAA,CAAU,SAAA,EAAW,kBAAA;AAAA"}
|
package/build/index.mjs
CHANGED
|
@@ -326,6 +326,46 @@ function specialBinding(paramtype, data) {
|
|
|
326
326
|
}
|
|
327
327
|
}
|
|
328
328
|
//#endregion
|
|
329
|
+
//#region src/lib/requestSlots.ts
|
|
330
|
+
/**
|
|
331
|
+
* Classify every input field by the REST request slot it would occupy, reading
|
|
332
|
+
* the discovery-time {@link Binding}s. A whole-DTO `@Query()`/`@Body()` (`object`
|
|
333
|
+
* binding) contributes all its fields to the matching slot; a bare `@Param()`
|
|
334
|
+
* (`params` binding) and a path-sourced `value` go to `params`.
|
|
335
|
+
*/
|
|
336
|
+
function requestSlotFields(bindings) {
|
|
337
|
+
const slots = {
|
|
338
|
+
params: [],
|
|
339
|
+
query: [],
|
|
340
|
+
body: []
|
|
341
|
+
};
|
|
342
|
+
for (const b of bindings) if (b.kind === "params") slots.params.push(...b.fields);
|
|
343
|
+
else if (b.kind === "object") slots[b.source].push(...b.fields);
|
|
344
|
+
else if (b.kind === "value") slots[b.source === "path" ? "params" : b.source].push(b.field);
|
|
345
|
+
return slots;
|
|
346
|
+
}
|
|
347
|
+
/** Fill one request slot from the validated input, only adding absent keys. */
|
|
348
|
+
function fillSlot(bag, fields, input, stringify) {
|
|
349
|
+
for (const field of fields) if (!(field in bag) && input[field] !== void 0) bag[field] = stringify ? String(input[field]) : input[field];
|
|
350
|
+
}
|
|
351
|
+
/**
|
|
352
|
+
* Fill `request.params`/`query`/`body` from the validated input, mirroring the
|
|
353
|
+
* slots Express would populate over REST (path -> `params`, `@Query` -> `query`,
|
|
354
|
+
* `@Body` -> `body`). Path/query values are stringified to match how Express
|
|
355
|
+
* delivers them (a guard reading `req.query.limit` sees `'10'`, not `10`); body
|
|
356
|
+
* keeps the parsed values. Only absent keys are added, so a real REST/tRPC
|
|
357
|
+
* request's own params/query/body are never overwritten. This is what lets a
|
|
358
|
+
* scope-enforcing guard (`req.params.sessionId`, `req.body.sessionId`, ...)
|
|
359
|
+
* decide identically over MCP and REST.
|
|
360
|
+
*/
|
|
361
|
+
function populateRequestSlots(request, slots, input) {
|
|
362
|
+
if (typeof request !== "object" || request === null) return;
|
|
363
|
+
const req = request;
|
|
364
|
+
if (slots.params.length > 0) fillSlot(req.params ??= {}, slots.params, input, true);
|
|
365
|
+
if (slots.query.length > 0) fillSlot(req.query ??= {}, slots.query, input, true);
|
|
366
|
+
if (slots.body.length > 0) fillSlot(req.body ??= {}, slots.body, input, false);
|
|
367
|
+
}
|
|
368
|
+
//#endregion
|
|
329
369
|
//#region src/lib/reflect/classValidator.ts
|
|
330
370
|
let cached;
|
|
331
371
|
/**
|
|
@@ -894,14 +934,14 @@ let ControllerDiscovery = class ControllerDiscovery {
|
|
|
894
934
|
baseShape: shape,
|
|
895
935
|
bindings,
|
|
896
936
|
guards: collectGuards(this.reflector, d.classRef, d.method),
|
|
897
|
-
|
|
937
|
+
requestSlots: requestSlotFields(bindings),
|
|
898
938
|
streaming: isAsyncGeneratorFn(d.method)
|
|
899
939
|
};
|
|
900
940
|
}
|
|
901
941
|
/** Build a guard-application closure shared by both run shapes. */
|
|
902
942
|
guardRunner(d, shared, globalGuards) {
|
|
903
943
|
const { moduleRef, reflector, appConfig } = this;
|
|
904
|
-
const { guards,
|
|
944
|
+
const { guards, requestSlots } = shared;
|
|
905
945
|
const { classRef, method } = d;
|
|
906
946
|
return async (context, input) => {
|
|
907
947
|
const all = [...collectGlobalGuards(appConfig, globalGuards), ...guards];
|
|
@@ -914,7 +954,7 @@ let ControllerDiscovery = class ControllerDiscovery {
|
|
|
914
954
|
params: {},
|
|
915
955
|
query: {}
|
|
916
956
|
};
|
|
917
|
-
|
|
957
|
+
populateRequestSlots(guardRequest, requestSlots, input);
|
|
918
958
|
await runGuards(all, moduleRef, reflector, classRef, method, guardRequest, response, hasRequest ? "http" : "rpc");
|
|
919
959
|
};
|
|
920
960
|
}
|
|
@@ -1097,23 +1137,6 @@ function buildInput(proto, methodName, pathParams, slots, operationParams, docFi
|
|
|
1097
1137
|
warnings
|
|
1098
1138
|
};
|
|
1099
1139
|
}
|
|
1100
|
-
/** Input field names that originate from the URL path (`@Param`), per the re-bind plan. */
|
|
1101
|
-
function pathParamFields(bindings) {
|
|
1102
|
-
const fields = [];
|
|
1103
|
-
for (const b of bindings) if (b.kind === "params") fields.push(...b.fields);
|
|
1104
|
-
else if (b.kind === "value" && b.source === "path") fields.push(b.field);
|
|
1105
|
-
return fields;
|
|
1106
|
-
}
|
|
1107
|
-
/**
|
|
1108
|
-
* Fill `request.params` with the reflected path fields from the validated input,
|
|
1109
|
-
* matching what Express would populate over REST (raw string values). Only adds
|
|
1110
|
-
* keys that are absent, so a real REST request's params are never overwritten.
|
|
1111
|
-
*/
|
|
1112
|
-
function populatePathParams(request, pathFields, input) {
|
|
1113
|
-
if (pathFields.length === 0 || typeof request !== "object" || request === null) return;
|
|
1114
|
-
const params = request.params ??= {};
|
|
1115
|
-
for (const field of pathFields) if (!(field in params) && input[field] !== void 0) params[field] = String(input[field]);
|
|
1116
|
-
}
|
|
1117
1140
|
function designTypeAt(designTypes, index) {
|
|
1118
1141
|
const ctor = designTypes[index];
|
|
1119
1142
|
if (ctor === String) return { type: "string" };
|
package/build/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../src/lib/metadata.ts","../src/decorator/mcp.ts","../src/decorator/trpc.ts","../src/lib/executionContext.ts","../src/lib/guards.ts","../src/lib/reflect/params.ts","../src/lib/rebind.ts","../src/lib/reflect/classValidator.ts","../src/lib/reflect/schema.ts","../src/lib/reflect/openapi.ts","../src/lib/reflect/response.ts","../src/lib/reflect/route.ts","../src/lib/reflect/swagger.ts","../src/lib/controllerDiscovery.ts","../src/lib/types.ts","../src/lib/silkweave.module.ts"],"sourcesContent":["import type { Type } from '@nestjs/common'\nimport type { z } from 'zod/v4'\n\n/** Reflect-metadata key carrying `@Mcp` options on a controller method. */\nexport const MCP_METADATA = '__silkweave_mcp__'\n\n/** Reflect-metadata key carrying `@Trpc` options on a controller method. */\nexport const TRPC_METADATA = '__silkweave_trpc__'\n\n/**\n * Options for the `@Mcp()` method decorator. Every field is optional - an empty\n * `@Mcp()` exposes the decorated controller route as an MCP tool with its name,\n * description, and input schema fully reflected from the method's route\n * (`@Get`/`@Post`/...), parameter decorators (`@Param`/`@Query`/`@Body`), and\n * any `@nestjs/swagger` (`@ApiOperation`/`@ApiParam`/`@ApiProperty`) or\n * `class-validator` metadata it carries.\n */\nexport interface McpMetadata {\n /**\n * MCP tool name override. When unset it is derived from the controller class\n * and method name (e.g. `ChannelsController.findOne` → `ChannelsFindOne`).\n */\n name?: string\n /**\n * Tool description override. When unset it falls back to the method's\n * `@ApiOperation({ summary | description })`, then a generated default.\n */\n description?: string\n /**\n * Zod override merged over the reflected input fields (override wins per\n * field). Accepts either a raw shape (`{ field: z.string() }`) or a whole\n * `z.object({ ... })` - the object's `.shape` is unwrapped. The escape hatch\n * for shapes reflection can't express losslessly - discriminated unions,\n * custom validators, `@Transform`, etc. Note it *adds to* the reflected\n * fields; it does not replace them, so a field reflection silently dropped\n * (see the unreflectable-param warning) is not recovered by listing the\n * others here.\n */\n input?: Record<string, z.ZodType> | z.ZodObject\n /**\n * Whether to apply the controller method's parameter-bound pipes\n * (`@Param('id', ParseIntPipe)`) when re-binding the call. Default `'apply'`.\n * Global/`ValidationPipe`, interceptors, and exception filters never run -\n * the method is invoked directly, not through Nest's HTTP request pipeline.\n */\n pipes?: 'apply' | 'skip'\n /**\n * Default MCP result format for this tool. `'json'` returns compact JSON text\n * (`jsonToolResult`); `'smart'` (the default when unset) inlines small\n * payloads and offloads large ones to an embedded resource (`smartToolResult`).\n * This is only a default - a client that sends `_meta.disposition` on the tool\n * call overrides it.\n */\n result?: 'json' | 'smart'\n}\n\n/** tRPC procedure kind for a `@Trpc`-decorated route. */\nexport type TrpcKind = 'query' | 'mutation' | 'subscription'\n\n/**\n * Options for the `@Trpc()` method decorator - the tRPC sibling of `@Mcp`. An\n * empty `@Trpc()` exposes the decorated controller route as a tRPC procedure\n * with its key, input schema, and kind reflected from the route + parameter\n * decorators + swagger/class-validator metadata (identically to `@Mcp`).\n *\n * Unlike MCP, tRPC carries precise *output* types into the generated router, so\n * `@Trpc` adds an `output`/`chunk` hatch and a `kind` override on top of the\n * shared reflection. The two decorators compose on the same method.\n */\nexport interface TrpcMetadata {\n /**\n * Procedure-name override (before camelCasing). When unset it is derived from\n * the controller class + method name (e.g. `UsersController.listBySpace` →\n * `Users.listBySpace`, camelCased by the router to `usersListBySpace`).\n */\n name?: string\n /**\n * Procedure description override. When unset it falls back to the method's\n * `@ApiOperation({ summary | description })`, then a generated default.\n */\n description?: string\n /**\n * Zod override merged over the reflected input fields (override wins per\n * field). Accepts a raw shape (`{ field: z.string() }`) or a whole\n * `z.object({ ... })` (its `.shape` is unwrapped). Same escape hatch as\n * `@Mcp({ input })`.\n */\n input?: Record<string, z.ZodType> | z.ZodObject\n /**\n * Explicit output schema driving the generated procedure's output type - a Zod\n * type, a DTO class (reflected like `@ApiOkResponse`), or a raw shape (wrapped\n * in `z.object`). Wins over `@ApiOkResponse` reflection. The biggest reason to\n * set this is when the return shape can't be reflected losslessly from a DTO.\n */\n output?: z.ZodType | Type | Record<string, z.ZodType>\n /**\n * Chunk schema for an async-generator route exposed as a tRPC **subscription**.\n * A Zod type or a DTO class. Drives the emitted\n * `TRPCSubscriptionProcedure<{ output }>` type. When unset the chunk type falls\n * back to `unknown`.\n */\n chunk?: z.ZodType | Type\n /**\n * Procedure kind. When unset it is inferred: an `async *` route ⇒\n * `'subscription'`, a `@Get` route ⇒ `'query'`, anything else ⇒ `'mutation'`.\n * Set this to expose a verb-less route (no `@Get`/`@Post`) as a query or\n * subscription - `@Trpc({ kind })` works without an HTTP-verb decorator, so the\n * route is served over tRPC (and/or MCP) without becoming a public REST route.\n */\n kind?: TrpcKind\n /**\n * Whether to apply the method's parameter-bound pipes when re-binding the call.\n * Default `'apply'`. Same semantics as `@Mcp({ pipes })`.\n */\n pipes?: 'apply' | 'skip'\n}\n","import { SetMetadata } from '@nestjs/common'\nimport { MCP_METADATA, type McpMetadata } from '../lib/metadata.js'\n\n/**\n * Method decorator that exposes an existing NestJS controller route as an MCP\n * tool. It is **additive** - the route keeps serving HTTP exactly as before;\n * `@Mcp()` just opts the method into MCP discovery.\n *\n * The tool's name, description, and input schema are reflected from the\n * method's own metadata:\n * - **fields** from the parameter decorators (`@Param`/`@Query`/`@Body`) - a\n * `@Param('id')` becomes an `id` field; a whole-DTO `@Body() dto: CreateDto`\n * is flattened to its properties,\n * - **types/constraints/descriptions** from `@nestjs/swagger`\n * (`@ApiParam`/`@ApiQuery`/`@ApiProperty`/`@ApiOperation`) and, when present,\n * `class-validator` decorators on the DTOs,\n * - optionally refined by an OpenAPI document passed to `SilkweaveModule`.\n *\n * On a tool call the input is split back into the method's positional arguments\n * and the method is invoked directly (with `@UseGuards` guards applied first).\n *\n * @example\n * ```ts\n * @Controller('sessions/:sessionId/channels')\n * export class ChannelsController {\n * @Get(':channelId')\n * @ApiOperation({ summary: 'Get a specific channel by ID' })\n * @ApiParam({ name: 'sessionId', description: 'Session ID' })\n * @ApiParam({ name: 'channelId', description: 'Channel ID' })\n * @Mcp()\n * findOne(@Param('sessionId') sessionId: string, @Param('channelId') channelId: string) {\n * return this.service.get(sessionId, channelId)\n * }\n * }\n * ```\n */\nexport function Mcp(options: McpMetadata = {}): MethodDecorator {\n return SetMetadata(MCP_METADATA, options)\n}\n","import { SetMetadata } from '@nestjs/common'\nimport { TRPC_METADATA, type TrpcMetadata } from '../lib/metadata.js'\n\n/**\n * Method decorator that exposes a NestJS controller route as a **tRPC\n * procedure** - the sibling of `@Mcp`. Like `@Mcp` it is additive and reflects\n * the procedure's input from the method's own metadata (route + `@Param`/\n * `@Query`/`@Body` + swagger/class-validator), so a single method can carry both\n * `@Trpc()` and `@Mcp()` and `@UseGuards()`.\n *\n * Two things differ from MCP because tRPC consumers need them:\n * - **kind** - inferred from the route (`@Get` ⇒ query, others ⇒ mutation) or an\n * `async *` body (⇒ subscription); override with `@Trpc({ kind })`.\n * - **output** - the generated `AppRouter` carries precise output types. Drive\n * them with `@ApiOkResponse({ type: Dto })` reflection or `@Trpc({ output })`.\n *\n * `@Trpc()` works **without** an HTTP-verb decorator: with no `@Get`/`@Post` the\n * route is never mapped as REST, so `@Trpc({ kind })` exposes it over tRPC (and\n * `@Mcp` over MCP) while keeping it off the public REST surface.\n *\n * @example\n * ```ts\n * @Controller('users')\n * export class UsersController {\n * @Get('list-by-space')\n * @ApiOperation({ summary: 'List users in a space' })\n * @ApiOkResponse({ type: ListUsersResponse }) // drives the output type\n * @UseGuards(AuthGuard)\n * @Trpc() // → procedure `usersListBySpace` (query)\n * @Mcp() // → MCP tool `UsersListBySpace`\n * listBySpace(@Query() q: ListBySpaceQuery, @Req() req: AppRequest) {\n * return this.service.list(req.user, q.spaceId)\n * }\n * }\n * ```\n */\nexport function Trpc(options: TrpcMetadata = {}): MethodDecorator {\n return SetMetadata(TRPC_METADATA, options)\n}\n","import type { ArgumentsHost, ContextType, ExecutionContext, Type } from '@nestjs/common'\n\n/** Subset of `HttpArgumentsHost` we need - re-declared inline to avoid deep `@nestjs/common/interfaces` imports. */\ninterface HttpHost {\n getRequest<T = unknown>(): T\n getResponse<T = unknown>(): T\n getNext<T = unknown>(): T\n}\n\ninterface RpcHost {\n getData<T = unknown>(): T\n getContext<T = unknown>(): T\n}\n\ninterface WsHost {\n getClient<T = unknown>(): T\n getData<T = unknown>(): T\n getPattern(): string\n}\n\n/**\n * Minimal `ExecutionContext` impl Nest guards can consume. We only need\n * `switchToHttp()` to work for our HTTP-backed transports; the RPC/WS shims are\n * stubbed so guards that introspect type can still call them without crashing.\n */\nexport class SilkweaveExecutionContext implements ExecutionContext, ArgumentsHost {\n constructor(\n private readonly args: unknown[],\n private readonly classRef: Type<unknown>,\n private readonly handler: (...handlerArgs: unknown[]) => unknown,\n private readonly contextType = 'http'\n ) { }\n\n getType<T extends string = ContextType>(): T {\n return this.contextType as T\n }\n\n getClass<T = unknown>(): Type<T> {\n return this.classRef as Type<T>\n }\n\n getHandler(): (...handlerArgs: unknown[]) => unknown {\n return this.handler\n }\n\n getArgs<T extends unknown[] = unknown[]>(): T {\n return this.args as T\n }\n\n getArgByIndex<T = unknown>(index: number): T {\n return this.args[index] as T\n }\n\n switchToHttp(): HttpHost {\n return {\n getRequest: <T = unknown>(): T => this.args[0] as T,\n getResponse: <T = unknown>(): T => this.args[1] as T,\n getNext: <T = unknown>(): T => this.args[2] as T\n }\n }\n\n switchToRpc(): RpcHost {\n return {\n getData: <T = unknown>(): T => this.args[0] as T,\n getContext: <T = unknown>(): T => this.args[1] as T\n }\n }\n\n switchToWs(): WsHost {\n return {\n getClient: <T = unknown>(): T => this.args[0] as T,\n getData: <T = unknown>(): T => this.args[1] as T,\n getPattern: (): string => ''\n }\n }\n}\n","import { ForbiddenException, type CanActivate, type Type } from '@nestjs/common'\nimport { GUARDS_METADATA } from '@nestjs/common/constants.js'\nimport { ApplicationConfig, ModuleRef, Reflector } from '@nestjs/core'\nimport { isObservable, lastValueFrom } from 'rxjs'\nimport { SilkweaveExecutionContext } from './executionContext.js'\n\ntype GuardRef = Type<CanActivate> | CanActivate\n\n/**\n * Collect the app's global guards that match an opt-in allow-list of classes.\n *\n * Reads both registration styles Nest exposes via `ApplicationConfig`:\n * `useGlobalGuards(new X())` instances (`getGlobalGuards()`) and\n * `{ provide: APP_GUARD, useClass }` DI guards (`getGlobalRequestGuards()`,\n * which yields `InstanceWrapper`s - we read `.instance` off each).\n *\n * The allow-list is intentionally explicit-by-class: a blanket \"run every\n * global\" would also fire unrelated globals (e.g. a `ThrottlerGuard` that\n * assumes a writable response) on every tool call. An empty allow-list runs\n * no globals, preserving the prior behavior.\n *\n * Call this at tool-call time, not at discovery time: `APP_GUARD` instances\n * aren't populated until `app.init()` finishes.\n */\nexport function collectGlobalGuards(\n appConfig: ApplicationConfig,\n allowList: Type<CanActivate>[]\n): CanActivate[] {\n if (allowList.length === 0) { return [] }\n const globals: CanActivate[] = [\n ...appConfig.getGlobalGuards(),\n ...appConfig.getGlobalRequestGuards().map((w) => w.instance)\n ].filter((g): g is CanActivate => g != null)\n return globals.filter((g) => allowList.some((c) => g instanceof c))\n}\n\n/**\n * Read `@UseGuards(...)` metadata for both the method and its class and merge\n * the two lists. Method-level guards run AFTER class-level guards (matching\n * Nest's own behavior).\n */\nexport function collectGuards(\n reflector: Reflector,\n classRef: Type<unknown>,\n handler: (...args: unknown[]) => unknown\n): GuardRef[] {\n const classGuards = reflector.get<GuardRef[]>(GUARDS_METADATA, classRef) ?? []\n const methodGuards = reflector.get<GuardRef[]>(GUARDS_METADATA, handler) ?? []\n return [...classGuards, ...methodGuards]\n}\n\nasync function resolveGuard(ref: GuardRef, moduleRef: ModuleRef): Promise<CanActivate> {\n if (typeof ref === 'function') {\n try {\n return await moduleRef.get(ref, { strict: false })\n } catch {\n return moduleRef.create(ref)\n }\n }\n return ref\n}\n\n/**\n * Run the configured guards against a request. Throws `ForbiddenException`\n * if any guard rejects, mirroring Nest's HTTP request-pipeline behavior.\n *\n * Pass `null` for `response` when running on top of a tRPC or MCP request that\n * doesn't surface a raw response object; guards that introspect the response\n * will receive `null`.\n *\n * `contextType` is reflected through `ExecutionContext.getType()` so guards can\n * branch on the transport. It is `'http'` for REST/tRPC and for MCP-over-HTTP\n * (where a header-bearing request stand-in is available); transports without any\n * HTTP request (e.g. MCP stdio) pass `'rpc'`.\n */\nexport async function runGuards(\n guards: GuardRef[],\n moduleRef: ModuleRef,\n reflector: Reflector,\n classRef: Type<unknown>,\n handler: (...args: unknown[]) => unknown,\n request: unknown,\n response: unknown,\n contextType: 'http' | 'rpc' = 'http'\n): Promise<void> {\n if (guards.length === 0) { return }\n const context = new SilkweaveExecutionContext([request, response], classRef, handler, contextType)\n for (const ref of guards) {\n const guard = await resolveGuard(ref, moduleRef)\n const result = guard.canActivate(context)\n const allowed = isObservable(result) ? await lastValueFrom(result) : await Promise.resolve(result)\n if (!allowed) {\n throw new ForbiddenException('Forbidden resource')\n }\n }\n // Reflector kept in the signature for future use (e.g., per-guard metadata) - unused here.\n void reflector\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { ROUTE_ARGS_METADATA } from '@nestjs/common/constants.js'\n\n/**\n * `RouteParamtypes` numeric values from `@nestjs/common` (re-declared to avoid a\n * value import of an internal enum). These are how `@Param`/`@Query`/`@Body`/...\n * tag each handler argument in `ROUTE_ARGS_METADATA`.\n */\nexport const PARAMTYPE = {\n REQUEST: 0,\n RESPONSE: 1,\n NEXT: 2,\n BODY: 3,\n QUERY: 4,\n PARAM: 5,\n HEADERS: 6,\n SESSION: 7,\n FILE: 8,\n FILES: 9,\n HOST: 10,\n IP: 11,\n RAW_BODY: 12\n} as const\n\nexport interface ParamSlot {\n /** `PARAMTYPE` value - which decorator tagged this argument. */\n paramtype: number\n /** Handler argument position. */\n index: number\n /** Decorator sub-key: `@Param('id')` → `'id'`; a bare `@Body()` → `undefined`. */\n data?: string\n /** Parameter-bound pipes (`@Param('id', ParseIntPipe)`). */\n pipes: unknown[]\n /** TypeScript-emitted constructor at this position (e.g. `String`, `CreateDto`). */\n designType?: unknown\n}\n\n/**\n * Read and normalise the route-argument metadata for a controller method.\n * Returns one {@link ParamSlot} per decorated handler argument, sorted by\n * argument index.\n */\nexport function readParamSlots(classRef: any, methodName: string, proto: any): ParamSlot[] {\n const raw = Reflect.getMetadata(ROUTE_ARGS_METADATA, classRef, methodName) as\n Record<string, { index: number; data?: unknown; pipes?: unknown[] }> | undefined\n if (!raw) { return [] }\n const designTypes = (Reflect.getMetadata('design:paramtypes', proto, methodName) as unknown[] | undefined) ?? []\n\n const slots: ParamSlot[] = []\n for (const key of Object.keys(raw)) {\n const entry = raw[key]\n const paramtype = Number(key.split(':')[0])\n if (Number.isNaN(paramtype)) { continue }\n slots.push({\n paramtype,\n index: entry.index,\n data: typeof entry.data === 'string' ? entry.data : undefined,\n pipes: entry.pipes ?? [],\n designType: designTypes[entry.index]\n })\n }\n return slots.sort((a, b) => a.index - b.index)\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment */\nimport { PARAMTYPE } from './reflect/params.js'\n\n/**\n * Instruction for reconstructing one positional handler argument from the flat\n * MCP tool input. Built at discovery time, consumed by {@link invokeRebound}.\n */\nexport type Binding =\n | { kind: 'value'; field: string; source: 'path' | 'query' | 'body'; metatype?: unknown; pipes?: unknown[] }\n | { kind: 'object'; source: 'query' | 'body'; fields: string[]; metatype?: unknown; pipes?: unknown[] }\n | { kind: 'params'; fields: string[] }\n | { kind: 'request' }\n | { kind: 'response' }\n | { kind: 'headers'; data?: string }\n | { kind: 'ip' }\n | { kind: 'host'; data?: string }\n | { kind: 'missing' }\n\ninterface RequestLike {\n headers?: Record<string, unknown>\n ip?: unknown\n hosts?: Record<string, unknown>\n}\n\nfunction newInstance(P: any): any | null {\n try { return new P() } catch { return null }\n}\n\nasync function applyPipes(value: unknown, pipes: unknown[] | undefined, metatype: unknown, type: 'param' | 'query' | 'body', data: string | undefined): Promise<unknown> {\n if (!pipes || pipes.length === 0) { return value }\n let current = value\n for (const p of pipes) {\n const pipe = typeof p === 'function' ? newInstance(p) : p\n if (pipe && typeof (pipe).transform === 'function') {\n current = await (pipe).transform(current, { type, metatype, data })\n }\n }\n return current\n}\n\n/** Pick a subset of keys (skipping `undefined`) into a fresh object. */\nfunction pickFields(input: Record<string, unknown>, fields: string[]): Record<string, unknown> {\n const obj: Record<string, unknown> = {}\n for (const f of fields) {\n if (input[f] !== undefined) { obj[f] = input[f] }\n }\n return obj\n}\n\n/** Resolve a single positional argument from one binding. */\nasync function resolveArg(\n b: Binding,\n input: Record<string, unknown>,\n request: RequestLike | undefined,\n response: unknown,\n applyParamPipes: boolean\n): Promise<unknown> {\n switch (b.kind) {\n case 'value': {\n const raw = input[b.field]\n const type = b.source === 'path' ? 'param' : b.source\n return applyParamPipes ? applyPipes(raw, b.pipes, b.metatype, type, b.field) : raw\n }\n case 'object': {\n const obj = pickFields(input, b.fields)\n return applyParamPipes ? applyPipes(obj, b.pipes, b.metatype, b.source, undefined) : obj\n }\n case 'params':\n return pickFields(input, b.fields)\n case 'headers':\n return b.data ? request?.headers?.[b.data.toLowerCase()] : (request?.headers ?? {})\n case 'request':\n return request ?? { headers: {} }\n case 'response':\n // The real Express response over tRPC (so `@Res({ passthrough: true })`\n // can set cookies/headers); `undefined` over MCP (no HTTP response).\n return response\n case 'ip':\n return request?.ip\n case 'host':\n return b.data ? request?.hosts?.[b.data] : request?.hosts\n default:\n return undefined\n }\n}\n\n/**\n * Reconstruct the controller method's positional arguments from the validated\n * tool `input` (and the request stand-in for `@Req`/`@Headers`/...), then call\n * it. `applyParamPipes` controls whether parameter-bound pipes run.\n */\nexport async function invokeRebound(\n method: (...args: any[]) => any,\n instance: object,\n input: Record<string, unknown>,\n bindings: Binding[],\n request: RequestLike | undefined,\n response: unknown,\n applyParamPipes: boolean\n): Promise<unknown> {\n const args: unknown[] = []\n for (let i = 0; i < bindings.length; i += 1) {\n args[i] = await resolveArg(bindings[i], input, request, response, applyParamPipes)\n }\n return await method.apply(instance, args)\n}\n\n/** Map a non-input parameter slot (`@Req`/`@Headers`/`@Ip`/...) to its runtime binding. */\nexport function specialBinding(paramtype: number, data: string | undefined): Binding | null {\n switch (paramtype) {\n case PARAMTYPE.REQUEST: return { kind: 'request' }\n case PARAMTYPE.RESPONSE:\n case PARAMTYPE.NEXT: return { kind: 'response' }\n case PARAMTYPE.HEADERS: return { kind: 'headers', data }\n case PARAMTYPE.IP: return { kind: 'ip' }\n case PARAMTYPE.HOST: return { kind: 'host', data }\n case PARAMTYPE.SESSION:\n case PARAMTYPE.FILE:\n case PARAMTYPE.FILES:\n case PARAMTYPE.RAW_BODY: return { kind: 'missing' }\n default: return null\n }\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment */\nimport { createRequire } from 'node:module'\nimport { join } from 'node:path'\n\nlet cached: any | null | undefined\n\n/**\n * Lazily resolve the optional `class-validator` peer; `null` when not installed.\n * Resolution is attempted both from this package and from the app's working\n * directory - the latter is what finds it in a pnpm install where the optional\n * peer lives in the consumer app rather than alongside `@silkweave/nestjs`. A\n * pnpm-deduped install shares one physical copy, so the metadata singleton the\n * app's decorators wrote to is the same one we read.\n */\nfunction loadClassValidator(): any | null {\n if (cached !== undefined) { return cached }\n for (const base of [import.meta.url, join(process.cwd(), 'noop.js')]) {\n try {\n cached = createRequire(base)('class-validator')\n return cached\n } catch { /* try the next resolution base */ }\n }\n cached = null\n return cached\n}\n\nexport interface ValidationMeta {\n /** `ValidationTypes` discriminator (e.g. `customValidation`, `conditionalValidation`). */\n type?: string\n /** Validator name - the actionable identity for built-ins (`isString`, `minLength`, ...). */\n name?: string\n constraints?: unknown[]\n}\n\n/**\n * Read `class-validator` metadata for a DTO class, grouped by property name.\n * Returns an empty map when `class-validator` is not installed or the class\n * carries no validation decorators - so callers degrade gracefully to swagger /\n * `design:type` reflection.\n */\nexport function classValidatorMetas(dtoType: any): Record<string, ValidationMeta[]> {\n const cv = loadClassValidator()\n if (!cv?.getMetadataStorage) { return {} }\n let metas: Array<{ propertyName?: string; type?: string; name?: string; constraints?: unknown[] }>\n try {\n metas = cv.getMetadataStorage().getTargetValidationMetadatas(dtoType, null, false, false)\n } catch {\n return {}\n }\n const out: Record<string, ValidationMeta[]> = {}\n for (const m of metas) {\n if (!m.propertyName) { continue }\n (out[m.propertyName] ??= []).push({ type: m.type, name: m.name, constraints: m.constraints })\n }\n return out\n}\n","/* eslint-disable @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-explicit-any */\nimport { z } from 'zod/v4'\nimport { classValidatorMetas } from './classValidator.js'\n\n/** `@nestjs/swagger` reflect-metadata keys. Read directly so swagger stays an optional peer. */\nconst API_MODEL_PROPERTIES = 'swagger/apiModelProperties'\nconst API_MODEL_PROPERTIES_ARRAY = 'swagger/apiModelPropertiesArray'\n\n/**\n * A transport-neutral description of a single input field. Every metadata\n * source (swagger decorators, class-validator, an OpenAPI document, TypeScript\n * `design:type`) is mapped to this shape, the shapes are merged by precedence,\n * and the result is converted to Zod once. Keeping a single intermediate keeps\n * the per-source mappers small and the Zod construction in one place.\n */\nexport interface FieldDesc {\n type?: 'string' | 'number' | 'integer' | 'boolean' | 'array' | 'object' | 'unknown'\n required?: boolean\n /** Field accepts `null` (`@ApiProperty({ nullable: true })` / OpenAPI `nullable`). */\n nullable?: boolean\n description?: string\n enum?: (string | number)[]\n items?: FieldDesc\n min?: number\n max?: number\n minLength?: number\n maxLength?: number\n format?: string\n default?: unknown\n}\n\n/** Strip `undefined` values so a later source never clobbers an earlier one with a hole. */\nfunction defined<T extends object>(obj: T): Partial<T> {\n const out: Record<string, unknown> = {}\n for (const [k, v] of Object.entries(obj)) {\n if (v !== undefined) { out[k] = v }\n }\n return out as Partial<T>\n}\n\n/** Merge `over` onto `base` - defined keys of `over` win. */\nexport function mergeField(base: FieldDesc, over: FieldDesc): FieldDesc {\n return { ...base, ...defined(over) }\n}\n\nfunction enumToZod(values: (string | number)[]): z.ZodType {\n const strings = values.filter((v): v is string => typeof v === 'string')\n if (strings.length === values.length && strings.length > 0) {\n return z.enum(strings as [string, ...string[]])\n }\n const literals = values.map((v) => z.literal(v))\n if (literals.length === 0) { return z.unknown() }\n if (literals.length === 1) { return literals[0] }\n return z.union(literals as unknown as [z.ZodType, z.ZodType, ...z.ZodType[]])\n}\n\nfunction baseToZod(d: FieldDesc): z.ZodType {\n switch (d.type) {\n case 'string': {\n let s = z.string()\n if (d.minLength != null) { s = s.min(d.minLength) }\n if (d.maxLength != null) { s = s.max(d.maxLength) }\n return s\n }\n case 'integer':\n case 'number': {\n let n = z.number()\n if (d.type === 'integer') { n = n.int() }\n if (d.min != null) { n = n.min(d.min) }\n if (d.max != null) { n = n.max(d.max) }\n return n\n }\n case 'boolean':\n return z.boolean()\n case 'array':\n return z.array(d.items ? fieldToZod({ ...d.items, required: true }) : z.unknown())\n case 'object':\n return z.record(z.string(), z.unknown())\n default:\n return z.unknown()\n }\n}\n\n/** Convert a merged {@link FieldDesc} to a Zod schema. */\nexport function fieldToZod(d: FieldDesc): z.ZodType {\n let schema = (d.enum?.length) ? enumToZod(d.enum) : baseToZod(d)\n if (d.description) { schema = schema.describe(d.description) }\n if (d.nullable) { schema = schema.nullable() }\n if (d.default !== undefined) {\n schema = (schema as any).default(d.default)\n } else if (d.required === false) {\n schema = schema.optional()\n }\n return schema\n}\n\n// --- per-source mappers ---------------------------------------------------\n\n/** Normalise a TS-enum object or an array literal to a flat value list. */\nexport function normalizeEnum(value: unknown): (string | number)[] | undefined {\n if (Array.isArray(value)) {\n return value.filter((v): v is string | number => typeof v === 'string' || typeof v === 'number')\n }\n if (value && typeof value === 'object') {\n return Object.values(value).filter((v): v is string | number => typeof v === 'string' || typeof v === 'number')\n }\n return undefined\n}\n\n/** Map a swagger/`design:type` type token (constructor, `[Type]`, or string) to a base type. */\nexport function typeTokenToBase(type: unknown): FieldDesc['type'] | undefined {\n if (type == null) { return undefined }\n if (type === String) { return 'string' }\n if (type === Number) { return 'number' }\n if (type === Boolean) { return 'boolean' }\n if (type === Array) { return 'array' }\n if (type === Date) { return 'string' }\n if (Array.isArray(type)) { return 'array' }\n if (typeof type === 'string') {\n const t = type.toLowerCase()\n if (t === 'string' || t === 'number' || t === 'integer' || t === 'boolean' || t === 'array' || t === 'object') {\n return t\n }\n }\n return undefined\n}\n\n/** From the constructor TypeScript emits via `emitDecoratorMetadata`. */\nexport function designTypeToField(ctor: unknown): FieldDesc {\n const type = typeTokenToBase(ctor)\n const f: FieldDesc = {}\n if (type) { f.type = type }\n return f\n}\n\n/** From an `@ApiParam`/`@ApiQuery` entry stored under `swagger/apiParameters`. */\nexport function swaggerParamToField(p: Record<string, any>): FieldDesc {\n const f: FieldDesc = {}\n if (p['description']) { f.description = p['description'] }\n if (typeof p['required'] === 'boolean') { f.required = p['required'] }\n const type = typeTokenToBase(p['type'])\n if (type) { f.type = type }\n if (p['isArray']) { f.type = 'array' }\n const en = normalizeEnum(p['enum'])\n if (en) { f.enum = en }\n if (p['schema'] && typeof p['schema'] === 'object') {\n return mergeField(f, openapiSchemaToField(p['schema']))\n }\n return f\n}\n\n/** From an `@ApiProperty` options object stored under `swagger/apiModelProperties`. */\nexport function apiPropertyToField(o: Record<string, any>): FieldDesc {\n const f: FieldDesc = {}\n if (o['description']) { f.description = o['description'] }\n if (typeof o['required'] === 'boolean') { f.required = o['required'] }\n const type = typeTokenToBase(o['type'])\n if (type) { f.type = type }\n if (o['isArray']) {\n f.items = { type: type && type !== 'array' ? type : 'unknown' }\n f.type = 'array'\n }\n const en = normalizeEnum(o['enum'])\n if (en) { f.enum = en }\n if (o['minimum'] != null) { f.min = o['minimum'] }\n if (o['maximum'] != null) { f.max = o['maximum'] }\n if (o['minLength'] != null) { f.minLength = o['minLength'] }\n if (o['maxLength'] != null) { f.maxLength = o['maxLength'] }\n if (o['format']) { f.format = o['format'] }\n if (o['nullable'] === true) { f.nullable = true }\n if (o['default'] !== undefined) { f.default = o['default'] }\n return f\n}\n\n/** `class-validator` decorator type → field base type. */\nconst CV_TYPE: Record<string, FieldDesc['type']> = {\n isString: 'string',\n isInt: 'integer',\n isBoolean: 'boolean',\n isArray: 'array'\n}\n\n/** `class-validator` decorator type → numeric-constraint field key. */\nconst CV_NUMERIC: Record<string, 'min' | 'max' | 'minLength' | 'maxLength'> = {\n min: 'min',\n max: 'max',\n minLength: 'minLength',\n maxLength: 'maxLength'\n}\n\n/**\n * Fold one `class-validator` metadata entry into the field descriptor. Built-in\n * validators record their identity in `name` (`isString`, `minLength`, ...) with\n * `type: 'customValidation'`; `@IsOptional` uses `name: 'isOptional'`. We key off\n * `name`, falling back to `type`.\n */\nfunction applyValidationMeta(f: FieldDesc, meta: { type?: string; name?: string; constraints?: unknown[] }): void {\n const key = meta.name ?? meta.type\n if (!key) { return }\n if (key in CV_TYPE) { f.type = CV_TYPE[key]; return }\n const c0 = meta.constraints?.[0]\n if (key in CV_NUMERIC) {\n if (typeof c0 === 'number') { f[CV_NUMERIC[key]] = c0 }\n return\n }\n if (key === 'isNumber') { if (!f.type) { f.type = 'number' } return }\n if (key === 'isEmail') { if (!f.type) { f.type = 'string' } f.format = 'email'; return }\n if (key === 'isDate' || key === 'isDateString') { f.type = 'string'; f.format = 'date-time'; return }\n if (key === 'isEnum') { const e = normalizeEnum(c0); if (e) { f.enum = e } return }\n if (key === 'isOptional') { f.required = false }\n}\n\n/** From an array of `class-validator` validation-metadata entries for one property. */\nexport function classValidatorToField(metas: Array<{ type?: string; name?: string; constraints?: unknown[] }>): FieldDesc {\n const f: FieldDesc = {}\n for (const meta of metas) { applyValidationMeta(f, meta) }\n return f\n}\n\n/** From an OpenAPI Schema Object (used by both the doc and `@ApiParam({ schema })`). */\nexport function openapiSchemaToField(schema: Record<string, any>): FieldDesc {\n const f: FieldDesc = {}\n const type = typeof schema['type'] === 'string' ? schema['type'].toLowerCase() : undefined\n if (type === 'string' || type === 'number' || type === 'integer' || type === 'boolean' || type === 'array' || type === 'object') {\n f.type = type\n }\n if (schema['description']) { f.description = schema['description'] }\n const en = normalizeEnum(schema['enum'])\n if (en) { f.enum = en }\n if (schema['minimum'] != null) { f.min = schema['minimum'] }\n if (schema['maximum'] != null) { f.max = schema['maximum'] }\n if (schema['minLength'] != null) { f.minLength = schema['minLength'] }\n if (schema['maxLength'] != null) { f.maxLength = schema['maxLength'] }\n if (schema['format']) { f.format = schema['format'] }\n if (schema['nullable'] === true) { f.nullable = true }\n if (schema['default'] !== undefined) { f.default = schema['default'] }\n if (schema['items'] && typeof schema['items'] === 'object') {\n f.items = openapiSchemaToField(schema['items'])\n }\n return f\n}\n\n/**\n * Reflect a whole-DTO class (`@Body() dto: CreateDto`) into per-property\n * {@link FieldDesc}s. Property names are the union of `@ApiProperty` and\n * `class-validator` decorated fields; each field merges `design:type` (base),\n * then `class-validator` constraints, then `@ApiProperty` (highest). Properties\n * default to required unless a source marks them optional.\n */\nexport function reflectDtoFields(dtoType: any): Record<string, FieldDesc> {\n const proto = dtoType?.prototype\n if (!proto) { return {} }\n const cvMetas = classValidatorMetas(dtoType)\n\n const names = new Set<string>()\n const swaggerArray = (Reflect.getMetadata(API_MODEL_PROPERTIES_ARRAY, proto) as string[] | undefined) ?? []\n for (const entry of swaggerArray) { names.add(entry.replace(/^:/, '')) }\n for (const name of Object.keys(cvMetas)) { names.add(name) }\n\n const out: Record<string, FieldDesc> = {}\n for (const name of names) {\n let f = designTypeToField(Reflect.getMetadata('design:type', proto, name))\n if (cvMetas[name]) { f = mergeField(f, classValidatorToField(cvMetas[name])) }\n const apiProp = Reflect.getMetadata(API_MODEL_PROPERTIES, proto, name) as Record<string, any> | undefined\n if (apiProp) {\n const fromApi = apiPropertyToField(apiProp)\n // `@ApiProperty` is required unless `required: false` is explicit.\n if (fromApi.required === undefined && apiProp['required'] === undefined) { fromApi.required = true }\n f = mergeField(f, fromApi)\n }\n if (f.required === undefined) { f.required = true }\n out[name] = f\n }\n return out\n}\n\n/**\n * Names of fields that could not be reflected into a concrete type - they will\n * become `z.unknown()` (or `z.array(z.unknown())`). This is how a nested DTO or a\n * `Dto[]` property silently degrades (reflection is one level deep), so the\n * adapters surface these as a build-time warning pointing at `@Trpc({ output })`\n * / `@Mcp({ input })`. Enum and `object` (record) fields are not degraded.\n */\nexport function unreflectedFields(fields: Record<string, FieldDesc>): string[] {\n const out: string[] = []\n for (const [name, f] of Object.entries(fields)) {\n if (f.enum?.length) { continue }\n if (!f.type || f.type === 'unknown') { out.push(name) } else if (f.type === 'array' && (!f.items?.type || f.items.type === 'unknown')) { out.push(name) }\n }\n return out\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment */\nimport { type FieldDesc, mergeField, openapiSchemaToField } from './schema.js'\n\n/**\n * A minimal view of an OpenAPI document - the subset we read. Matches the shape\n * `SwaggerModule.createDocument()` returns, but typed loosely so callers can\n * pass any compatible object without a hard `@nestjs/swagger` dependency.\n */\nexport interface OpenApiDocument {\n paths?: Record<string, Record<string, any>>\n components?: { schemas?: Record<string, any> }\n}\n\nexport interface OpenApiLookup {\n doc: OpenApiDocument\n /** `${METHOD} ${path}` → operation object. */\n operations: Map<string, any>\n}\n\n/** Index a document's operations by `${METHOD} ${path}` for fast matching. */\nexport function buildOpenApiLookup(doc: OpenApiDocument): OpenApiLookup {\n const operations = new Map<string, any>()\n for (const [path, item] of Object.entries(doc.paths ?? {})) {\n for (const [verb, op] of Object.entries(item ?? {})) {\n operations.set(`${verb.toUpperCase()} ${path}`, op)\n }\n }\n return { doc, operations }\n}\n\n/** Locate the operation for a route, tolerating a global path prefix on the document side. */\nfunction findOperation(lookup: OpenApiLookup, method: string, openapiPath: string): any | undefined {\n const exact = lookup.operations.get(`${method} ${openapiPath}`)\n if (exact) { return exact }\n // Fall back to a suffix match so a `setGlobalPrefix('api')` document still resolves.\n for (const [key, op] of lookup.operations) {\n const [verb, path] = key.split(' ')\n if (verb === method && (path.endsWith(openapiPath) || openapiPath.endsWith(path))) { return op }\n }\n return undefined\n}\n\nfunction resolveRef(doc: OpenApiDocument, schema: any): any {\n let current = schema\n let guard = 0\n while (current && typeof current === 'object' && typeof current['$ref'] === 'string' && guard < 10) {\n const match = /^#\\/components\\/schemas\\/(.+)$/.exec(current['$ref'])\n if (!match) { break }\n current = doc.components?.schemas?.[match[1]]\n guard += 1\n }\n return current\n}\n\n/**\n * Resolve the per-field descriptors for a route from an ingested OpenAPI\n * document. Merges `parameters` (path/query/header) and the JSON request-body\n * schema's properties into a single field map. Returns `{}` when the operation\n * isn't found - callers fall back to decorator reflection.\n */\nexport function openApiFields(lookup: OpenApiLookup, method: string, openapiPath: string): Record<string, FieldDesc> {\n const op = findOperation(lookup, method, openapiPath)\n if (!op) { return {} }\n const out: Record<string, FieldDesc> = {}\n\n for (const param of (op['parameters'] as Array<Record<string, any>> | undefined) ?? []) {\n const name = typeof param['name'] === 'string' ? param['name'] : undefined\n if (!name) { continue }\n const schema = param['schema'] ? resolveRef(lookup.doc, param['schema']) : undefined\n let field = schema ? openapiSchemaToField(schema) : {}\n if (param['description']) { field = mergeField(field, { description: param['description'] }) }\n if (typeof param['required'] === 'boolean') { field = mergeField(field, { required: param['required'] }) }\n out[name] = field\n }\n\n const bodySchema = resolveRef(lookup.doc, op['requestBody']?.['content']?.['application/json']?.['schema'])\n if (bodySchema && typeof bodySchema === 'object' && bodySchema['properties']) {\n const required = new Set<string>(Array.isArray(bodySchema['required']) ? bodySchema['required'] : [])\n for (const [name, propSchema] of Object.entries(bodySchema['properties'] as Record<string, any>)) {\n const field = openapiSchemaToField(resolveRef(lookup.doc, propSchema))\n field.required = required.has(name)\n out[name] = field\n }\n }\n\n return out\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { z } from 'zod/v4'\nimport { type FieldDesc, fieldToZod, reflectDtoFields } from './schema.js'\n\n/** `@nestjs/swagger` response metadata key (read directly - swagger is an optional peer). */\nconst API_RESPONSE = 'swagger/apiResponse'\n\n/** Status keys we treat as the \"success\" response, in preference order. */\nconst SUCCESS_KEYS = ['200', '201', '202', '204', '2XX', 'default']\n\n/** The 2xx (or first) `@ApiResponse` entry for a method, if any. */\nfunction successEntry(method: (...args: any[]) => any): { type?: unknown; isArray?: boolean } | undefined {\n const responses = Reflect.getMetadata(API_RESPONSE, method) as Record<string, { type?: unknown; isArray?: boolean }> | undefined\n if (!responses) { return undefined }\n const key = SUCCESS_KEYS.find((k) => responses[k]) ?? Object.keys(responses)[0]\n return key ? responses[key] : undefined\n}\n\n/**\n * Reflect a `@Trpc` procedure's output schema from the method's\n * `@ApiOkResponse({ type: Dto })` (or any 2xx `@ApiResponse`) metadata. The\n * response DTO is flattened with {@link reflectDtoFields} into a Zod object,\n * wrapped in `z.array(...)` when the response is `isArray`.\n *\n * Returns `undefined` when there is no response DTO to reflect (e.g. a primitive\n * return type or no `@ApiResponse` decorator) - the caller then falls back to an\n * explicit `@Trpc({ output })` or an `unknown` output type.\n */\nexport function reflectResponseSchema(method: (...args: any[]) => any): z.ZodType | undefined {\n const entry = successEntry(method)\n const dtoType = entry?.type\n if (typeof dtoType !== 'function') { return undefined }\n\n const schema = reflectDtoSchema(dtoType)\n if (!schema) { return undefined }\n return entry?.isArray ? z.array(schema) : schema\n}\n\n/**\n * The reflected `FieldDesc` map for a method's response DTO (the same fields\n * {@link reflectResponseSchema} builds its schema from), or `undefined` when\n * there is no DTO to reflect. Used to detect fields that degraded to `unknown`\n * (nested DTO / `Dto[]`) so the caller can warn.\n */\nexport function reflectResponseFields(method: (...args: any[]) => any): Record<string, FieldDesc> | undefined {\n const dtoType = successEntry(method)?.type\n if (typeof dtoType !== 'function') { return undefined }\n return reflectDtoFields(dtoType)\n}\n\n/**\n * Reflect a DTO class (its `@ApiProperty`/`class-validator`-decorated properties)\n * into a Zod object schema. Returns `undefined` when the type isn't a class or\n * has no reflectable properties. Used for `@Trpc({ output })`/`@Trpc({ chunk })`\n * when given a DTO class instead of a Zod schema.\n */\nexport function reflectDtoSchema(dtoType: unknown): z.ZodType | undefined {\n if (typeof dtoType !== 'function') { return undefined }\n const fields = reflectDtoFields(dtoType)\n const names = Object.keys(fields)\n if (names.length === 0) { return undefined }\n const shape: Record<string, z.ZodType> = {}\n for (const name of names) { shape[name] = fieldToZod(fields[name]) }\n return z.object(shape)\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { PATH_METADATA, METHOD_METADATA } from '@nestjs/common/constants.js'\n\n/**\n * `RequestMethod` numeric values (from `@nestjs/common`) mapped to verbs. We\n * map our own table rather than importing the enum to avoid pulling a value\n * import for a handful of constants.\n */\nconst REQUEST_METHOD: Record<number, string> = {\n 0: 'GET',\n 1: 'POST',\n 2: 'PUT',\n 3: 'DELETE',\n 4: 'PATCH',\n 6: 'OPTIONS',\n 7: 'HEAD'\n}\n\nexport interface RouteInfo {\n /** HTTP verb (`GET`/`POST`/...). `PATCH` and others outside the REST set fall back to `POST`-ish handling by callers. */\n method: string\n /** Full route template in Nest form, e.g. `sessions/:sessionId/channels/:channelId` (no leading slash). */\n path: string\n /** Full route template in OpenAPI form, e.g. `/sessions/{sessionId}/channels/{channelId}`. */\n openapiPath: string\n /** Names of the `:param` placeholders across controller + method path. */\n pathParams: string[]\n}\n\nfunction normalizeSegment(value: unknown): string {\n if (typeof value !== 'string') { return '' }\n return value.replace(/^\\/+/, '').replace(/\\/+$/, '')\n}\n\nfunction joinPath(...segments: string[]): string {\n return segments.map(normalizeSegment).filter(Boolean).join('/')\n}\n\n/**\n * Resolve the composed route (controller prefix + method path), HTTP verb, and\n * path-param names for a decorated controller method, reading Nest's own\n * `PATH_METADATA`/`METHOD_METADATA` reflection.\n */\nexport function reflectRoute(classRef: any, method: (...args: any[]) => any): RouteInfo {\n const classPath = Reflect.getMetadata(PATH_METADATA, classRef) as string | string[] | undefined\n const methodPath = Reflect.getMetadata(PATH_METADATA, method) as string | string[] | undefined\n const verbCode = Reflect.getMetadata(METHOD_METADATA, method) as number | undefined\n\n const classSeg = Array.isArray(classPath) ? (classPath[0] ?? '') : (classPath ?? '')\n const methodSeg = Array.isArray(methodPath) ? (methodPath[0] ?? '') : (methodPath ?? '')\n const path = joinPath(classSeg, methodSeg)\n const httpMethod = REQUEST_METHOD[verbCode ?? 0] ?? 'GET'\n\n const pathParams = [...path.matchAll(/:([A-Za-z0-9_]+)/g)].map((m) => m[1])\n const openapiPath = `/${path.replace(/:([A-Za-z0-9_]+)/g, '{$1}')}`\n\n return { method: httpMethod, path, openapiPath, pathParams }\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport type { FieldDesc } from './schema.js'\nimport { swaggerParamToField } from './schema.js'\n\n/** `@nestjs/swagger` reflect-metadata keys (read directly - swagger is an optional peer). */\nconst API_OPERATION = 'swagger/apiOperation'\nconst API_PARAMETERS = 'swagger/apiParameters'\n\nexport interface OperationMeta {\n /** Tool-description candidate from `@ApiOperation({ summary | description })`. */\n description?: string\n /** Per-name `FieldDesc` reflected from `@ApiParam`/`@ApiQuery` entries. */\n params: Record<string, FieldDesc>\n}\n\n/**\n * Read operation-level `@nestjs/swagger` metadata off a controller method:\n * `@ApiOperation` (summary/description) and the `@ApiParam`/`@ApiQuery` array\n * (each describing one path/query field). Returns empty data when swagger\n * decorators are absent.\n */\nexport function reflectOperation(method: (...args: any[]) => any): OperationMeta {\n const operation = Reflect.getMetadata(API_OPERATION, method) as Record<string, any> | undefined\n const description = operation\n ? (typeof operation['summary'] === 'string' && operation['summary']\n ? operation['summary']\n : (typeof operation['description'] === 'string' ? operation['description'] : undefined))\n : undefined\n\n const parameters = (Reflect.getMetadata(API_PARAMETERS, method) as Array<Record<string, any>> | undefined) ?? []\n const params: Record<string, FieldDesc> = {}\n for (const p of parameters) {\n const name = typeof p['name'] === 'string' ? p['name'] : undefined\n if (!name) { continue }\n params[name] = swaggerParamToField(p)\n }\n\n return { description, params }\n}\n","/* eslint-disable @typescript-eslint/no-unsafe-assignment */\nimport { HttpException, Injectable, Logger, type CanActivate, type Type } from '@nestjs/common'\nimport { ApplicationConfig, DiscoveryService, MetadataScanner, ModuleRef, Reflector } from '@nestjs/core'\nimport { SilkweaveError, type Action, type ActionKind, type SilkweaveContext } from '@silkweave/core'\nimport { z } from 'zod/v4'\nimport { collectGlobalGuards, collectGuards, runGuards } from './guards.js'\nimport { MCP_METADATA, TRPC_METADATA, type McpMetadata, type TrpcMetadata } from './metadata.js'\nimport { invokeRebound, specialBinding, type Binding } from './rebind.js'\nimport { buildOpenApiLookup, openApiFields, type OpenApiDocument, type OpenApiLookup } from './reflect/openapi.js'\nimport { PARAMTYPE, type ParamSlot, readParamSlots } from './reflect/params.js'\nimport { reflectDtoSchema, reflectResponseFields, reflectResponseSchema } from './reflect/response.js'\nimport { reflectRoute, type RouteInfo } from './reflect/route.js'\nimport { type FieldDesc, fieldToZod, mergeField, reflectDtoFields, unreflectedFields } from './reflect/schema.js'\nimport { reflectOperation } from './reflect/swagger.js'\n\n/** Discovery-time diagnostics (unreflectable params, degraded outputs). */\nconst logger = new Logger('Silkweave')\n\ninterface Discovered {\n instance: object\n classRef: Type<unknown>\n method: (...args: unknown[]) => unknown\n methodName: string\n mcp?: McpMetadata\n trpc?: TrpcMetadata\n}\n\ninterface BuiltInput {\n shape: Record<string, z.ZodType>\n bindings: Binding[]\n /** Human-readable notes about params reflection could not turn into fields. */\n warnings: string[]\n}\n\n/** Shared reflection computed once per discovered method, reused across targets. */\ninterface Reflected {\n route: RouteInfo\n base: string\n description?: string\n baseShape: Record<string, z.ZodType>\n bindings: Binding[]\n guards: ReturnType<typeof collectGuards>\n pathFields: string[]\n streaming: boolean\n}\n\nexport interface DiscoverOptions {\n openapi?: OpenApiDocument\n globalGuards?: Type<CanActivate>[]\n defaultResult?: 'json' | 'smart'\n}\n\n@Injectable()\nexport class ControllerDiscovery {\n constructor(\n private readonly discovery: DiscoveryService,\n private readonly scanner: MetadataScanner,\n private readonly reflector: Reflector,\n private readonly moduleRef: ModuleRef,\n private readonly appConfig: ApplicationConfig\n ) { }\n\n /**\n * Walk every Nest provider/controller, find methods annotated with `@Mcp`\n * and/or `@Trpc`, and build a core `Action` per decorator present on each\n * method. The input schema is reflected from the route + parameter decorators\n * (+ optional OpenAPI document) and the `run` re-binds the validated input back\n * into the method's positional arguments (with `@UseGuards` guards applied\n * first). A method carrying both decorators yields two actions - one gated to\n * the `mcp` adapter, one to the `trpc`/`typegen` adapters - sharing the same\n * reflected input, bindings, and guards.\n */\n discover(options: DiscoverOptions = {}): Action[] {\n const lookup = options.openapi ? buildOpenApiLookup(options.openapi) : undefined\n const discovered: Discovered[] = []\n for (const wrapper of this.discovery.getProviders().concat(this.discovery.getControllers())) {\n const { instance } = wrapper\n if (!instance || typeof instance !== 'object') { continue }\n const proto = Object.getPrototypeOf(instance) as object | null\n if (!proto) { continue }\n const classRef = instance.constructor as Type<unknown>\n for (const methodName of this.scanner.getAllMethodNames(proto)) {\n const method = (proto as Record<string, unknown>)[methodName] as ((...args: unknown[]) => unknown) | undefined\n if (typeof method !== 'function') { continue }\n const mcp = this.reflector.get<McpMetadata>(MCP_METADATA, method)\n const trpc = this.reflector.get<TrpcMetadata>(TRPC_METADATA, method)\n if (!mcp && !trpc) { continue }\n discovered.push({ instance, classRef, method, methodName, mcp, trpc })\n }\n }\n\n const globalGuards = options.globalGuards ?? []\n const actions: Action[] = []\n for (const d of discovered) {\n const shared = this.reflect(d, lookup)\n if (d.mcp) { actions.push(this.mcpAction(d, shared, globalGuards, options.defaultResult)) }\n if (d.trpc) { actions.push(this.trpcAction(d, shared, globalGuards)) }\n }\n return actions\n }\n\n /** Compute the per-method reflection shared by the `mcp` and `trpc` builders. */\n private reflect(d: Discovered, lookup: OpenApiLookup | undefined): Reflected {\n const proto = Object.getPrototypeOf(d.instance) as object\n const route = reflectRoute(d.classRef, d.method)\n const slots = readParamSlots(d.classRef, d.methodName, proto)\n const operation = reflectOperation(d.method)\n const docFields = lookup ? openApiFields(lookup, route.method, route.openapiPath) : {}\n\n const { shape, bindings, warnings } = buildInput(proto, d.methodName, route.pathParams, slots, operation.params, docFields)\n for (const w of warnings) { logger.warn(`${d.classRef.name}.${d.methodName}: ${w}`) }\n\n return {\n route,\n base: d.classRef.name.replace(/Controller$/, ''),\n description: operation.description,\n baseShape: shape,\n bindings,\n guards: collectGuards(this.reflector, d.classRef, d.method),\n pathFields: pathParamFields(bindings),\n streaming: isAsyncGeneratorFn(d.method)\n }\n }\n\n /** Build a guard-application closure shared by both run shapes. */\n private guardRunner(d: Discovered, shared: Reflected, globalGuards: Type<CanActivate>[]) {\n const { moduleRef, reflector, appConfig } = this\n const { guards, pathFields } = shared\n const { classRef, method } = d\n return async (context: SilkweaveContext, input: object): Promise<void> => {\n // Resolved at call time - `APP_GUARD` instances aren't populated until\n // `app.init()` finishes. Globals run before the route/class guards.\n const all = [...collectGlobalGuards(appConfig, globalGuards), ...guards]\n if (all.length === 0) { return }\n const request = context.getOptional<unknown>('request')\n const response = context.getOptional<unknown>('response') ?? null\n const hasRequest = request != null\n const guardRequest = hasRequest ? request : { headers: {}, params: {}, query: {} }\n populatePathParams(guardRequest, pathFields, input as Record<string, unknown>)\n await runGuards(all, moduleRef, reflector, classRef, method, guardRequest, response, hasRequest ? 'http' : 'rpc')\n }\n }\n\n /** Synthesize the MCP-targeted action (unchanged behavior from v2.4). */\n private mcpAction(d: Discovered, shared: Reflected, globalGuards: Type<CanActivate>[], defaultResult?: 'json' | 'smart'): Action {\n const meta = d.mcp!\n const shape = { ...shared.baseShape, ...inputShape(meta.input) }\n const name = meta.name ?? `${shared.base}.${d.methodName}`\n const description = meta.description ?? shared.description ?? `${d.methodName} (${shared.route.method} /${shared.route.path})`\n const applyParamPipes = meta.pipes !== 'skip'\n const applyGuards = this.guardRunner(d, shared, globalGuards)\n const { method, instance } = d\n const { bindings, streaming } = shared\n\n return {\n name,\n description,\n input: z.object(shape),\n ...((meta.result ?? defaultResult) ? { disposition: meta.result ?? defaultResult } : {}),\n isEnabled: (ctx) => ctx.getOptional<string>('adapter') === 'mcp',\n ...(streaming\n ? { chunk: z.unknown(), run: streamingRun(applyGuards, method, instance, bindings, applyParamPipes, false) }\n : {\n run: async (input: object, context: SilkweaveContext): Promise<object> => {\n await applyGuards(context, input)\n const request = context.getOptional<{ headers?: Record<string, unknown> }>('request')\n const response = context.getOptional<unknown>('response')\n const result = await invokeRebound(method, instance, input as Record<string, unknown>, bindings, request, response, applyParamPipes)\n return result ?? {}\n }\n })\n } as Action\n }\n\n /** Synthesize the tRPC-targeted action (kind/output/subscription + httpStatus errors). */\n private trpcAction(d: Discovered, shared: Reflected, globalGuards: Type<CanActivate>[]): Action {\n const meta = d.trpc!\n const shape = { ...shared.baseShape, ...inputShape(meta.input) }\n const name = meta.name ?? `${shared.base}.${d.methodName}`\n const description = meta.description ?? shared.description ?? `${d.methodName} (${shared.route.method} /${shared.route.path})`\n const applyParamPipes = meta.pipes !== 'skip'\n const applyGuards = this.guardRunner(d, shared, globalGuards)\n const { method, instance } = d\n const { bindings, streaming } = shared\n\n // tRPC and typegen both consume `@Trpc` actions; MCP never does.\n const isEnabled = (ctx: SilkweaveContext): boolean => {\n const adapter = ctx.getOptional<string>('adapter')\n return adapter === 'trpc' || adapter === 'typegen'\n }\n\n if (streaming) {\n return {\n name,\n description,\n input: z.object(shape),\n chunk: resolveSchema(meta.chunk) ?? z.unknown(),\n isEnabled,\n run: streamingRun(applyGuards, method, instance, bindings, applyParamPipes, true)\n } as Action\n }\n\n const kind: ActionKind = meta.kind === 'query' || meta.kind === 'mutation'\n ? meta.kind\n : (shared.route.method === 'GET' ? 'query' : 'mutation')\n const output = resolveOutput(meta, method)\n\n // Reflection is one level deep, so a nested DTO or `Dto[]` output property\n // degrades to `unknown`/`unknown[]`. Surface it - the fix is `@Trpc({ output })`.\n const degraded = outputDegradedFields(meta, method)\n if (output && degraded.length > 0) {\n logger.warn(\n `${d.classRef.name}.${d.methodName}: tRPC output field(s) ${degraded.join(', ')} reflected to 'unknown' ` +\n '(nested DTO or Dto[] - reflection is one level deep). Supply @Trpc({ output }) with a Zod schema for precise types.'\n )\n }\n\n return {\n name,\n description,\n input: z.object(shape),\n ...(output ? { output } : {}),\n kind,\n isEnabled,\n run: async (input: object, context: SilkweaveContext): Promise<object> => {\n try {\n await applyGuards(context, input)\n const request = context.getOptional<{ headers?: Record<string, unknown> }>('request')\n const response = context.getOptional<unknown>('response')\n const result = await invokeRebound(method, instance, input as Record<string, unknown>, bindings, request, response, applyParamPipes)\n return result ?? {}\n } catch (error) {\n throw toSilkweaveError(error)\n }\n }\n } as Action\n }\n}\n\n/** Build a streaming (`async *`) run that applies guards then yields the method's chunks. */\nfunction streamingRun(\n applyGuards: (context: SilkweaveContext, input: object) => Promise<void>,\n method: (...args: unknown[]) => unknown,\n instance: object,\n bindings: Binding[],\n applyParamPipes: boolean,\n mapErrors: boolean\n) {\n return async function* (input: object, context: SilkweaveContext): AsyncGenerator<unknown, void, void> {\n try {\n await applyGuards(context, input)\n const request = context.getOptional<{ headers?: Record<string, unknown> }>('request')\n const response = context.getOptional<unknown>('response')\n const gen = await invokeRebound(method, instance, input as Record<string, unknown>, bindings, request, response, applyParamPipes) as AsyncIterable<unknown>\n for await (const chunk of gen) { yield chunk }\n } catch (error) {\n throw mapErrors ? toSilkweaveError(error) : error\n }\n }\n}\n\n/** Resolve a `@Trpc` action's output schema: explicit override wins over `@ApiOkResponse` reflection. */\nfunction resolveOutput(meta: TrpcMetadata, method: (...args: unknown[]) => unknown): z.ZodType | undefined {\n return resolveSchema(meta.output) ?? reflectResponseSchema(method)\n}\n\n/**\n * Output field names that reflected to `unknown` (nested DTO / `Dto[]`). Only the\n * reflected paths are inspected - an explicit Zod or raw-shape `@Trpc({ output })`\n * is the caller's own typing and is never flagged.\n */\nfunction outputDegradedFields(meta: TrpcMetadata, method: (...args: unknown[]) => unknown): string[] {\n if (meta.output != null && isZodSchema(meta.output)) { return [] }\n const fields = typeof meta.output === 'function'\n ? reflectDtoFields(meta.output)\n : meta.output != null ? undefined : reflectResponseFields(method)\n return fields ? unreflectedFields(fields) : []\n}\n\n/**\n * Normalise an `@Mcp`/`@Trpc({ input })` override to a raw Zod shape. Accepts a\n * plain `Record<string, ZodType>` or a whole `z.object({ ... })` (duck-typed by\n * `safeParse` + `shape`, so a different zod copy's object still unwraps).\n */\nfunction inputShape(input: McpMetadata['input']): Record<string, z.ZodType> {\n if (!input) { return {} }\n const maybe = input as { safeParse?: unknown; shape?: unknown }\n if (typeof maybe.safeParse === 'function' && maybe.shape != null && typeof maybe.shape === 'object') {\n return maybe.shape as Record<string, z.ZodType>\n }\n return input as Record<string, z.ZodType>\n}\n\n/**\n * Coerce an `output`/`chunk` override to a Zod schema: a Zod schema passes\n * through, a DTO class is reflected, and a raw shape is wrapped in `z.object`.\n */\nfunction resolveSchema(value: TrpcMetadata['output']): z.ZodType | undefined {\n if (value == null) { return undefined }\n if (isZodSchema(value)) { return value }\n if (typeof value === 'function') { return reflectDtoSchema(value) }\n return z.object(value)\n}\n\nfunction isZodSchema(value: unknown): value is z.ZodType {\n return Boolean(value) && typeof value === 'object' && typeof (value as { safeParse?: unknown }).safeParse === 'function'\n}\n\nfunction isAsyncGeneratorFn(fn: unknown): boolean {\n return typeof fn === 'function' && (fn as { constructor?: { name?: string } }).constructor?.name === 'AsyncGeneratorFunction'\n}\n\n/**\n * Convert a thrown Nest `HttpException` into a `SilkweaveError` carrying its HTTP\n * status, so the tRPC adapter's `mapError` maps it to the right `TRPCError` code\n * (and `data.httpStatus`) - e.g. a denying `AuthGuard`'s `UnauthorizedException`\n * surfaces to the client as a `401`. Non-HTTP errors pass through unchanged.\n */\nfunction toSilkweaveError(error: unknown): unknown {\n if (error instanceof HttpException) {\n const status = error.getStatus()\n const response = error.getResponse()\n const raw = typeof response === 'string'\n ? response\n : (response as { message?: unknown })?.message ?? error.message\n const message = Array.isArray(raw) ? raw.join(', ') : String(raw)\n return new SilkweaveError(message, 'http_error', status)\n }\n return error\n}\n\n/** Build the merged Zod input shape and the per-argument re-bind plan. */\nfunction buildInput(\n proto: object,\n methodName: string,\n pathParams: string[],\n slots: ReturnType<typeof readParamSlots>,\n operationParams: Record<string, FieldDesc>,\n docFields: Record<string, FieldDesc>\n): BuiltInput {\n const designTypes = (Reflect.getMetadata('design:paramtypes', proto, methodName) as unknown[] | undefined) ?? []\n const fields: Record<string, FieldDesc> = {}\n const warnings: string[] = []\n const maxIndex = slots.reduce((m, s) => Math.max(m, s.index), -1)\n const bindings: Binding[] = Array.from({ length: maxIndex + 1 }, () => ({ kind: 'missing' as const }))\n\n const addField = (name: string, desc: FieldDesc): void => {\n fields[name] = name in fields ? mergeField(fields[name], desc) : desc\n }\n\n for (const slot of slots) {\n const { binding, fields: contributed } = contributeSlot(slot, pathParams, designTypes)\n bindings[slot.index] = binding\n for (const [name, desc] of Object.entries(contributed)) { addField(name, desc) }\n // A whole-DTO `@Body()`/`@Query()` that reflected to zero fields: the type\n // was unreflectable (an interface, or an intersection/union TypeScript\n // erases to `Object`/`Array` under `design:type`). Its fields are silently\n // absent unless declared via `@Mcp`/`@Trpc({ input })`.\n if (binding.kind === 'object' && binding.fields.length === 0) {\n const typeName = (designTypes[slot.index] as { name?: string } | undefined)?.name ?? 'unknown'\n warnings.push(\n `whole-${binding.source} parameter #${slot.index} (type '${typeName}') reflected no input fields. ` +\n `If it is an intersection/union (e.g. 'A & B'), TypeScript erases it to '${typeName}' so the DTO is lost - ` +\n 'use a single DTO class or declare the fields via @Mcp/@Trpc({ input }).'\n )\n }\n }\n\n // Layer operation-level (`@ApiParam`/`@ApiQuery`) then OpenAPI-document\n // metadata over the structural fields (later sources win per field).\n for (const [name, desc] of Object.entries(operationParams)) {\n if (name in fields) { fields[name] = mergeField(fields[name], desc) }\n }\n for (const [name, desc] of Object.entries(docFields)) {\n if (name in fields) { fields[name] = mergeField(fields[name], desc) }\n }\n\n const shape: Record<string, z.ZodType> = {}\n for (const [name, desc] of Object.entries(fields)) { shape[name] = fieldToZod(desc) }\n\n return { shape, bindings, warnings }\n}\n\n/** Input field names that originate from the URL path (`@Param`), per the re-bind plan. */\nfunction pathParamFields(bindings: Binding[]): string[] {\n const fields: string[] = []\n for (const b of bindings) {\n if (b.kind === 'params') { fields.push(...b.fields) } else if (b.kind === 'value' && b.source === 'path') { fields.push(b.field) }\n }\n return fields\n}\n\n/**\n * Fill `request.params` with the reflected path fields from the validated input,\n * matching what Express would populate over REST (raw string values). Only adds\n * keys that are absent, so a real REST request's params are never overwritten.\n */\nfunction populatePathParams(request: unknown, pathFields: string[], input: Record<string, unknown>): void {\n if (pathFields.length === 0 || typeof request !== 'object' || request === null) { return }\n const params = ((request as { params?: Record<string, unknown> }).params ??= {})\n for (const field of pathFields) {\n if (!(field in params) && input[field] !== undefined) {\n params[field] = String(input[field])\n }\n }\n}\n\nfunction designTypeAt(designTypes: unknown[], index: number): FieldDesc {\n const ctor = designTypes[index]\n if (ctor === String) { return { type: 'string' } }\n if (ctor === Number) { return { type: 'number' } }\n if (ctor === Boolean) { return { type: 'boolean' } }\n return {}\n}\n\ninterface SlotContribution {\n binding: Binding\n /** Input fields this slot contributes, keyed by field name. */\n fields: Record<string, FieldDesc>\n}\n\n/** A `@Param('id')` scalar or a bare `@Param()` covering all path params. */\nfunction paramContribution(slot: ParamSlot, pathParams: string[]): SlotContribution {\n if (slot.data) {\n return {\n binding: { kind: 'value', field: slot.data, source: 'path', metatype: slot.designType, pipes: slot.pipes },\n fields: { [slot.data]: { type: 'string', required: true } }\n }\n }\n const fields: Record<string, FieldDesc> = {}\n for (const p of pathParams) { fields[p] = { type: 'string', required: true } }\n return { binding: { kind: 'params', fields: pathParams }, fields }\n}\n\n/** A `@Query('x')`/`@Body('x')` scalar or a whole-DTO `@Query()`/`@Body()`. */\nfunction bodyOrQueryContribution(slot: ParamSlot, source: 'query' | 'body', requiredScalar: boolean, designTypes: unknown[]): SlotContribution {\n if (slot.data) {\n return {\n binding: { kind: 'value', field: slot.data, source, metatype: slot.designType, pipes: slot.pipes },\n fields: { [slot.data]: mergeField(designTypeAt(designTypes, slot.index), { required: requiredScalar }) }\n }\n }\n const dtoFields = reflectDtoFields(slot.designType)\n return {\n binding: { kind: 'object', source, fields: Object.keys(dtoFields), metatype: slot.designType, pipes: slot.pipes },\n fields: dtoFields\n }\n}\n\n/** Map one parameter slot to its input-field contribution and re-bind instruction. */\nfunction contributeSlot(slot: ParamSlot, pathParams: string[], designTypes: unknown[]): SlotContribution {\n switch (slot.paramtype) {\n case PARAMTYPE.PARAM: return paramContribution(slot, pathParams)\n case PARAMTYPE.QUERY: return bodyOrQueryContribution(slot, 'query', false, designTypes)\n case PARAMTYPE.BODY: return bodyOrQueryContribution(slot, 'body', true, designTypes)\n default: return { binding: specialBinding(slot.paramtype, slot.data) ?? { kind: 'missing' }, fields: {} }\n }\n}\n","import type { CanActivate, Type } from '@nestjs/common'\nimport type { HttpAdapterHost } from '@nestjs/core'\nimport type { Action, SilkweaveContext, SilkweaveOptions } from '@silkweave/core'\nimport type { OpenApiDocument } from './reflect/openapi.js'\n\n/**\n * Context passed to a Nest Silkweave adapter when `SilkweaveModule` wires it\n * up. Adapters register their routes directly on `httpAdapter` (no\n * placeholder middleware, no `silkweave()` builder), so they only fire\n * `register()` once and own the rest of their lifecycle implicitly through\n * Nest.\n */\nexport interface NestAdapterRegisterContext {\n /** Nest's underlying HTTP adapter (Express or Fastify). */\n httpAdapter: NonNullable<HttpAdapterHost['httpAdapter']>\n /** Identity the adapter surfaces to clients (e.g. MCP server name). */\n silkweaveOptions: SilkweaveOptions\n /** Per-adapter context - already forked with `{ adapter: adapter.name, ...userContext }`. */\n baseContext: SilkweaveContext\n /** Actions filtered to those enabled on this adapter. */\n actions: Action[]\n}\n\n/**\n * A Silkweave Nest adapter. Each transport (REST, tRPC, MCP) implements this\n * shape. `register()` is called from `SilkweaveModule.configure()` - which\n * runs *before* Nest's controller routes are mapped - so adapter routes\n * always sit ahead of any catch-all controllers in the framework's request\n * pipeline.\n */\nexport interface NestSilkweaveAdapter {\n /** Adapter discriminator - set on the silkweave context as `ctx.get('adapter')`. */\n readonly name: 'mcp' | 'trpc' | 'typegen'\n /** URL prefix the adapter mounts on (e.g. `'/mcp'`). Surfaced for introspection. */\n readonly basePath?: string\n /**\n * When `true`, the adapter receives every discovered action regardless of\n * each action's `isEnabled` gate. Reserved for non-runtime adapters that need\n * the entire action surface.\n */\n readonly allActions?: boolean\n /** Register this adapter's routes on Nest's HTTP server. */\n register(ctx: NestAdapterRegisterContext): void\n}\n\nexport interface SilkweaveModuleOptions {\n /** Identity for the silkweave instance - surfaced to MCP clients, OpenAPI, etc. */\n silkweave: SilkweaveOptions\n /** Adapters to mount - any of `mcp()`, `trpc()`, `typegen()`. */\n adapters: NestSilkweaveAdapter[]\n /** Initial context keys merged into every adapter's `baseContext`. */\n context?: Record<string, unknown>\n /**\n * Optional OpenAPI document (e.g. from `SwaggerModule.createDocument(app, cfg)`)\n * used as an authoritative source when reflecting `@Mcp` tool input schemas.\n * Matched to each method by HTTP verb + path; falls back to decorator\n * reflection when an operation or field isn't present.\n */\n openapi?: OpenApiDocument\n /**\n * Opt-in allow-list of app-global guard classes (registered via\n * `app.useGlobalGuards()` or `{ provide: APP_GUARD, useClass }`) to run on\n * every MCP tool call, before each method/class `@UseGuards`. Listed by\n * class - a blanket \"run all globals\" is deliberately not offered, since\n * unrelated globals (e.g. a `ThrottlerGuard` that needs a writable response)\n * would misbehave over MCP. Empty/omitted ⇒ no global guards run.\n *\n * Note: over MCP the request stand-in is headers-only (`params`/`query` are\n * empty), so per-session or IP-derived guard logic won't apply; header-based\n * authentication still works.\n */\n globalGuards?: Type<CanActivate>[]\n /**\n * Default MCP result format for every `@Mcp` tool - `'json'` (compact JSON,\n * `jsonToolResult`) or `'smart'` (inline small / embedded-resource large,\n * `smartToolResult`). Defaults to `'smart'`. A per-method `@Mcp({ result })`\n * overrides this, and a client's per-call `_meta.disposition` overrides both.\n */\n defaultResult?: 'json' | 'smart'\n}\n\nexport const SILKWEAVE_MODULE_OPTIONS = '__silkweave_module_options__'\n","import { Inject, Module, type DynamicModule, type MiddlewareConsumer, type NestModule } from '@nestjs/common'\nimport { DiscoveryModule, HttpAdapterHost } from '@nestjs/core'\nimport { createContext } from '@silkweave/core'\nimport { ControllerDiscovery } from './controllerDiscovery.js'\nimport { SILKWEAVE_MODULE_OPTIONS, type SilkweaveModuleOptions } from './types.js'\n\n/**\n * Root module for `@silkweave/nestjs`.\n *\n * Discovers every `@Mcp`/`@Trpc`-decorated **controller method** via\n * `DiscoveryService`, reflects each into a Silkweave action (input schema from\n * the route + parameter decorators + optional OpenAPI document; invocation by\n * re-binding the validated input back into the method), and registers the\n * configured adapter(s) - `mcp()`, `trpc()`, `typegen()` - directly on Nest's\n * HTTP adapter inside `configure()`.\n *\n * Because `configure()` runs during `registerModules` - before Nest's\n * `registerRouter()` step - Silkweave's routes always sit ahead of every\n * controller in the Express stack. The controllers keep serving HTTP exactly as\n * before; `@Mcp` is purely additive.\n *\n * @example\n * ```ts\n * @Module({\n * imports: [\n * SilkweaveModule.forRoot({\n * silkweave: { name: 'app', description: 'My App', version: '1.0.0' },\n * adapters: [mcp({ basePath: '/mcp' })]\n * })\n * ],\n * controllers: [ChannelsController]\n * })\n * export class AppModule {}\n * ```\n */\n@Module({})\nexport class SilkweaveModule implements NestModule {\n constructor(\n @Inject(SILKWEAVE_MODULE_OPTIONS) private readonly options: SilkweaveModuleOptions,\n private readonly discovery: ControllerDiscovery,\n private readonly httpAdapterHost: HttpAdapterHost\n ) { }\n\n static forRoot(options: SilkweaveModuleOptions): DynamicModule {\n return {\n module: SilkweaveModule,\n global: true,\n imports: [DiscoveryModule],\n providers: [\n { provide: SILKWEAVE_MODULE_OPTIONS, useValue: options },\n ControllerDiscovery\n ],\n exports: []\n }\n }\n\n configure(_consumer: MiddlewareConsumer): void {\n const httpAdapter = this.httpAdapterHost.httpAdapter\n if (!httpAdapter) {\n throw new Error('@silkweave/nestjs: HttpAdapterHost.httpAdapter is not available.')\n }\n const allActions = this.discovery.discover({\n openapi: this.options.openapi,\n globalGuards: this.options.globalGuards,\n defaultResult: this.options.defaultResult\n })\n for (const adapter of this.options.adapters) {\n const baseContext = createContext({ ...(this.options.context ?? {}), adapter: adapter.name })\n const actions = adapter.allActions\n ? allActions\n : allActions.filter((a) => !a.isEnabled || a.isEnabled(baseContext))\n adapter.register({\n httpAdapter,\n silkweaveOptions: this.options.silkweave,\n baseContext,\n actions\n })\n }\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../src/lib/metadata.ts","../src/decorator/mcp.ts","../src/decorator/trpc.ts","../src/lib/executionContext.ts","../src/lib/guards.ts","../src/lib/reflect/params.ts","../src/lib/rebind.ts","../src/lib/requestSlots.ts","../src/lib/reflect/classValidator.ts","../src/lib/reflect/schema.ts","../src/lib/reflect/openapi.ts","../src/lib/reflect/response.ts","../src/lib/reflect/route.ts","../src/lib/reflect/swagger.ts","../src/lib/controllerDiscovery.ts","../src/lib/types.ts","../src/lib/silkweave.module.ts"],"sourcesContent":["import type { Type } from '@nestjs/common'\nimport type { z } from 'zod/v4'\n\n/** Reflect-metadata key carrying `@Mcp` options on a controller method. */\nexport const MCP_METADATA = '__silkweave_mcp__'\n\n/** Reflect-metadata key carrying `@Trpc` options on a controller method. */\nexport const TRPC_METADATA = '__silkweave_trpc__'\n\n/**\n * Options for the `@Mcp()` method decorator. Every field is optional - an empty\n * `@Mcp()` exposes the decorated controller route as an MCP tool with its name,\n * description, and input schema fully reflected from the method's route\n * (`@Get`/`@Post`/...), parameter decorators (`@Param`/`@Query`/`@Body`), and\n * any `@nestjs/swagger` (`@ApiOperation`/`@ApiParam`/`@ApiProperty`) or\n * `class-validator` metadata it carries.\n */\nexport interface McpMetadata {\n /**\n * MCP tool name override. When unset it is derived from the controller class\n * and method name (e.g. `ChannelsController.findOne` → `ChannelsFindOne`).\n */\n name?: string\n /**\n * Tool description override. When unset it falls back to the method's\n * `@ApiOperation({ summary | description })`, then a generated default.\n */\n description?: string\n /**\n * Zod override merged over the reflected input fields (override wins per\n * field). Accepts either a raw shape (`{ field: z.string() }`) or a whole\n * `z.object({ ... })` - the object's `.shape` is unwrapped. The escape hatch\n * for shapes reflection can't express losslessly - discriminated unions,\n * custom validators, `@Transform`, etc. Note it *adds to* the reflected\n * fields; it does not replace them, so a field reflection silently dropped\n * (see the unreflectable-param warning) is not recovered by listing the\n * others here.\n */\n input?: Record<string, z.ZodType> | z.ZodObject\n /**\n * Whether to apply the controller method's parameter-bound pipes\n * (`@Param('id', ParseIntPipe)`) when re-binding the call. Default `'apply'`.\n * Global/`ValidationPipe`, interceptors, and exception filters never run -\n * the method is invoked directly, not through Nest's HTTP request pipeline.\n */\n pipes?: 'apply' | 'skip'\n /**\n * Default MCP result format for this tool. `'json'` returns compact JSON text\n * (`jsonToolResult`); `'smart'` (the default when unset) inlines small\n * payloads and offloads large ones to an embedded resource (`smartToolResult`).\n * This is only a default - a client that sends `_meta.disposition` on the tool\n * call overrides it.\n */\n result?: 'json' | 'smart'\n}\n\n/** tRPC procedure kind for a `@Trpc`-decorated route. */\nexport type TrpcKind = 'query' | 'mutation' | 'subscription'\n\n/**\n * Options for the `@Trpc()` method decorator - the tRPC sibling of `@Mcp`. An\n * empty `@Trpc()` exposes the decorated controller route as a tRPC procedure\n * with its key, input schema, and kind reflected from the route + parameter\n * decorators + swagger/class-validator metadata (identically to `@Mcp`).\n *\n * Unlike MCP, tRPC carries precise *output* types into the generated router, so\n * `@Trpc` adds an `output`/`chunk` hatch and a `kind` override on top of the\n * shared reflection. The two decorators compose on the same method.\n */\nexport interface TrpcMetadata {\n /**\n * Procedure-name override (before camelCasing). When unset it is derived from\n * the controller class + method name (e.g. `UsersController.listBySpace` →\n * `Users.listBySpace`, camelCased by the router to `usersListBySpace`).\n */\n name?: string\n /**\n * Procedure description override. When unset it falls back to the method's\n * `@ApiOperation({ summary | description })`, then a generated default.\n */\n description?: string\n /**\n * Zod override merged over the reflected input fields (override wins per\n * field). Accepts a raw shape (`{ field: z.string() }`) or a whole\n * `z.object({ ... })` (its `.shape` is unwrapped). Same escape hatch as\n * `@Mcp({ input })`.\n */\n input?: Record<string, z.ZodType> | z.ZodObject\n /**\n * Explicit output schema driving the generated procedure's output type - a Zod\n * type, a DTO class (reflected like `@ApiOkResponse`), or a raw shape (wrapped\n * in `z.object`). Wins over `@ApiOkResponse` reflection. The biggest reason to\n * set this is when the return shape can't be reflected losslessly from a DTO.\n */\n output?: z.ZodType | Type | Record<string, z.ZodType>\n /**\n * Chunk schema for an async-generator route exposed as a tRPC **subscription**.\n * A Zod type or a DTO class. Drives the emitted\n * `TRPCSubscriptionProcedure<{ output }>` type. When unset the chunk type falls\n * back to `unknown`.\n */\n chunk?: z.ZodType | Type\n /**\n * Procedure kind. When unset it is inferred: an `async *` route ⇒\n * `'subscription'`, a `@Get` route ⇒ `'query'`, anything else ⇒ `'mutation'`.\n * Set this to expose a verb-less route (no `@Get`/`@Post`) as a query or\n * subscription - `@Trpc({ kind })` works without an HTTP-verb decorator, so the\n * route is served over tRPC (and/or MCP) without becoming a public REST route.\n */\n kind?: TrpcKind\n /**\n * Whether to apply the method's parameter-bound pipes when re-binding the call.\n * Default `'apply'`. Same semantics as `@Mcp({ pipes })`.\n */\n pipes?: 'apply' | 'skip'\n}\n","import { SetMetadata } from '@nestjs/common'\nimport { MCP_METADATA, type McpMetadata } from '../lib/metadata.js'\n\n/**\n * Method decorator that exposes an existing NestJS controller route as an MCP\n * tool. It is **additive** - the route keeps serving HTTP exactly as before;\n * `@Mcp()` just opts the method into MCP discovery.\n *\n * The tool's name, description, and input schema are reflected from the\n * method's own metadata:\n * - **fields** from the parameter decorators (`@Param`/`@Query`/`@Body`) - a\n * `@Param('id')` becomes an `id` field; a whole-DTO `@Body() dto: CreateDto`\n * is flattened to its properties,\n * - **types/constraints/descriptions** from `@nestjs/swagger`\n * (`@ApiParam`/`@ApiQuery`/`@ApiProperty`/`@ApiOperation`) and, when present,\n * `class-validator` decorators on the DTOs,\n * - optionally refined by an OpenAPI document passed to `SilkweaveModule`.\n *\n * On a tool call the input is split back into the method's positional arguments\n * and the method is invoked directly (with `@UseGuards` guards applied first).\n *\n * @example\n * ```ts\n * @Controller('sessions/:sessionId/channels')\n * export class ChannelsController {\n * @Get(':channelId')\n * @ApiOperation({ summary: 'Get a specific channel by ID' })\n * @ApiParam({ name: 'sessionId', description: 'Session ID' })\n * @ApiParam({ name: 'channelId', description: 'Channel ID' })\n * @Mcp()\n * findOne(@Param('sessionId') sessionId: string, @Param('channelId') channelId: string) {\n * return this.service.get(sessionId, channelId)\n * }\n * }\n * ```\n */\nexport function Mcp(options: McpMetadata = {}): MethodDecorator {\n return SetMetadata(MCP_METADATA, options)\n}\n","import { SetMetadata } from '@nestjs/common'\nimport { TRPC_METADATA, type TrpcMetadata } from '../lib/metadata.js'\n\n/**\n * Method decorator that exposes a NestJS controller route as a **tRPC\n * procedure** - the sibling of `@Mcp`. Like `@Mcp` it is additive and reflects\n * the procedure's input from the method's own metadata (route + `@Param`/\n * `@Query`/`@Body` + swagger/class-validator), so a single method can carry both\n * `@Trpc()` and `@Mcp()` and `@UseGuards()`.\n *\n * Two things differ from MCP because tRPC consumers need them:\n * - **kind** - inferred from the route (`@Get` ⇒ query, others ⇒ mutation) or an\n * `async *` body (⇒ subscription); override with `@Trpc({ kind })`.\n * - **output** - the generated `AppRouter` carries precise output types. Drive\n * them with `@ApiOkResponse({ type: Dto })` reflection or `@Trpc({ output })`.\n *\n * `@Trpc()` works **without** an HTTP-verb decorator: with no `@Get`/`@Post` the\n * route is never mapped as REST, so `@Trpc({ kind })` exposes it over tRPC (and\n * `@Mcp` over MCP) while keeping it off the public REST surface.\n *\n * @example\n * ```ts\n * @Controller('users')\n * export class UsersController {\n * @Get('list-by-space')\n * @ApiOperation({ summary: 'List users in a space' })\n * @ApiOkResponse({ type: ListUsersResponse }) // drives the output type\n * @UseGuards(AuthGuard)\n * @Trpc() // → procedure `usersListBySpace` (query)\n * @Mcp() // → MCP tool `UsersListBySpace`\n * listBySpace(@Query() q: ListBySpaceQuery, @Req() req: AppRequest) {\n * return this.service.list(req.user, q.spaceId)\n * }\n * }\n * ```\n */\nexport function Trpc(options: TrpcMetadata = {}): MethodDecorator {\n return SetMetadata(TRPC_METADATA, options)\n}\n","import type { ArgumentsHost, ContextType, ExecutionContext, Type } from '@nestjs/common'\n\n/** Subset of `HttpArgumentsHost` we need - re-declared inline to avoid deep `@nestjs/common/interfaces` imports. */\ninterface HttpHost {\n getRequest<T = unknown>(): T\n getResponse<T = unknown>(): T\n getNext<T = unknown>(): T\n}\n\ninterface RpcHost {\n getData<T = unknown>(): T\n getContext<T = unknown>(): T\n}\n\ninterface WsHost {\n getClient<T = unknown>(): T\n getData<T = unknown>(): T\n getPattern(): string\n}\n\n/**\n * Minimal `ExecutionContext` impl Nest guards can consume. We only need\n * `switchToHttp()` to work for our HTTP-backed transports; the RPC/WS shims are\n * stubbed so guards that introspect type can still call them without crashing.\n */\nexport class SilkweaveExecutionContext implements ExecutionContext, ArgumentsHost {\n constructor(\n private readonly args: unknown[],\n private readonly classRef: Type<unknown>,\n private readonly handler: (...handlerArgs: unknown[]) => unknown,\n private readonly contextType = 'http'\n ) { }\n\n getType<T extends string = ContextType>(): T {\n return this.contextType as T\n }\n\n getClass<T = unknown>(): Type<T> {\n return this.classRef as Type<T>\n }\n\n getHandler(): (...handlerArgs: unknown[]) => unknown {\n return this.handler\n }\n\n getArgs<T extends unknown[] = unknown[]>(): T {\n return this.args as T\n }\n\n getArgByIndex<T = unknown>(index: number): T {\n return this.args[index] as T\n }\n\n switchToHttp(): HttpHost {\n return {\n getRequest: <T = unknown>(): T => this.args[0] as T,\n getResponse: <T = unknown>(): T => this.args[1] as T,\n getNext: <T = unknown>(): T => this.args[2] as T\n }\n }\n\n switchToRpc(): RpcHost {\n return {\n getData: <T = unknown>(): T => this.args[0] as T,\n getContext: <T = unknown>(): T => this.args[1] as T\n }\n }\n\n switchToWs(): WsHost {\n return {\n getClient: <T = unknown>(): T => this.args[0] as T,\n getData: <T = unknown>(): T => this.args[1] as T,\n getPattern: (): string => ''\n }\n }\n}\n","import { ForbiddenException, type CanActivate, type Type } from '@nestjs/common'\nimport { GUARDS_METADATA } from '@nestjs/common/constants.js'\nimport { ApplicationConfig, ModuleRef, Reflector } from '@nestjs/core'\nimport { isObservable, lastValueFrom } from 'rxjs'\nimport { SilkweaveExecutionContext } from './executionContext.js'\n\ntype GuardRef = Type<CanActivate> | CanActivate\n\n/**\n * Collect the app's global guards that match an opt-in allow-list of classes.\n *\n * Reads both registration styles Nest exposes via `ApplicationConfig`:\n * `useGlobalGuards(new X())` instances (`getGlobalGuards()`) and\n * `{ provide: APP_GUARD, useClass }` DI guards (`getGlobalRequestGuards()`,\n * which yields `InstanceWrapper`s - we read `.instance` off each).\n *\n * The allow-list is intentionally explicit-by-class: a blanket \"run every\n * global\" would also fire unrelated globals (e.g. a `ThrottlerGuard` that\n * assumes a writable response) on every tool call. An empty allow-list runs\n * no globals, preserving the prior behavior.\n *\n * Call this at tool-call time, not at discovery time: `APP_GUARD` instances\n * aren't populated until `app.init()` finishes.\n */\nexport function collectGlobalGuards(\n appConfig: ApplicationConfig,\n allowList: Type<CanActivate>[]\n): CanActivate[] {\n if (allowList.length === 0) { return [] }\n const globals: CanActivate[] = [\n ...appConfig.getGlobalGuards(),\n ...appConfig.getGlobalRequestGuards().map((w) => w.instance)\n ].filter((g): g is CanActivate => g != null)\n return globals.filter((g) => allowList.some((c) => g instanceof c))\n}\n\n/**\n * Read `@UseGuards(...)` metadata for both the method and its class and merge\n * the two lists. Method-level guards run AFTER class-level guards (matching\n * Nest's own behavior).\n */\nexport function collectGuards(\n reflector: Reflector,\n classRef: Type<unknown>,\n handler: (...args: unknown[]) => unknown\n): GuardRef[] {\n const classGuards = reflector.get<GuardRef[]>(GUARDS_METADATA, classRef) ?? []\n const methodGuards = reflector.get<GuardRef[]>(GUARDS_METADATA, handler) ?? []\n return [...classGuards, ...methodGuards]\n}\n\nasync function resolveGuard(ref: GuardRef, moduleRef: ModuleRef): Promise<CanActivate> {\n if (typeof ref === 'function') {\n try {\n return await moduleRef.get(ref, { strict: false })\n } catch {\n return moduleRef.create(ref)\n }\n }\n return ref\n}\n\n/**\n * Run the configured guards against a request. Throws `ForbiddenException`\n * if any guard rejects, mirroring Nest's HTTP request-pipeline behavior.\n *\n * Pass `null` for `response` when running on top of a tRPC or MCP request that\n * doesn't surface a raw response object; guards that introspect the response\n * will receive `null`.\n *\n * `contextType` is reflected through `ExecutionContext.getType()` so guards can\n * branch on the transport. It is `'http'` for REST/tRPC and for MCP-over-HTTP\n * (where a header-bearing request stand-in is available); transports without any\n * HTTP request (e.g. MCP stdio) pass `'rpc'`.\n */\nexport async function runGuards(\n guards: GuardRef[],\n moduleRef: ModuleRef,\n reflector: Reflector,\n classRef: Type<unknown>,\n handler: (...args: unknown[]) => unknown,\n request: unknown,\n response: unknown,\n contextType: 'http' | 'rpc' = 'http'\n): Promise<void> {\n if (guards.length === 0) { return }\n const context = new SilkweaveExecutionContext([request, response], classRef, handler, contextType)\n for (const ref of guards) {\n const guard = await resolveGuard(ref, moduleRef)\n const result = guard.canActivate(context)\n const allowed = isObservable(result) ? await lastValueFrom(result) : await Promise.resolve(result)\n if (!allowed) {\n throw new ForbiddenException('Forbidden resource')\n }\n }\n // Reflector kept in the signature for future use (e.g., per-guard metadata) - unused here.\n void reflector\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { ROUTE_ARGS_METADATA } from '@nestjs/common/constants.js'\n\n/**\n * `RouteParamtypes` numeric values from `@nestjs/common` (re-declared to avoid a\n * value import of an internal enum). These are how `@Param`/`@Query`/`@Body`/...\n * tag each handler argument in `ROUTE_ARGS_METADATA`.\n */\nexport const PARAMTYPE = {\n REQUEST: 0,\n RESPONSE: 1,\n NEXT: 2,\n BODY: 3,\n QUERY: 4,\n PARAM: 5,\n HEADERS: 6,\n SESSION: 7,\n FILE: 8,\n FILES: 9,\n HOST: 10,\n IP: 11,\n RAW_BODY: 12\n} as const\n\nexport interface ParamSlot {\n /** `PARAMTYPE` value - which decorator tagged this argument. */\n paramtype: number\n /** Handler argument position. */\n index: number\n /** Decorator sub-key: `@Param('id')` → `'id'`; a bare `@Body()` → `undefined`. */\n data?: string\n /** Parameter-bound pipes (`@Param('id', ParseIntPipe)`). */\n pipes: unknown[]\n /** TypeScript-emitted constructor at this position (e.g. `String`, `CreateDto`). */\n designType?: unknown\n}\n\n/**\n * Read and normalise the route-argument metadata for a controller method.\n * Returns one {@link ParamSlot} per decorated handler argument, sorted by\n * argument index.\n */\nexport function readParamSlots(classRef: any, methodName: string, proto: any): ParamSlot[] {\n const raw = Reflect.getMetadata(ROUTE_ARGS_METADATA, classRef, methodName) as\n Record<string, { index: number; data?: unknown; pipes?: unknown[] }> | undefined\n if (!raw) { return [] }\n const designTypes = (Reflect.getMetadata('design:paramtypes', proto, methodName) as unknown[] | undefined) ?? []\n\n const slots: ParamSlot[] = []\n for (const key of Object.keys(raw)) {\n const entry = raw[key]\n const paramtype = Number(key.split(':')[0])\n if (Number.isNaN(paramtype)) { continue }\n slots.push({\n paramtype,\n index: entry.index,\n data: typeof entry.data === 'string' ? entry.data : undefined,\n pipes: entry.pipes ?? [],\n designType: designTypes[entry.index]\n })\n }\n return slots.sort((a, b) => a.index - b.index)\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment */\nimport { PARAMTYPE } from './reflect/params.js'\n\n/**\n * Instruction for reconstructing one positional handler argument from the flat\n * MCP tool input. Built at discovery time, consumed by {@link invokeRebound}.\n */\nexport type Binding =\n | { kind: 'value'; field: string; source: 'path' | 'query' | 'body'; metatype?: unknown; pipes?: unknown[] }\n | { kind: 'object'; source: 'query' | 'body'; fields: string[]; metatype?: unknown; pipes?: unknown[] }\n | { kind: 'params'; fields: string[] }\n | { kind: 'request' }\n | { kind: 'response' }\n | { kind: 'headers'; data?: string }\n | { kind: 'ip' }\n | { kind: 'host'; data?: string }\n | { kind: 'missing' }\n\ninterface RequestLike {\n headers?: Record<string, unknown>\n ip?: unknown\n hosts?: Record<string, unknown>\n}\n\nfunction newInstance(P: any): any | null {\n try { return new P() } catch { return null }\n}\n\nasync function applyPipes(value: unknown, pipes: unknown[] | undefined, metatype: unknown, type: 'param' | 'query' | 'body', data: string | undefined): Promise<unknown> {\n if (!pipes || pipes.length === 0) { return value }\n let current = value\n for (const p of pipes) {\n const pipe = typeof p === 'function' ? newInstance(p) : p\n if (pipe && typeof (pipe).transform === 'function') {\n current = await (pipe).transform(current, { type, metatype, data })\n }\n }\n return current\n}\n\n/** Pick a subset of keys (skipping `undefined`) into a fresh object. */\nfunction pickFields(input: Record<string, unknown>, fields: string[]): Record<string, unknown> {\n const obj: Record<string, unknown> = {}\n for (const f of fields) {\n if (input[f] !== undefined) { obj[f] = input[f] }\n }\n return obj\n}\n\n/** Resolve a single positional argument from one binding. */\nasync function resolveArg(\n b: Binding,\n input: Record<string, unknown>,\n request: RequestLike | undefined,\n response: unknown,\n applyParamPipes: boolean\n): Promise<unknown> {\n switch (b.kind) {\n case 'value': {\n const raw = input[b.field]\n const type = b.source === 'path' ? 'param' : b.source\n return applyParamPipes ? applyPipes(raw, b.pipes, b.metatype, type, b.field) : raw\n }\n case 'object': {\n const obj = pickFields(input, b.fields)\n return applyParamPipes ? applyPipes(obj, b.pipes, b.metatype, b.source, undefined) : obj\n }\n case 'params':\n return pickFields(input, b.fields)\n case 'headers':\n return b.data ? request?.headers?.[b.data.toLowerCase()] : (request?.headers ?? {})\n case 'request':\n return request ?? { headers: {} }\n case 'response':\n // The real Express response over tRPC (so `@Res({ passthrough: true })`\n // can set cookies/headers); `undefined` over MCP (no HTTP response).\n return response\n case 'ip':\n return request?.ip\n case 'host':\n return b.data ? request?.hosts?.[b.data] : request?.hosts\n default:\n return undefined\n }\n}\n\n/**\n * Reconstruct the controller method's positional arguments from the validated\n * tool `input` (and the request stand-in for `@Req`/`@Headers`/...), then call\n * it. `applyParamPipes` controls whether parameter-bound pipes run.\n */\nexport async function invokeRebound(\n method: (...args: any[]) => any,\n instance: object,\n input: Record<string, unknown>,\n bindings: Binding[],\n request: RequestLike | undefined,\n response: unknown,\n applyParamPipes: boolean\n): Promise<unknown> {\n const args: unknown[] = []\n for (let i = 0; i < bindings.length; i += 1) {\n args[i] = await resolveArg(bindings[i], input, request, response, applyParamPipes)\n }\n return await method.apply(instance, args)\n}\n\n/** Map a non-input parameter slot (`@Req`/`@Headers`/`@Ip`/...) to its runtime binding. */\nexport function specialBinding(paramtype: number, data: string | undefined): Binding | null {\n switch (paramtype) {\n case PARAMTYPE.REQUEST: return { kind: 'request' }\n case PARAMTYPE.RESPONSE:\n case PARAMTYPE.NEXT: return { kind: 'response' }\n case PARAMTYPE.HEADERS: return { kind: 'headers', data }\n case PARAMTYPE.IP: return { kind: 'ip' }\n case PARAMTYPE.HOST: return { kind: 'host', data }\n case PARAMTYPE.SESSION:\n case PARAMTYPE.FILE:\n case PARAMTYPE.FILES:\n case PARAMTYPE.RAW_BODY: return { kind: 'missing' }\n default: return null\n }\n}\n","import type { Binding } from './rebind.js'\n\n/**\n * Request-slot reconstruction: route the validated tool input back into the\n * `request.params`/`query`/`body` slots Express would populate over REST, so a\n * host guard reading any of them decides identically over MCP and REST. Kept in\n * its own module (not re-exported from the package root) so these helpers stay\n * internal while remaining unit-testable.\n */\n\n/** Input field names grouped by the REST request slot Express would source them from. */\nexport interface RequestSlots {\n /** `@Param`/path-template fields -> `request.params` (raw strings). */\n params: string[]\n /** `@Query` fields -> `request.query` (raw strings). */\n query: string[]\n /** `@Body` fields -> `request.body` (parsed values). */\n body: string[]\n}\n\n/**\n * Classify every input field by the REST request slot it would occupy, reading\n * the discovery-time {@link Binding}s. A whole-DTO `@Query()`/`@Body()` (`object`\n * binding) contributes all its fields to the matching slot; a bare `@Param()`\n * (`params` binding) and a path-sourced `value` go to `params`.\n */\nexport function requestSlotFields(bindings: Binding[]): RequestSlots {\n const slots: RequestSlots = { params: [], query: [], body: [] }\n for (const b of bindings) {\n if (b.kind === 'params') { slots.params.push(...b.fields) } else if (b.kind === 'object') { slots[b.source].push(...b.fields) } else if (b.kind === 'value') { slots[b.source === 'path' ? 'params' : b.source].push(b.field) }\n }\n return slots\n}\n\n/** Fill one request slot from the validated input, only adding absent keys. */\nfunction fillSlot(bag: Record<string, unknown>, fields: string[], input: Record<string, unknown>, stringify: boolean): void {\n for (const field of fields) {\n if (!(field in bag) && input[field] !== undefined) {\n bag[field] = stringify ? String(input[field]) : input[field]\n }\n }\n}\n\n/**\n * Fill `request.params`/`query`/`body` from the validated input, mirroring the\n * slots Express would populate over REST (path -> `params`, `@Query` -> `query`,\n * `@Body` -> `body`). Path/query values are stringified to match how Express\n * delivers them (a guard reading `req.query.limit` sees `'10'`, not `10`); body\n * keeps the parsed values. Only absent keys are added, so a real REST/tRPC\n * request's own params/query/body are never overwritten. This is what lets a\n * scope-enforcing guard (`req.params.sessionId`, `req.body.sessionId`, ...)\n * decide identically over MCP and REST.\n */\nexport function populateRequestSlots(request: unknown, slots: RequestSlots, input: Record<string, unknown>): void {\n if (typeof request !== 'object' || request === null) { return }\n const req = request as { params?: Record<string, unknown>; query?: Record<string, unknown>; body?: Record<string, unknown> }\n if (slots.params.length > 0) { fillSlot((req.params ??= {}), slots.params, input, true) }\n if (slots.query.length > 0) { fillSlot((req.query ??= {}), slots.query, input, true) }\n if (slots.body.length > 0) { fillSlot((req.body ??= {}), slots.body, input, false) }\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment */\nimport { createRequire } from 'node:module'\nimport { join } from 'node:path'\n\nlet cached: any | null | undefined\n\n/**\n * Lazily resolve the optional `class-validator` peer; `null` when not installed.\n * Resolution is attempted both from this package and from the app's working\n * directory - the latter is what finds it in a pnpm install where the optional\n * peer lives in the consumer app rather than alongside `@silkweave/nestjs`. A\n * pnpm-deduped install shares one physical copy, so the metadata singleton the\n * app's decorators wrote to is the same one we read.\n */\nfunction loadClassValidator(): any | null {\n if (cached !== undefined) { return cached }\n for (const base of [import.meta.url, join(process.cwd(), 'noop.js')]) {\n try {\n cached = createRequire(base)('class-validator')\n return cached\n } catch { /* try the next resolution base */ }\n }\n cached = null\n return cached\n}\n\nexport interface ValidationMeta {\n /** `ValidationTypes` discriminator (e.g. `customValidation`, `conditionalValidation`). */\n type?: string\n /** Validator name - the actionable identity for built-ins (`isString`, `minLength`, ...). */\n name?: string\n constraints?: unknown[]\n}\n\n/**\n * Read `class-validator` metadata for a DTO class, grouped by property name.\n * Returns an empty map when `class-validator` is not installed or the class\n * carries no validation decorators - so callers degrade gracefully to swagger /\n * `design:type` reflection.\n */\nexport function classValidatorMetas(dtoType: any): Record<string, ValidationMeta[]> {\n const cv = loadClassValidator()\n if (!cv?.getMetadataStorage) { return {} }\n let metas: Array<{ propertyName?: string; type?: string; name?: string; constraints?: unknown[] }>\n try {\n metas = cv.getMetadataStorage().getTargetValidationMetadatas(dtoType, null, false, false)\n } catch {\n return {}\n }\n const out: Record<string, ValidationMeta[]> = {}\n for (const m of metas) {\n if (!m.propertyName) { continue }\n (out[m.propertyName] ??= []).push({ type: m.type, name: m.name, constraints: m.constraints })\n }\n return out\n}\n","/* eslint-disable @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-explicit-any */\nimport { z } from 'zod/v4'\nimport { classValidatorMetas } from './classValidator.js'\n\n/** `@nestjs/swagger` reflect-metadata keys. Read directly so swagger stays an optional peer. */\nconst API_MODEL_PROPERTIES = 'swagger/apiModelProperties'\nconst API_MODEL_PROPERTIES_ARRAY = 'swagger/apiModelPropertiesArray'\n\n/**\n * A transport-neutral description of a single input field. Every metadata\n * source (swagger decorators, class-validator, an OpenAPI document, TypeScript\n * `design:type`) is mapped to this shape, the shapes are merged by precedence,\n * and the result is converted to Zod once. Keeping a single intermediate keeps\n * the per-source mappers small and the Zod construction in one place.\n */\nexport interface FieldDesc {\n type?: 'string' | 'number' | 'integer' | 'boolean' | 'array' | 'object' | 'unknown'\n required?: boolean\n /** Field accepts `null` (`@ApiProperty({ nullable: true })` / OpenAPI `nullable`). */\n nullable?: boolean\n description?: string\n enum?: (string | number)[]\n items?: FieldDesc\n min?: number\n max?: number\n minLength?: number\n maxLength?: number\n format?: string\n default?: unknown\n}\n\n/** Strip `undefined` values so a later source never clobbers an earlier one with a hole. */\nfunction defined<T extends object>(obj: T): Partial<T> {\n const out: Record<string, unknown> = {}\n for (const [k, v] of Object.entries(obj)) {\n if (v !== undefined) { out[k] = v }\n }\n return out as Partial<T>\n}\n\n/** Merge `over` onto `base` - defined keys of `over` win. */\nexport function mergeField(base: FieldDesc, over: FieldDesc): FieldDesc {\n return { ...base, ...defined(over) }\n}\n\nfunction enumToZod(values: (string | number)[]): z.ZodType {\n const strings = values.filter((v): v is string => typeof v === 'string')\n if (strings.length === values.length && strings.length > 0) {\n return z.enum(strings as [string, ...string[]])\n }\n const literals = values.map((v) => z.literal(v))\n if (literals.length === 0) { return z.unknown() }\n if (literals.length === 1) { return literals[0] }\n return z.union(literals as unknown as [z.ZodType, z.ZodType, ...z.ZodType[]])\n}\n\nfunction baseToZod(d: FieldDesc): z.ZodType {\n switch (d.type) {\n case 'string': {\n let s = z.string()\n if (d.minLength != null) { s = s.min(d.minLength) }\n if (d.maxLength != null) { s = s.max(d.maxLength) }\n return s\n }\n case 'integer':\n case 'number': {\n let n = z.number()\n if (d.type === 'integer') { n = n.int() }\n if (d.min != null) { n = n.min(d.min) }\n if (d.max != null) { n = n.max(d.max) }\n return n\n }\n case 'boolean':\n return z.boolean()\n case 'array':\n return z.array(d.items ? fieldToZod({ ...d.items, required: true }) : z.unknown())\n case 'object':\n return z.record(z.string(), z.unknown())\n default:\n return z.unknown()\n }\n}\n\n/** Convert a merged {@link FieldDesc} to a Zod schema. */\nexport function fieldToZod(d: FieldDesc): z.ZodType {\n let schema = (d.enum?.length) ? enumToZod(d.enum) : baseToZod(d)\n if (d.description) { schema = schema.describe(d.description) }\n if (d.nullable) { schema = schema.nullable() }\n if (d.default !== undefined) {\n schema = (schema as any).default(d.default)\n } else if (d.required === false) {\n schema = schema.optional()\n }\n return schema\n}\n\n// --- per-source mappers ---------------------------------------------------\n\n/** Normalise a TS-enum object or an array literal to a flat value list. */\nexport function normalizeEnum(value: unknown): (string | number)[] | undefined {\n if (Array.isArray(value)) {\n return value.filter((v): v is string | number => typeof v === 'string' || typeof v === 'number')\n }\n if (value && typeof value === 'object') {\n return Object.values(value).filter((v): v is string | number => typeof v === 'string' || typeof v === 'number')\n }\n return undefined\n}\n\n/** Map a swagger/`design:type` type token (constructor, `[Type]`, or string) to a base type. */\nexport function typeTokenToBase(type: unknown): FieldDesc['type'] | undefined {\n if (type == null) { return undefined }\n if (type === String) { return 'string' }\n if (type === Number) { return 'number' }\n if (type === Boolean) { return 'boolean' }\n if (type === Array) { return 'array' }\n if (type === Date) { return 'string' }\n if (Array.isArray(type)) { return 'array' }\n if (typeof type === 'string') {\n const t = type.toLowerCase()\n if (t === 'string' || t === 'number' || t === 'integer' || t === 'boolean' || t === 'array' || t === 'object') {\n return t\n }\n }\n return undefined\n}\n\n/** From the constructor TypeScript emits via `emitDecoratorMetadata`. */\nexport function designTypeToField(ctor: unknown): FieldDesc {\n const type = typeTokenToBase(ctor)\n const f: FieldDesc = {}\n if (type) { f.type = type }\n return f\n}\n\n/** From an `@ApiParam`/`@ApiQuery` entry stored under `swagger/apiParameters`. */\nexport function swaggerParamToField(p: Record<string, any>): FieldDesc {\n const f: FieldDesc = {}\n if (p['description']) { f.description = p['description'] }\n if (typeof p['required'] === 'boolean') { f.required = p['required'] }\n const type = typeTokenToBase(p['type'])\n if (type) { f.type = type }\n if (p['isArray']) { f.type = 'array' }\n const en = normalizeEnum(p['enum'])\n if (en) { f.enum = en }\n if (p['schema'] && typeof p['schema'] === 'object') {\n return mergeField(f, openapiSchemaToField(p['schema']))\n }\n return f\n}\n\n/** From an `@ApiProperty` options object stored under `swagger/apiModelProperties`. */\nexport function apiPropertyToField(o: Record<string, any>): FieldDesc {\n const f: FieldDesc = {}\n if (o['description']) { f.description = o['description'] }\n if (typeof o['required'] === 'boolean') { f.required = o['required'] }\n const type = typeTokenToBase(o['type'])\n if (type) { f.type = type }\n if (o['isArray']) {\n f.items = { type: type && type !== 'array' ? type : 'unknown' }\n f.type = 'array'\n }\n const en = normalizeEnum(o['enum'])\n if (en) { f.enum = en }\n if (o['minimum'] != null) { f.min = o['minimum'] }\n if (o['maximum'] != null) { f.max = o['maximum'] }\n if (o['minLength'] != null) { f.minLength = o['minLength'] }\n if (o['maxLength'] != null) { f.maxLength = o['maxLength'] }\n if (o['format']) { f.format = o['format'] }\n if (o['nullable'] === true) { f.nullable = true }\n if (o['default'] !== undefined) { f.default = o['default'] }\n return f\n}\n\n/** `class-validator` decorator type → field base type. */\nconst CV_TYPE: Record<string, FieldDesc['type']> = {\n isString: 'string',\n isInt: 'integer',\n isBoolean: 'boolean',\n isArray: 'array'\n}\n\n/** `class-validator` decorator type → numeric-constraint field key. */\nconst CV_NUMERIC: Record<string, 'min' | 'max' | 'minLength' | 'maxLength'> = {\n min: 'min',\n max: 'max',\n minLength: 'minLength',\n maxLength: 'maxLength'\n}\n\n/**\n * Fold one `class-validator` metadata entry into the field descriptor. Built-in\n * validators record their identity in `name` (`isString`, `minLength`, ...) with\n * `type: 'customValidation'`; `@IsOptional` uses `name: 'isOptional'`. We key off\n * `name`, falling back to `type`.\n */\nfunction applyValidationMeta(f: FieldDesc, meta: { type?: string; name?: string; constraints?: unknown[] }): void {\n const key = meta.name ?? meta.type\n if (!key) { return }\n if (key in CV_TYPE) { f.type = CV_TYPE[key]; return }\n const c0 = meta.constraints?.[0]\n if (key in CV_NUMERIC) {\n if (typeof c0 === 'number') { f[CV_NUMERIC[key]] = c0 }\n return\n }\n if (key === 'isNumber') { if (!f.type) { f.type = 'number' } return }\n if (key === 'isEmail') { if (!f.type) { f.type = 'string' } f.format = 'email'; return }\n if (key === 'isDate' || key === 'isDateString') { f.type = 'string'; f.format = 'date-time'; return }\n if (key === 'isEnum') { const e = normalizeEnum(c0); if (e) { f.enum = e } return }\n if (key === 'isOptional') { f.required = false }\n}\n\n/** From an array of `class-validator` validation-metadata entries for one property. */\nexport function classValidatorToField(metas: Array<{ type?: string; name?: string; constraints?: unknown[] }>): FieldDesc {\n const f: FieldDesc = {}\n for (const meta of metas) { applyValidationMeta(f, meta) }\n return f\n}\n\n/** From an OpenAPI Schema Object (used by both the doc and `@ApiParam({ schema })`). */\nexport function openapiSchemaToField(schema: Record<string, any>): FieldDesc {\n const f: FieldDesc = {}\n const type = typeof schema['type'] === 'string' ? schema['type'].toLowerCase() : undefined\n if (type === 'string' || type === 'number' || type === 'integer' || type === 'boolean' || type === 'array' || type === 'object') {\n f.type = type\n }\n if (schema['description']) { f.description = schema['description'] }\n const en = normalizeEnum(schema['enum'])\n if (en) { f.enum = en }\n if (schema['minimum'] != null) { f.min = schema['minimum'] }\n if (schema['maximum'] != null) { f.max = schema['maximum'] }\n if (schema['minLength'] != null) { f.minLength = schema['minLength'] }\n if (schema['maxLength'] != null) { f.maxLength = schema['maxLength'] }\n if (schema['format']) { f.format = schema['format'] }\n if (schema['nullable'] === true) { f.nullable = true }\n if (schema['default'] !== undefined) { f.default = schema['default'] }\n if (schema['items'] && typeof schema['items'] === 'object') {\n f.items = openapiSchemaToField(schema['items'])\n }\n return f\n}\n\n/**\n * Reflect a whole-DTO class (`@Body() dto: CreateDto`) into per-property\n * {@link FieldDesc}s. Property names are the union of `@ApiProperty` and\n * `class-validator` decorated fields; each field merges `design:type` (base),\n * then `class-validator` constraints, then `@ApiProperty` (highest). Properties\n * default to required unless a source marks them optional.\n */\nexport function reflectDtoFields(dtoType: any): Record<string, FieldDesc> {\n const proto = dtoType?.prototype\n if (!proto) { return {} }\n const cvMetas = classValidatorMetas(dtoType)\n\n const names = new Set<string>()\n const swaggerArray = (Reflect.getMetadata(API_MODEL_PROPERTIES_ARRAY, proto) as string[] | undefined) ?? []\n for (const entry of swaggerArray) { names.add(entry.replace(/^:/, '')) }\n for (const name of Object.keys(cvMetas)) { names.add(name) }\n\n const out: Record<string, FieldDesc> = {}\n for (const name of names) {\n let f = designTypeToField(Reflect.getMetadata('design:type', proto, name))\n if (cvMetas[name]) { f = mergeField(f, classValidatorToField(cvMetas[name])) }\n const apiProp = Reflect.getMetadata(API_MODEL_PROPERTIES, proto, name) as Record<string, any> | undefined\n if (apiProp) {\n const fromApi = apiPropertyToField(apiProp)\n // `@ApiProperty` is required unless `required: false` is explicit.\n if (fromApi.required === undefined && apiProp['required'] === undefined) { fromApi.required = true }\n f = mergeField(f, fromApi)\n }\n if (f.required === undefined) { f.required = true }\n out[name] = f\n }\n return out\n}\n\n/**\n * Names of fields that could not be reflected into a concrete type - they will\n * become `z.unknown()` (or `z.array(z.unknown())`). This is how a nested DTO or a\n * `Dto[]` property silently degrades (reflection is one level deep), so the\n * adapters surface these as a build-time warning pointing at `@Trpc({ output })`\n * / `@Mcp({ input })`. Enum and `object` (record) fields are not degraded.\n */\nexport function unreflectedFields(fields: Record<string, FieldDesc>): string[] {\n const out: string[] = []\n for (const [name, f] of Object.entries(fields)) {\n if (f.enum?.length) { continue }\n if (!f.type || f.type === 'unknown') { out.push(name) } else if (f.type === 'array' && (!f.items?.type || f.items.type === 'unknown')) { out.push(name) }\n }\n return out\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment */\nimport { type FieldDesc, mergeField, openapiSchemaToField } from './schema.js'\n\n/**\n * A minimal view of an OpenAPI document - the subset we read. Matches the shape\n * `SwaggerModule.createDocument()` returns, but typed loosely so callers can\n * pass any compatible object without a hard `@nestjs/swagger` dependency.\n */\nexport interface OpenApiDocument {\n paths?: Record<string, Record<string, any>>\n components?: { schemas?: Record<string, any> }\n}\n\nexport interface OpenApiLookup {\n doc: OpenApiDocument\n /** `${METHOD} ${path}` → operation object. */\n operations: Map<string, any>\n}\n\n/** Index a document's operations by `${METHOD} ${path}` for fast matching. */\nexport function buildOpenApiLookup(doc: OpenApiDocument): OpenApiLookup {\n const operations = new Map<string, any>()\n for (const [path, item] of Object.entries(doc.paths ?? {})) {\n for (const [verb, op] of Object.entries(item ?? {})) {\n operations.set(`${verb.toUpperCase()} ${path}`, op)\n }\n }\n return { doc, operations }\n}\n\n/** Locate the operation for a route, tolerating a global path prefix on the document side. */\nfunction findOperation(lookup: OpenApiLookup, method: string, openapiPath: string): any | undefined {\n const exact = lookup.operations.get(`${method} ${openapiPath}`)\n if (exact) { return exact }\n // Fall back to a suffix match so a `setGlobalPrefix('api')` document still resolves.\n for (const [key, op] of lookup.operations) {\n const [verb, path] = key.split(' ')\n if (verb === method && (path.endsWith(openapiPath) || openapiPath.endsWith(path))) { return op }\n }\n return undefined\n}\n\nfunction resolveRef(doc: OpenApiDocument, schema: any): any {\n let current = schema\n let guard = 0\n while (current && typeof current === 'object' && typeof current['$ref'] === 'string' && guard < 10) {\n const match = /^#\\/components\\/schemas\\/(.+)$/.exec(current['$ref'])\n if (!match) { break }\n current = doc.components?.schemas?.[match[1]]\n guard += 1\n }\n return current\n}\n\n/**\n * Resolve the per-field descriptors for a route from an ingested OpenAPI\n * document. Merges `parameters` (path/query/header) and the JSON request-body\n * schema's properties into a single field map. Returns `{}` when the operation\n * isn't found - callers fall back to decorator reflection.\n */\nexport function openApiFields(lookup: OpenApiLookup, method: string, openapiPath: string): Record<string, FieldDesc> {\n const op = findOperation(lookup, method, openapiPath)\n if (!op) { return {} }\n const out: Record<string, FieldDesc> = {}\n\n for (const param of (op['parameters'] as Array<Record<string, any>> | undefined) ?? []) {\n const name = typeof param['name'] === 'string' ? param['name'] : undefined\n if (!name) { continue }\n const schema = param['schema'] ? resolveRef(lookup.doc, param['schema']) : undefined\n let field = schema ? openapiSchemaToField(schema) : {}\n if (param['description']) { field = mergeField(field, { description: param['description'] }) }\n if (typeof param['required'] === 'boolean') { field = mergeField(field, { required: param['required'] }) }\n out[name] = field\n }\n\n const bodySchema = resolveRef(lookup.doc, op['requestBody']?.['content']?.['application/json']?.['schema'])\n if (bodySchema && typeof bodySchema === 'object' && bodySchema['properties']) {\n const required = new Set<string>(Array.isArray(bodySchema['required']) ? bodySchema['required'] : [])\n for (const [name, propSchema] of Object.entries(bodySchema['properties'] as Record<string, any>)) {\n const field = openapiSchemaToField(resolveRef(lookup.doc, propSchema))\n field.required = required.has(name)\n out[name] = field\n }\n }\n\n return out\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { z } from 'zod/v4'\nimport { type FieldDesc, fieldToZod, reflectDtoFields } from './schema.js'\n\n/** `@nestjs/swagger` response metadata key (read directly - swagger is an optional peer). */\nconst API_RESPONSE = 'swagger/apiResponse'\n\n/** Status keys we treat as the \"success\" response, in preference order. */\nconst SUCCESS_KEYS = ['200', '201', '202', '204', '2XX', 'default']\n\n/** The 2xx (or first) `@ApiResponse` entry for a method, if any. */\nfunction successEntry(method: (...args: any[]) => any): { type?: unknown; isArray?: boolean } | undefined {\n const responses = Reflect.getMetadata(API_RESPONSE, method) as Record<string, { type?: unknown; isArray?: boolean }> | undefined\n if (!responses) { return undefined }\n const key = SUCCESS_KEYS.find((k) => responses[k]) ?? Object.keys(responses)[0]\n return key ? responses[key] : undefined\n}\n\n/**\n * Reflect a `@Trpc` procedure's output schema from the method's\n * `@ApiOkResponse({ type: Dto })` (or any 2xx `@ApiResponse`) metadata. The\n * response DTO is flattened with {@link reflectDtoFields} into a Zod object,\n * wrapped in `z.array(...)` when the response is `isArray`.\n *\n * Returns `undefined` when there is no response DTO to reflect (e.g. a primitive\n * return type or no `@ApiResponse` decorator) - the caller then falls back to an\n * explicit `@Trpc({ output })` or an `unknown` output type.\n */\nexport function reflectResponseSchema(method: (...args: any[]) => any): z.ZodType | undefined {\n const entry = successEntry(method)\n const dtoType = entry?.type\n if (typeof dtoType !== 'function') { return undefined }\n\n const schema = reflectDtoSchema(dtoType)\n if (!schema) { return undefined }\n return entry?.isArray ? z.array(schema) : schema\n}\n\n/**\n * The reflected `FieldDesc` map for a method's response DTO (the same fields\n * {@link reflectResponseSchema} builds its schema from), or `undefined` when\n * there is no DTO to reflect. Used to detect fields that degraded to `unknown`\n * (nested DTO / `Dto[]`) so the caller can warn.\n */\nexport function reflectResponseFields(method: (...args: any[]) => any): Record<string, FieldDesc> | undefined {\n const dtoType = successEntry(method)?.type\n if (typeof dtoType !== 'function') { return undefined }\n return reflectDtoFields(dtoType)\n}\n\n/**\n * Reflect a DTO class (its `@ApiProperty`/`class-validator`-decorated properties)\n * into a Zod object schema. Returns `undefined` when the type isn't a class or\n * has no reflectable properties. Used for `@Trpc({ output })`/`@Trpc({ chunk })`\n * when given a DTO class instead of a Zod schema.\n */\nexport function reflectDtoSchema(dtoType: unknown): z.ZodType | undefined {\n if (typeof dtoType !== 'function') { return undefined }\n const fields = reflectDtoFields(dtoType)\n const names = Object.keys(fields)\n if (names.length === 0) { return undefined }\n const shape: Record<string, z.ZodType> = {}\n for (const name of names) { shape[name] = fieldToZod(fields[name]) }\n return z.object(shape)\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { PATH_METADATA, METHOD_METADATA } from '@nestjs/common/constants.js'\n\n/**\n * `RequestMethod` numeric values (from `@nestjs/common`) mapped to verbs. We\n * map our own table rather than importing the enum to avoid pulling a value\n * import for a handful of constants.\n */\nconst REQUEST_METHOD: Record<number, string> = {\n 0: 'GET',\n 1: 'POST',\n 2: 'PUT',\n 3: 'DELETE',\n 4: 'PATCH',\n 6: 'OPTIONS',\n 7: 'HEAD'\n}\n\nexport interface RouteInfo {\n /** HTTP verb (`GET`/`POST`/...). `PATCH` and others outside the REST set fall back to `POST`-ish handling by callers. */\n method: string\n /** Full route template in Nest form, e.g. `sessions/:sessionId/channels/:channelId` (no leading slash). */\n path: string\n /** Full route template in OpenAPI form, e.g. `/sessions/{sessionId}/channels/{channelId}`. */\n openapiPath: string\n /** Names of the `:param` placeholders across controller + method path. */\n pathParams: string[]\n}\n\nfunction normalizeSegment(value: unknown): string {\n if (typeof value !== 'string') { return '' }\n return value.replace(/^\\/+/, '').replace(/\\/+$/, '')\n}\n\nfunction joinPath(...segments: string[]): string {\n return segments.map(normalizeSegment).filter(Boolean).join('/')\n}\n\n/**\n * Resolve the composed route (controller prefix + method path), HTTP verb, and\n * path-param names for a decorated controller method, reading Nest's own\n * `PATH_METADATA`/`METHOD_METADATA` reflection.\n */\nexport function reflectRoute(classRef: any, method: (...args: any[]) => any): RouteInfo {\n const classPath = Reflect.getMetadata(PATH_METADATA, classRef) as string | string[] | undefined\n const methodPath = Reflect.getMetadata(PATH_METADATA, method) as string | string[] | undefined\n const verbCode = Reflect.getMetadata(METHOD_METADATA, method) as number | undefined\n\n const classSeg = Array.isArray(classPath) ? (classPath[0] ?? '') : (classPath ?? '')\n const methodSeg = Array.isArray(methodPath) ? (methodPath[0] ?? '') : (methodPath ?? '')\n const path = joinPath(classSeg, methodSeg)\n const httpMethod = REQUEST_METHOD[verbCode ?? 0] ?? 'GET'\n\n const pathParams = [...path.matchAll(/:([A-Za-z0-9_]+)/g)].map((m) => m[1])\n const openapiPath = `/${path.replace(/:([A-Za-z0-9_]+)/g, '{$1}')}`\n\n return { method: httpMethod, path, openapiPath, pathParams }\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport type { FieldDesc } from './schema.js'\nimport { swaggerParamToField } from './schema.js'\n\n/** `@nestjs/swagger` reflect-metadata keys (read directly - swagger is an optional peer). */\nconst API_OPERATION = 'swagger/apiOperation'\nconst API_PARAMETERS = 'swagger/apiParameters'\n\nexport interface OperationMeta {\n /** Tool-description candidate from `@ApiOperation({ summary | description })`. */\n description?: string\n /** Per-name `FieldDesc` reflected from `@ApiParam`/`@ApiQuery` entries. */\n params: Record<string, FieldDesc>\n}\n\n/**\n * Read operation-level `@nestjs/swagger` metadata off a controller method:\n * `@ApiOperation` (summary/description) and the `@ApiParam`/`@ApiQuery` array\n * (each describing one path/query field). Returns empty data when swagger\n * decorators are absent.\n */\nexport function reflectOperation(method: (...args: any[]) => any): OperationMeta {\n const operation = Reflect.getMetadata(API_OPERATION, method) as Record<string, any> | undefined\n const description = operation\n ? (typeof operation['summary'] === 'string' && operation['summary']\n ? operation['summary']\n : (typeof operation['description'] === 'string' ? operation['description'] : undefined))\n : undefined\n\n const parameters = (Reflect.getMetadata(API_PARAMETERS, method) as Array<Record<string, any>> | undefined) ?? []\n const params: Record<string, FieldDesc> = {}\n for (const p of parameters) {\n const name = typeof p['name'] === 'string' ? p['name'] : undefined\n if (!name) { continue }\n params[name] = swaggerParamToField(p)\n }\n\n return { description, params }\n}\n","/* eslint-disable @typescript-eslint/no-unsafe-assignment */\nimport { HttpException, Injectable, Logger, type CanActivate, type Type } from '@nestjs/common'\nimport { ApplicationConfig, DiscoveryService, MetadataScanner, ModuleRef, Reflector } from '@nestjs/core'\nimport { SilkweaveError, type Action, type ActionKind, type SilkweaveContext } from '@silkweave/core'\nimport { z } from 'zod/v4'\nimport { collectGlobalGuards, collectGuards, runGuards } from './guards.js'\nimport { MCP_METADATA, TRPC_METADATA, type McpMetadata, type TrpcMetadata } from './metadata.js'\nimport { invokeRebound, specialBinding, type Binding } from './rebind.js'\nimport { populateRequestSlots, requestSlotFields, type RequestSlots } from './requestSlots.js'\nimport { buildOpenApiLookup, openApiFields, type OpenApiDocument, type OpenApiLookup } from './reflect/openapi.js'\nimport { PARAMTYPE, type ParamSlot, readParamSlots } from './reflect/params.js'\nimport { reflectDtoSchema, reflectResponseFields, reflectResponseSchema } from './reflect/response.js'\nimport { reflectRoute, type RouteInfo } from './reflect/route.js'\nimport { type FieldDesc, fieldToZod, mergeField, reflectDtoFields, unreflectedFields } from './reflect/schema.js'\nimport { reflectOperation } from './reflect/swagger.js'\n\n/** Discovery-time diagnostics (unreflectable params, degraded outputs). */\nconst logger = new Logger('Silkweave')\n\ninterface Discovered {\n instance: object\n classRef: Type<unknown>\n method: (...args: unknown[]) => unknown\n methodName: string\n mcp?: McpMetadata\n trpc?: TrpcMetadata\n}\n\ninterface BuiltInput {\n shape: Record<string, z.ZodType>\n bindings: Binding[]\n /** Human-readable notes about params reflection could not turn into fields. */\n warnings: string[]\n}\n\n/** Shared reflection computed once per discovered method, reused across targets. */\ninterface Reflected {\n route: RouteInfo\n base: string\n description?: string\n baseShape: Record<string, z.ZodType>\n bindings: Binding[]\n guards: ReturnType<typeof collectGuards>\n requestSlots: RequestSlots\n streaming: boolean\n}\n\nexport interface DiscoverOptions {\n openapi?: OpenApiDocument\n globalGuards?: Type<CanActivate>[]\n defaultResult?: 'json' | 'smart'\n}\n\n@Injectable()\nexport class ControllerDiscovery {\n constructor(\n private readonly discovery: DiscoveryService,\n private readonly scanner: MetadataScanner,\n private readonly reflector: Reflector,\n private readonly moduleRef: ModuleRef,\n private readonly appConfig: ApplicationConfig\n ) { }\n\n /**\n * Walk every Nest provider/controller, find methods annotated with `@Mcp`\n * and/or `@Trpc`, and build a core `Action` per decorator present on each\n * method. The input schema is reflected from the route + parameter decorators\n * (+ optional OpenAPI document) and the `run` re-binds the validated input back\n * into the method's positional arguments (with `@UseGuards` guards applied\n * first). A method carrying both decorators yields two actions - one gated to\n * the `mcp` adapter, one to the `trpc`/`typegen` adapters - sharing the same\n * reflected input, bindings, and guards.\n */\n discover(options: DiscoverOptions = {}): Action[] {\n const lookup = options.openapi ? buildOpenApiLookup(options.openapi) : undefined\n const discovered: Discovered[] = []\n for (const wrapper of this.discovery.getProviders().concat(this.discovery.getControllers())) {\n const { instance } = wrapper\n if (!instance || typeof instance !== 'object') { continue }\n const proto = Object.getPrototypeOf(instance) as object | null\n if (!proto) { continue }\n const classRef = instance.constructor as Type<unknown>\n for (const methodName of this.scanner.getAllMethodNames(proto)) {\n const method = (proto as Record<string, unknown>)[methodName] as ((...args: unknown[]) => unknown) | undefined\n if (typeof method !== 'function') { continue }\n const mcp = this.reflector.get<McpMetadata>(MCP_METADATA, method)\n const trpc = this.reflector.get<TrpcMetadata>(TRPC_METADATA, method)\n if (!mcp && !trpc) { continue }\n discovered.push({ instance, classRef, method, methodName, mcp, trpc })\n }\n }\n\n const globalGuards = options.globalGuards ?? []\n const actions: Action[] = []\n for (const d of discovered) {\n const shared = this.reflect(d, lookup)\n if (d.mcp) { actions.push(this.mcpAction(d, shared, globalGuards, options.defaultResult)) }\n if (d.trpc) { actions.push(this.trpcAction(d, shared, globalGuards)) }\n }\n return actions\n }\n\n /** Compute the per-method reflection shared by the `mcp` and `trpc` builders. */\n private reflect(d: Discovered, lookup: OpenApiLookup | undefined): Reflected {\n const proto = Object.getPrototypeOf(d.instance) as object\n const route = reflectRoute(d.classRef, d.method)\n const slots = readParamSlots(d.classRef, d.methodName, proto)\n const operation = reflectOperation(d.method)\n const docFields = lookup ? openApiFields(lookup, route.method, route.openapiPath) : {}\n\n const { shape, bindings, warnings } = buildInput(proto, d.methodName, route.pathParams, slots, operation.params, docFields)\n for (const w of warnings) { logger.warn(`${d.classRef.name}.${d.methodName}: ${w}`) }\n\n return {\n route,\n base: d.classRef.name.replace(/Controller$/, ''),\n description: operation.description,\n baseShape: shape,\n bindings,\n guards: collectGuards(this.reflector, d.classRef, d.method),\n requestSlots: requestSlotFields(bindings),\n streaming: isAsyncGeneratorFn(d.method)\n }\n }\n\n /** Build a guard-application closure shared by both run shapes. */\n private guardRunner(d: Discovered, shared: Reflected, globalGuards: Type<CanActivate>[]) {\n const { moduleRef, reflector, appConfig } = this\n const { guards, requestSlots } = shared\n const { classRef, method } = d\n return async (context: SilkweaveContext, input: object): Promise<void> => {\n // Resolved at call time - `APP_GUARD` instances aren't populated until\n // `app.init()` finishes. Globals run before the route/class guards.\n const all = [...collectGlobalGuards(appConfig, globalGuards), ...guards]\n if (all.length === 0) { return }\n const request = context.getOptional<unknown>('request')\n const response = context.getOptional<unknown>('response') ?? null\n const hasRequest = request != null\n const guardRequest = hasRequest ? request : { headers: {}, params: {}, query: {} }\n populateRequestSlots(guardRequest, requestSlots, input as Record<string, unknown>)\n await runGuards(all, moduleRef, reflector, classRef, method, guardRequest, response, hasRequest ? 'http' : 'rpc')\n }\n }\n\n /** Synthesize the MCP-targeted action (unchanged behavior from v2.4). */\n private mcpAction(d: Discovered, shared: Reflected, globalGuards: Type<CanActivate>[], defaultResult?: 'json' | 'smart'): Action {\n const meta = d.mcp!\n const shape = { ...shared.baseShape, ...inputShape(meta.input) }\n const name = meta.name ?? `${shared.base}.${d.methodName}`\n const description = meta.description ?? shared.description ?? `${d.methodName} (${shared.route.method} /${shared.route.path})`\n const applyParamPipes = meta.pipes !== 'skip'\n const applyGuards = this.guardRunner(d, shared, globalGuards)\n const { method, instance } = d\n const { bindings, streaming } = shared\n\n return {\n name,\n description,\n input: z.object(shape),\n ...((meta.result ?? defaultResult) ? { disposition: meta.result ?? defaultResult } : {}),\n isEnabled: (ctx) => ctx.getOptional<string>('adapter') === 'mcp',\n ...(streaming\n ? { chunk: z.unknown(), run: streamingRun(applyGuards, method, instance, bindings, applyParamPipes, false) }\n : {\n run: async (input: object, context: SilkweaveContext): Promise<object> => {\n await applyGuards(context, input)\n const request = context.getOptional<{ headers?: Record<string, unknown> }>('request')\n const response = context.getOptional<unknown>('response')\n const result = await invokeRebound(method, instance, input as Record<string, unknown>, bindings, request, response, applyParamPipes)\n return result ?? {}\n }\n })\n } as Action\n }\n\n /** Synthesize the tRPC-targeted action (kind/output/subscription + httpStatus errors). */\n private trpcAction(d: Discovered, shared: Reflected, globalGuards: Type<CanActivate>[]): Action {\n const meta = d.trpc!\n const shape = { ...shared.baseShape, ...inputShape(meta.input) }\n const name = meta.name ?? `${shared.base}.${d.methodName}`\n const description = meta.description ?? shared.description ?? `${d.methodName} (${shared.route.method} /${shared.route.path})`\n const applyParamPipes = meta.pipes !== 'skip'\n const applyGuards = this.guardRunner(d, shared, globalGuards)\n const { method, instance } = d\n const { bindings, streaming } = shared\n\n // tRPC and typegen both consume `@Trpc` actions; MCP never does.\n const isEnabled = (ctx: SilkweaveContext): boolean => {\n const adapter = ctx.getOptional<string>('adapter')\n return adapter === 'trpc' || adapter === 'typegen'\n }\n\n if (streaming) {\n return {\n name,\n description,\n input: z.object(shape),\n chunk: resolveSchema(meta.chunk) ?? z.unknown(),\n isEnabled,\n run: streamingRun(applyGuards, method, instance, bindings, applyParamPipes, true)\n } as Action\n }\n\n const kind: ActionKind = meta.kind === 'query' || meta.kind === 'mutation'\n ? meta.kind\n : (shared.route.method === 'GET' ? 'query' : 'mutation')\n const output = resolveOutput(meta, method)\n\n // Reflection is one level deep, so a nested DTO or `Dto[]` output property\n // degrades to `unknown`/`unknown[]`. Surface it - the fix is `@Trpc({ output })`.\n const degraded = outputDegradedFields(meta, method)\n if (output && degraded.length > 0) {\n logger.warn(\n `${d.classRef.name}.${d.methodName}: tRPC output field(s) ${degraded.join(', ')} reflected to 'unknown' ` +\n '(nested DTO or Dto[] - reflection is one level deep). Supply @Trpc({ output }) with a Zod schema for precise types.'\n )\n }\n\n return {\n name,\n description,\n input: z.object(shape),\n ...(output ? { output } : {}),\n kind,\n isEnabled,\n run: async (input: object, context: SilkweaveContext): Promise<object> => {\n try {\n await applyGuards(context, input)\n const request = context.getOptional<{ headers?: Record<string, unknown> }>('request')\n const response = context.getOptional<unknown>('response')\n const result = await invokeRebound(method, instance, input as Record<string, unknown>, bindings, request, response, applyParamPipes)\n return result ?? {}\n } catch (error) {\n throw toSilkweaveError(error)\n }\n }\n } as Action\n }\n}\n\n/** Build a streaming (`async *`) run that applies guards then yields the method's chunks. */\nfunction streamingRun(\n applyGuards: (context: SilkweaveContext, input: object) => Promise<void>,\n method: (...args: unknown[]) => unknown,\n instance: object,\n bindings: Binding[],\n applyParamPipes: boolean,\n mapErrors: boolean\n) {\n return async function* (input: object, context: SilkweaveContext): AsyncGenerator<unknown, void, void> {\n try {\n await applyGuards(context, input)\n const request = context.getOptional<{ headers?: Record<string, unknown> }>('request')\n const response = context.getOptional<unknown>('response')\n const gen = await invokeRebound(method, instance, input as Record<string, unknown>, bindings, request, response, applyParamPipes) as AsyncIterable<unknown>\n for await (const chunk of gen) { yield chunk }\n } catch (error) {\n throw mapErrors ? toSilkweaveError(error) : error\n }\n }\n}\n\n/** Resolve a `@Trpc` action's output schema: explicit override wins over `@ApiOkResponse` reflection. */\nfunction resolveOutput(meta: TrpcMetadata, method: (...args: unknown[]) => unknown): z.ZodType | undefined {\n return resolveSchema(meta.output) ?? reflectResponseSchema(method)\n}\n\n/**\n * Output field names that reflected to `unknown` (nested DTO / `Dto[]`). Only the\n * reflected paths are inspected - an explicit Zod or raw-shape `@Trpc({ output })`\n * is the caller's own typing and is never flagged.\n */\nfunction outputDegradedFields(meta: TrpcMetadata, method: (...args: unknown[]) => unknown): string[] {\n if (meta.output != null && isZodSchema(meta.output)) { return [] }\n const fields = typeof meta.output === 'function'\n ? reflectDtoFields(meta.output)\n : meta.output != null ? undefined : reflectResponseFields(method)\n return fields ? unreflectedFields(fields) : []\n}\n\n/**\n * Normalise an `@Mcp`/`@Trpc({ input })` override to a raw Zod shape. Accepts a\n * plain `Record<string, ZodType>` or a whole `z.object({ ... })` (duck-typed by\n * `safeParse` + `shape`, so a different zod copy's object still unwraps).\n */\nfunction inputShape(input: McpMetadata['input']): Record<string, z.ZodType> {\n if (!input) { return {} }\n const maybe = input as { safeParse?: unknown; shape?: unknown }\n if (typeof maybe.safeParse === 'function' && maybe.shape != null && typeof maybe.shape === 'object') {\n return maybe.shape as Record<string, z.ZodType>\n }\n return input as Record<string, z.ZodType>\n}\n\n/**\n * Coerce an `output`/`chunk` override to a Zod schema: a Zod schema passes\n * through, a DTO class is reflected, and a raw shape is wrapped in `z.object`.\n */\nfunction resolveSchema(value: TrpcMetadata['output']): z.ZodType | undefined {\n if (value == null) { return undefined }\n if (isZodSchema(value)) { return value }\n if (typeof value === 'function') { return reflectDtoSchema(value) }\n return z.object(value)\n}\n\nfunction isZodSchema(value: unknown): value is z.ZodType {\n return Boolean(value) && typeof value === 'object' && typeof (value as { safeParse?: unknown }).safeParse === 'function'\n}\n\nfunction isAsyncGeneratorFn(fn: unknown): boolean {\n return typeof fn === 'function' && (fn as { constructor?: { name?: string } }).constructor?.name === 'AsyncGeneratorFunction'\n}\n\n/**\n * Convert a thrown Nest `HttpException` into a `SilkweaveError` carrying its HTTP\n * status, so the tRPC adapter's `mapError` maps it to the right `TRPCError` code\n * (and `data.httpStatus`) - e.g. a denying `AuthGuard`'s `UnauthorizedException`\n * surfaces to the client as a `401`. Non-HTTP errors pass through unchanged.\n */\nfunction toSilkweaveError(error: unknown): unknown {\n if (error instanceof HttpException) {\n const status = error.getStatus()\n const response = error.getResponse()\n const raw = typeof response === 'string'\n ? response\n : (response as { message?: unknown })?.message ?? error.message\n const message = Array.isArray(raw) ? raw.join(', ') : String(raw)\n return new SilkweaveError(message, 'http_error', status)\n }\n return error\n}\n\n/** Build the merged Zod input shape and the per-argument re-bind plan. */\nfunction buildInput(\n proto: object,\n methodName: string,\n pathParams: string[],\n slots: ReturnType<typeof readParamSlots>,\n operationParams: Record<string, FieldDesc>,\n docFields: Record<string, FieldDesc>\n): BuiltInput {\n const designTypes = (Reflect.getMetadata('design:paramtypes', proto, methodName) as unknown[] | undefined) ?? []\n const fields: Record<string, FieldDesc> = {}\n const warnings: string[] = []\n const maxIndex = slots.reduce((m, s) => Math.max(m, s.index), -1)\n const bindings: Binding[] = Array.from({ length: maxIndex + 1 }, () => ({ kind: 'missing' as const }))\n\n const addField = (name: string, desc: FieldDesc): void => {\n fields[name] = name in fields ? mergeField(fields[name], desc) : desc\n }\n\n for (const slot of slots) {\n const { binding, fields: contributed } = contributeSlot(slot, pathParams, designTypes)\n bindings[slot.index] = binding\n for (const [name, desc] of Object.entries(contributed)) { addField(name, desc) }\n // A whole-DTO `@Body()`/`@Query()` that reflected to zero fields: the type\n // was unreflectable (an interface, or an intersection/union TypeScript\n // erases to `Object`/`Array` under `design:type`). Its fields are silently\n // absent unless declared via `@Mcp`/`@Trpc({ input })`.\n if (binding.kind === 'object' && binding.fields.length === 0) {\n const typeName = (designTypes[slot.index] as { name?: string } | undefined)?.name ?? 'unknown'\n warnings.push(\n `whole-${binding.source} parameter #${slot.index} (type '${typeName}') reflected no input fields. ` +\n `If it is an intersection/union (e.g. 'A & B'), TypeScript erases it to '${typeName}' so the DTO is lost - ` +\n 'use a single DTO class or declare the fields via @Mcp/@Trpc({ input }).'\n )\n }\n }\n\n // Layer operation-level (`@ApiParam`/`@ApiQuery`) then OpenAPI-document\n // metadata over the structural fields (later sources win per field).\n for (const [name, desc] of Object.entries(operationParams)) {\n if (name in fields) { fields[name] = mergeField(fields[name], desc) }\n }\n for (const [name, desc] of Object.entries(docFields)) {\n if (name in fields) { fields[name] = mergeField(fields[name], desc) }\n }\n\n const shape: Record<string, z.ZodType> = {}\n for (const [name, desc] of Object.entries(fields)) { shape[name] = fieldToZod(desc) }\n\n return { shape, bindings, warnings }\n}\n\nfunction designTypeAt(designTypes: unknown[], index: number): FieldDesc {\n const ctor = designTypes[index]\n if (ctor === String) { return { type: 'string' } }\n if (ctor === Number) { return { type: 'number' } }\n if (ctor === Boolean) { return { type: 'boolean' } }\n return {}\n}\n\ninterface SlotContribution {\n binding: Binding\n /** Input fields this slot contributes, keyed by field name. */\n fields: Record<string, FieldDesc>\n}\n\n/** A `@Param('id')` scalar or a bare `@Param()` covering all path params. */\nfunction paramContribution(slot: ParamSlot, pathParams: string[]): SlotContribution {\n if (slot.data) {\n return {\n binding: { kind: 'value', field: slot.data, source: 'path', metatype: slot.designType, pipes: slot.pipes },\n fields: { [slot.data]: { type: 'string', required: true } }\n }\n }\n const fields: Record<string, FieldDesc> = {}\n for (const p of pathParams) { fields[p] = { type: 'string', required: true } }\n return { binding: { kind: 'params', fields: pathParams }, fields }\n}\n\n/** A `@Query('x')`/`@Body('x')` scalar or a whole-DTO `@Query()`/`@Body()`. */\nfunction bodyOrQueryContribution(slot: ParamSlot, source: 'query' | 'body', requiredScalar: boolean, designTypes: unknown[]): SlotContribution {\n if (slot.data) {\n return {\n binding: { kind: 'value', field: slot.data, source, metatype: slot.designType, pipes: slot.pipes },\n fields: { [slot.data]: mergeField(designTypeAt(designTypes, slot.index), { required: requiredScalar }) }\n }\n }\n const dtoFields = reflectDtoFields(slot.designType)\n return {\n binding: { kind: 'object', source, fields: Object.keys(dtoFields), metatype: slot.designType, pipes: slot.pipes },\n fields: dtoFields\n }\n}\n\n/** Map one parameter slot to its input-field contribution and re-bind instruction. */\nfunction contributeSlot(slot: ParamSlot, pathParams: string[], designTypes: unknown[]): SlotContribution {\n switch (slot.paramtype) {\n case PARAMTYPE.PARAM: return paramContribution(slot, pathParams)\n case PARAMTYPE.QUERY: return bodyOrQueryContribution(slot, 'query', false, designTypes)\n case PARAMTYPE.BODY: return bodyOrQueryContribution(slot, 'body', true, designTypes)\n default: return { binding: specialBinding(slot.paramtype, slot.data) ?? { kind: 'missing' }, fields: {} }\n }\n}\n","import type { CanActivate, Type } from '@nestjs/common'\nimport type { HttpAdapterHost } from '@nestjs/core'\nimport type { Action, SilkweaveContext, SilkweaveOptions } from '@silkweave/core'\nimport type { OpenApiDocument } from './reflect/openapi.js'\n\n/**\n * Context passed to a Nest Silkweave adapter when `SilkweaveModule` wires it\n * up. Adapters register their routes directly on `httpAdapter` (no\n * placeholder middleware, no `silkweave()` builder), so they only fire\n * `register()` once and own the rest of their lifecycle implicitly through\n * Nest.\n */\nexport interface NestAdapterRegisterContext {\n /** Nest's underlying HTTP adapter (Express or Fastify). */\n httpAdapter: NonNullable<HttpAdapterHost['httpAdapter']>\n /** Identity the adapter surfaces to clients (e.g. MCP server name). */\n silkweaveOptions: SilkweaveOptions\n /** Per-adapter context - already forked with `{ adapter: adapter.name, ...userContext }`. */\n baseContext: SilkweaveContext\n /** Actions filtered to those enabled on this adapter. */\n actions: Action[]\n}\n\n/**\n * A Silkweave Nest adapter. Each transport (REST, tRPC, MCP) implements this\n * shape. `register()` is called from `SilkweaveModule.configure()` - which\n * runs *before* Nest's controller routes are mapped - so adapter routes\n * always sit ahead of any catch-all controllers in the framework's request\n * pipeline.\n */\nexport interface NestSilkweaveAdapter {\n /** Adapter discriminator - set on the silkweave context as `ctx.get('adapter')`. */\n readonly name: 'mcp' | 'trpc' | 'typegen'\n /** URL prefix the adapter mounts on (e.g. `'/mcp'`). Surfaced for introspection. */\n readonly basePath?: string\n /**\n * When `true`, the adapter receives every discovered action regardless of\n * each action's `isEnabled` gate. Reserved for non-runtime adapters that need\n * the entire action surface.\n */\n readonly allActions?: boolean\n /** Register this adapter's routes on Nest's HTTP server. */\n register(ctx: NestAdapterRegisterContext): void\n}\n\nexport interface SilkweaveModuleOptions {\n /** Identity for the silkweave instance - surfaced to MCP clients, OpenAPI, etc. */\n silkweave: SilkweaveOptions\n /** Adapters to mount - any of `mcp()`, `trpc()`, `typegen()`. */\n adapters: NestSilkweaveAdapter[]\n /** Initial context keys merged into every adapter's `baseContext`. */\n context?: Record<string, unknown>\n /**\n * Optional OpenAPI document (e.g. from `SwaggerModule.createDocument(app, cfg)`)\n * used as an authoritative source when reflecting `@Mcp` tool input schemas.\n * Matched to each method by HTTP verb + path; falls back to decorator\n * reflection when an operation or field isn't present.\n */\n openapi?: OpenApiDocument\n /**\n * Opt-in allow-list of app-global guard classes (registered via\n * `app.useGlobalGuards()` or `{ provide: APP_GUARD, useClass }`) to run on\n * every MCP tool call, before each method/class `@UseGuards`. Listed by\n * class - a blanket \"run all globals\" is deliberately not offered, since\n * unrelated globals (e.g. a `ThrottlerGuard` that needs a writable response)\n * would misbehave over MCP. Empty/omitted ⇒ no global guards run.\n *\n * Note: over MCP the request stand-in is headers-only (`params`/`query` are\n * empty), so per-session or IP-derived guard logic won't apply; header-based\n * authentication still works.\n */\n globalGuards?: Type<CanActivate>[]\n /**\n * Default MCP result format for every `@Mcp` tool - `'json'` (compact JSON,\n * `jsonToolResult`) or `'smart'` (inline small / embedded-resource large,\n * `smartToolResult`). Defaults to `'smart'`. A per-method `@Mcp({ result })`\n * overrides this, and a client's per-call `_meta.disposition` overrides both.\n */\n defaultResult?: 'json' | 'smart'\n}\n\nexport const SILKWEAVE_MODULE_OPTIONS = '__silkweave_module_options__'\n","import { Inject, Module, type DynamicModule, type MiddlewareConsumer, type NestModule } from '@nestjs/common'\nimport { DiscoveryModule, HttpAdapterHost } from '@nestjs/core'\nimport { createContext } from '@silkweave/core'\nimport { ControllerDiscovery } from './controllerDiscovery.js'\nimport { SILKWEAVE_MODULE_OPTIONS, type SilkweaveModuleOptions } from './types.js'\n\n/**\n * Root module for `@silkweave/nestjs`.\n *\n * Discovers every `@Mcp`/`@Trpc`-decorated **controller method** via\n * `DiscoveryService`, reflects each into a Silkweave action (input schema from\n * the route + parameter decorators + optional OpenAPI document; invocation by\n * re-binding the validated input back into the method), and registers the\n * configured adapter(s) - `mcp()`, `trpc()`, `typegen()` - directly on Nest's\n * HTTP adapter inside `configure()`.\n *\n * Because `configure()` runs during `registerModules` - before Nest's\n * `registerRouter()` step - Silkweave's routes always sit ahead of every\n * controller in the Express stack. The controllers keep serving HTTP exactly as\n * before; `@Mcp` is purely additive.\n *\n * @example\n * ```ts\n * @Module({\n * imports: [\n * SilkweaveModule.forRoot({\n * silkweave: { name: 'app', description: 'My App', version: '1.0.0' },\n * adapters: [mcp({ basePath: '/mcp' })]\n * })\n * ],\n * controllers: [ChannelsController]\n * })\n * export class AppModule {}\n * ```\n */\n@Module({})\nexport class SilkweaveModule implements NestModule {\n constructor(\n @Inject(SILKWEAVE_MODULE_OPTIONS) private readonly options: SilkweaveModuleOptions,\n private readonly discovery: ControllerDiscovery,\n private readonly httpAdapterHost: HttpAdapterHost\n ) { }\n\n static forRoot(options: SilkweaveModuleOptions): DynamicModule {\n return {\n module: SilkweaveModule,\n global: true,\n imports: [DiscoveryModule],\n providers: [\n { provide: SILKWEAVE_MODULE_OPTIONS, useValue: options },\n ControllerDiscovery\n ],\n exports: []\n }\n }\n\n configure(_consumer: MiddlewareConsumer): void {\n const httpAdapter = this.httpAdapterHost.httpAdapter\n if (!httpAdapter) {\n throw new Error('@silkweave/nestjs: HttpAdapterHost.httpAdapter is not available.')\n }\n const allActions = this.discovery.discover({\n openapi: this.options.openapi,\n globalGuards: this.options.globalGuards,\n defaultResult: this.options.defaultResult\n })\n for (const adapter of this.options.adapters) {\n const baseContext = createContext({ ...(this.options.context ?? {}), adapter: adapter.name })\n const actions = adapter.allActions\n ? allActions\n : allActions.filter((a) => !a.isEnabled || a.isEnabled(baseContext))\n adapter.register({\n httpAdapter,\n silkweaveOptions: this.options.silkweave,\n baseContext,\n actions\n })\n }\n }\n}\n"],"mappings":"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"}
|
package/build/mcp.d.mts
CHANGED
package/build/mcp.mjs
CHANGED
|
@@ -50,8 +50,6 @@ function mcp(options = {}) {
|
|
|
50
50
|
if (options.sideloadResources !== false) adapter.get(`${basePath}/resource/:id`, ...prefix(corsHandler, protect(sideloadResource({ resourceDir: options.resourceDir }))));
|
|
51
51
|
const transport = mcpTransport(silkweaveOptions, baseContext, actions);
|
|
52
52
|
adapter.post(basePath, ...prefix(corsHandler, express.json(), protect(transport.post)));
|
|
53
|
-
adapter.get(basePath, ...prefix(corsHandler, protect(transport.stream)));
|
|
54
|
-
adapter.delete(basePath, ...prefix(corsHandler, protect(transport.stream)));
|
|
55
53
|
}
|
|
56
54
|
};
|
|
57
55
|
}
|
package/build/mcp.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp.mjs","names":[],"sources":["../src/adapter/mcp.ts"],"sourcesContent":["import { AuthConfig } from '@silkweave/auth'\nimport {\n authMiddleware,\n mcpCors,\n mcpTransport,\n oauthRoutes,\n protectedResourceMetadata,\n sideloadResource\n} from '@silkweave/mcp'\nimport { type CorsOptions } from 'cors'\nimport express, { type RequestHandler } from 'express'\nimport type { NestAdapterRegisterContext, NestSilkweaveAdapter } from '../lib/types.js'\n\nexport interface McpAdapterOptions {\n /** URL prefix the MCP namespace lives under - the transport itself is at this exact path. Default `'/mcp'`. */\n basePath?: string\n /** Optional bearer-token / OAuth 2.1 config. */\n auth?: AuthConfig\n /** CORS configuration. `false` to disable, `true`/omitted for permissive defaults, or a `CorsOptions` object. */\n cors?: CorsOptions | boolean\n /** Mount the sideload resource route at `${basePath}/resource/:id`. Default `true`. */\n sideloadResources?: boolean\n /** Directory the sideload route reads from. Default `'resources'`. */\n resourceDir?: string\n}\n\nfunction compose(...handlers: RequestHandler[]): RequestHandler {\n return (req, res, next) => {\n let i = 0\n const dispatch: () => void = () => {\n const h = handlers[i++]\n if (!h) { return next() }\n h(req, res, (err) => err ? next(err) : dispatch())\n }\n dispatch()\n }\n}\n\n/**\n * MCP adapter for `@silkweave/nestjs`. Registers the MCP Streamable HTTP\n * transport, sideload, well-known and OAuth routes individually on Nest's\n * HTTP adapter at the configured `basePath` (default `/mcp`):\n *\n * - `POST/GET/DELETE ${basePath}` - Streamable HTTP transport\n * - `GET ${basePath}/resource/:id` - sideload (`sideloadResources` opt-out)\n * - `GET ${basePath}/.well-known/oauth-protected-resource` - RFC 9728 metadata (when `auth.resourceUrl`/`auth.authorizationServers` set)\n * - `GET ${basePath}/authorize`, `POST ${basePath}/token`, `POST ${basePath}/register`, `GET ${basePath}${callbackPath}` (when `auth.provider` set)\n *\n * Each route is a real Nest-level route - they show up in\n * `RoutesResolver`'s log and there is no sub-app or middleware-slot\n * indirection.\n */\nexport function mcp(options: McpAdapterOptions = {}): NestSilkweaveAdapter {\n return {\n name: 'mcp',\n register({ httpAdapter, silkweaveOptions, baseContext, actions }: NestAdapterRegisterContext): void {\n const basePath = (options.basePath ?? '/mcp').replace(/\\/$/, '')\n if (!basePath) { throw new Error('@silkweave/nestjs mcp(): basePath cannot be empty or \"/\" - pick a path like \"/mcp\".') }\n\n const adapter = httpAdapter as unknown as {\n get: (path: string, ...h: RequestHandler[]) => unknown\n post: (path: string, ...h: RequestHandler[]) => unknown\n delete: (path: string, ...h: RequestHandler[]) => unknown\n }\n\n const corsHandler = mcpCors(options.cors ?? true)\n const auth = options.auth\n const guard = auth ? authMiddleware(auth, baseContext) : null\n const prefix = (...handlers: (RequestHandler | null)[]): RequestHandler[] =>\n handlers.filter((h): h is RequestHandler => Boolean(h))\n\n // Public auth-discovery / OAuth routes - registered first so they're\n // never inadvertently guarded by the auth middleware.\n if (auth?.authorizationServers?.length && auth.resourceUrl) {\n adapter.get(\n `${basePath}/.well-known/oauth-protected-resource`,\n ...prefix(corsHandler, protectedResourceMetadata(auth))\n )\n }\n if (auth?.provider) {\n const oauth = oauthRoutes(auth)\n adapter.get(`${basePath}/.well-known/oauth-authorization-server`, ...prefix(corsHandler, oauth.wellKnownAuthServer))\n adapter.get(`${basePath}/authorize`, ...prefix(corsHandler, oauth.authorize))\n adapter.get(`${basePath}${oauth.callbackPath}`, ...prefix(corsHandler, oauth.callback))\n adapter.post(`${basePath}/token`, ...prefix(corsHandler, ...oauth.token))\n adapter.post(`${basePath}/register`, ...prefix(corsHandler, ...oauth.register))\n }\n\n // Protected routes - wrapped with auth middleware (when configured).\n const protect = guard ? (h: RequestHandler) => compose(guard, h) : (h: RequestHandler) => h\n\n if (options.sideloadResources !== false) {\n adapter.get(`${basePath}/resource/:id`, ...prefix(corsHandler, protect(sideloadResource({ resourceDir: options.resourceDir }))))\n }\n\n const transport = mcpTransport(silkweaveOptions, baseContext, actions)\n adapter.post(basePath, ...prefix(corsHandler, express.json(), protect(transport.post)))\n
|
|
1
|
+
{"version":3,"file":"mcp.mjs","names":[],"sources":["../src/adapter/mcp.ts"],"sourcesContent":["import { AuthConfig } from '@silkweave/auth'\nimport {\n authMiddleware,\n mcpCors,\n mcpTransport,\n oauthRoutes,\n protectedResourceMetadata,\n sideloadResource\n} from '@silkweave/mcp'\nimport { type CorsOptions } from 'cors'\nimport express, { type RequestHandler } from 'express'\nimport type { NestAdapterRegisterContext, NestSilkweaveAdapter } from '../lib/types.js'\n\nexport interface McpAdapterOptions {\n /** URL prefix the MCP namespace lives under - the transport itself is at this exact path. Default `'/mcp'`. */\n basePath?: string\n /** Optional bearer-token / OAuth 2.1 config. */\n auth?: AuthConfig\n /** CORS configuration. `false` to disable, `true`/omitted for permissive defaults, or a `CorsOptions` object. */\n cors?: CorsOptions | boolean\n /** Mount the sideload resource route at `${basePath}/resource/:id`. Default `true`. */\n sideloadResources?: boolean\n /** Directory the sideload route reads from. Default `'resources'`. */\n resourceDir?: string\n}\n\nfunction compose(...handlers: RequestHandler[]): RequestHandler {\n return (req, res, next) => {\n let i = 0\n const dispatch: () => void = () => {\n const h = handlers[i++]\n if (!h) { return next() }\n h(req, res, (err) => err ? next(err) : dispatch())\n }\n dispatch()\n }\n}\n\n/**\n * MCP adapter for `@silkweave/nestjs`. Registers the MCP Streamable HTTP\n * transport, sideload, well-known and OAuth routes individually on Nest's\n * HTTP adapter at the configured `basePath` (default `/mcp`):\n *\n * - `POST/GET/DELETE ${basePath}` - Streamable HTTP transport\n * - `GET ${basePath}/resource/:id` - sideload (`sideloadResources` opt-out)\n * - `GET ${basePath}/.well-known/oauth-protected-resource` - RFC 9728 metadata (when `auth.resourceUrl`/`auth.authorizationServers` set)\n * - `GET ${basePath}/authorize`, `POST ${basePath}/token`, `POST ${basePath}/register`, `GET ${basePath}${callbackPath}` (when `auth.provider` set)\n *\n * Each route is a real Nest-level route - they show up in\n * `RoutesResolver`'s log and there is no sub-app or middleware-slot\n * indirection.\n */\nexport function mcp(options: McpAdapterOptions = {}): NestSilkweaveAdapter {\n return {\n name: 'mcp',\n register({ httpAdapter, silkweaveOptions, baseContext, actions }: NestAdapterRegisterContext): void {\n const basePath = (options.basePath ?? '/mcp').replace(/\\/$/, '')\n if (!basePath) { throw new Error('@silkweave/nestjs mcp(): basePath cannot be empty or \"/\" - pick a path like \"/mcp\".') }\n\n const adapter = httpAdapter as unknown as {\n get: (path: string, ...h: RequestHandler[]) => unknown\n post: (path: string, ...h: RequestHandler[]) => unknown\n delete: (path: string, ...h: RequestHandler[]) => unknown\n }\n\n const corsHandler = mcpCors(options.cors ?? true)\n const auth = options.auth\n const guard = auth ? authMiddleware(auth, baseContext) : null\n const prefix = (...handlers: (RequestHandler | null)[]): RequestHandler[] =>\n handlers.filter((h): h is RequestHandler => Boolean(h))\n\n // Public auth-discovery / OAuth routes - registered first so they're\n // never inadvertently guarded by the auth middleware.\n if (auth?.authorizationServers?.length && auth.resourceUrl) {\n adapter.get(\n `${basePath}/.well-known/oauth-protected-resource`,\n ...prefix(corsHandler, protectedResourceMetadata(auth))\n )\n }\n if (auth?.provider) {\n const oauth = oauthRoutes(auth)\n adapter.get(`${basePath}/.well-known/oauth-authorization-server`, ...prefix(corsHandler, oauth.wellKnownAuthServer))\n adapter.get(`${basePath}/authorize`, ...prefix(corsHandler, oauth.authorize))\n adapter.get(`${basePath}${oauth.callbackPath}`, ...prefix(corsHandler, oauth.callback))\n adapter.post(`${basePath}/token`, ...prefix(corsHandler, ...oauth.token))\n adapter.post(`${basePath}/register`, ...prefix(corsHandler, ...oauth.register))\n }\n\n // Protected routes - wrapped with auth middleware (when configured).\n const protect = guard ? (h: RequestHandler) => compose(guard, h) : (h: RequestHandler) => h\n\n if (options.sideloadResources !== false) {\n adapter.get(`${basePath}/resource/:id`, ...prefix(corsHandler, protect(sideloadResource({ resourceDir: options.resourceDir }))))\n }\n\n const transport = mcpTransport(silkweaveOptions, baseContext, actions)\n adapter.post(basePath, ...prefix(corsHandler, express.json(), protect(transport.post)))\n }\n }\n}\n"],"mappings":";;;AA0BA,SAAS,QAAQ,GAAG,UAA4C;AAC9D,SAAQ,KAAK,KAAK,SAAS;EACzB,IAAI,IAAI;EACR,MAAM,iBAA6B;GACjC,MAAM,IAAI,SAAS;AACnB,OAAI,CAAC,EAAK,QAAO,MAAM;AACvB,KAAE,KAAK,MAAM,QAAQ,MAAM,KAAK,IAAI,GAAG,UAAU,CAAC;;AAEpD,YAAU;;;;;;;;;;;;;;;;;AAkBd,SAAgB,IAAI,UAA6B,EAAE,EAAwB;AACzE,QAAO;EACL,MAAM;EACN,SAAS,EAAE,aAAa,kBAAkB,aAAa,WAA6C;GAClG,MAAM,YAAY,QAAQ,YAAY,QAAQ,QAAQ,OAAO,GAAG;AAChE,OAAI,CAAC,SAAY,OAAM,IAAI,MAAM,0FAAsF;GAEvH,MAAM,UAAU;GAMhB,MAAM,cAAc,QAAQ,QAAQ,QAAQ,KAAK;GACjD,MAAM,OAAO,QAAQ;GACrB,MAAM,QAAQ,OAAO,eAAe,MAAM,YAAY,GAAG;GACzD,MAAM,UAAU,GAAG,aACjB,SAAS,QAAQ,MAA2B,QAAQ,EAAE,CAAC;AAIzD,OAAI,MAAM,sBAAsB,UAAU,KAAK,YAC7C,SAAQ,IACN,GAAG,SAAS,wCACZ,GAAG,OAAO,aAAa,0BAA0B,KAAK,CAAC,CACxD;AAEH,OAAI,MAAM,UAAU;IAClB,MAAM,QAAQ,YAAY,KAAK;AAC/B,YAAQ,IAAI,GAAG,SAAS,0CAA0C,GAAG,OAAO,aAAa,MAAM,oBAAoB,CAAC;AACpH,YAAQ,IAAI,GAAG,SAAS,aAAa,GAAG,OAAO,aAAa,MAAM,UAAU,CAAC;AAC7E,YAAQ,IAAI,GAAG,WAAW,MAAM,gBAAgB,GAAG,OAAO,aAAa,MAAM,SAAS,CAAC;AACvF,YAAQ,KAAK,GAAG,SAAS,SAAS,GAAG,OAAO,aAAa,GAAG,MAAM,MAAM,CAAC;AACzE,YAAQ,KAAK,GAAG,SAAS,YAAY,GAAG,OAAO,aAAa,GAAG,MAAM,SAAS,CAAC;;GAIjF,MAAM,UAAU,SAAS,MAAsB,QAAQ,OAAO,EAAE,IAAI,MAAsB;AAE1F,OAAI,QAAQ,sBAAsB,MAChC,SAAQ,IAAI,GAAG,SAAS,gBAAgB,GAAG,OAAO,aAAa,QAAQ,iBAAiB,EAAE,aAAa,QAAQ,aAAa,CAAC,CAAC,CAAC,CAAC;GAGlI,MAAM,YAAY,aAAa,kBAAkB,aAAa,QAAQ;AACtE,WAAQ,KAAK,UAAU,GAAG,OAAO,aAAa,QAAQ,MAAM,EAAE,QAAQ,UAAU,KAAK,CAAC,CAAC;;EAE1F"}
|
package/build/trpc.d.mts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@silkweave/nestjs",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.1.0",
|
|
4
4
|
"description": "Silkweave NestJS Adapter",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://www.silkweave.dev",
|
|
@@ -44,12 +44,12 @@
|
|
|
44
44
|
"@nestjs/common": "^10.0.0 || ^11.0.0",
|
|
45
45
|
"@nestjs/core": "^10.0.0 || ^11.0.0",
|
|
46
46
|
"@nestjs/swagger": "^7.0.0 || ^8.0.0 || ^11.0.0",
|
|
47
|
-
"rxjs": "^7.0.0",
|
|
48
47
|
"@trpc/server": "^11.7.1",
|
|
49
48
|
"class-validator": "^0.14.0 || ^0.15.0",
|
|
50
|
-
"
|
|
51
|
-
"@silkweave/
|
|
52
|
-
"@silkweave/trpc": "^
|
|
49
|
+
"rxjs": "^7.0.0",
|
|
50
|
+
"@silkweave/mcp": "^3.1.0",
|
|
51
|
+
"@silkweave/trpc": "^3.1.0",
|
|
52
|
+
"@silkweave/typegen": "^3.1.0"
|
|
53
53
|
},
|
|
54
54
|
"peerDependenciesMeta": {
|
|
55
55
|
"@nestjs/swagger": {
|
|
@@ -75,7 +75,7 @@
|
|
|
75
75
|
"cors": "^2.8.6",
|
|
76
76
|
"express": "^5.2.1",
|
|
77
77
|
"zod": "^3.25.0",
|
|
78
|
-
"@silkweave/core": "
|
|
78
|
+
"@silkweave/core": "3.1.0"
|
|
79
79
|
},
|
|
80
80
|
"devDependencies": {
|
|
81
81
|
"@eslint/js": "^10.0.1",
|
|
@@ -95,10 +95,11 @@
|
|
|
95
95
|
"tsx": "^4.21.0",
|
|
96
96
|
"typescript": "^5.9.3",
|
|
97
97
|
"typescript-eslint": "^8.56.1",
|
|
98
|
-
"
|
|
99
|
-
"@silkweave/mcp": "
|
|
100
|
-
"@silkweave/trpc": "
|
|
101
|
-
"@silkweave/typegen": "
|
|
98
|
+
"vitest": "^4.1.9",
|
|
99
|
+
"@silkweave/mcp": "3.1.0",
|
|
100
|
+
"@silkweave/trpc": "3.1.0",
|
|
101
|
+
"@silkweave/typegen": "3.1.0",
|
|
102
|
+
"@silkweave/auth": "3.1.0"
|
|
102
103
|
},
|
|
103
104
|
"scripts": {
|
|
104
105
|
"clean": "rimraf build",
|
|
@@ -106,6 +107,7 @@
|
|
|
106
107
|
"watch": "tsdown --watch",
|
|
107
108
|
"typecheck": "tsc --noEmit",
|
|
108
109
|
"lint": "eslint",
|
|
109
|
-
"check": "pnpm lint && pnpm typecheck"
|
|
110
|
+
"check": "pnpm lint && pnpm typecheck",
|
|
111
|
+
"test": "vitest run"
|
|
110
112
|
}
|
|
111
113
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index-C1W-O7EX.d.mts","names":["SilkweaveContext","AuthError","Error","code","statusCode","constructor","message","invalidToken","insufficientScope","extractBearerToken","header","buildWWWAuthenticate","error","description","resourceMetadataUrl","ProtectedResourceMetadata","resource","authorization_servers","scopes_supported","bearer_methods_supported","generateProtectedResourceMetadata","resourceUrl","authorizationServers","AuthInfo","token","clientId","scopes","expiresAt","key","OAuthRequest","URL","Record","method","url","headers","body","OAuthResponse","status","OAuthProvider","Promise","authorize","req","callback","register","metadata","verifyToken","VerifyToken","context","AuthConfig","required","requiredScopes","provider","callbackPath","AuthCodeData","redirectUri","codeChallenge","codeChallengeMethod","upstreamAccessToken","upstreamIdToken","email","sub","PendingAuthData","scope","clientState","ClientRegistration","clientSecret","redirectUris","clientName","createdAt","RefreshTokenData","OAuthStore","saveAuthCode","data","getAuthCode","deleteAuthCode","savePendingAuth","state","getPendingAuth","deletePendingAuth","savePkceVerifier","verifier","getPkceVerifier","deletePkceVerifier","saveClient","getClient","saveRefreshToken","getRefreshToken","deleteRefreshToken","GoogleOAuthOptions","signingKey","tokenTtl","store","google","options","OAuthProxyConfig","authorizeUrl","tokenUrl","userinfoUrl","createOAuthProxy","config","matchRedirectUri","uri","patterns","createJsonStore","path","createMemoryStore","RedisClient","get","set","value","ex","del","RedisStoreOptions","client","prefix","createRedisStore","ValidateResult","auth","error_description","validateToken","authorizationHeader"],"sources":["../../auth/build/index.d.mts"],"mappings":";;;;;UAyBUuB,QAAAA;EACRC,KAAAA;EACAC,QAAAA;EACAC,MAAAA;EACAC,SAAAA;EAAAA,CACCC,GAAAA;AAAAA;AAAAA,UAEOC,YAAAA;EACRG,MAAAA;EACAC,GAAAA,EAAKH,GAAAA;EACLI,OAAAA,EAASH,MAAAA;EACTI,IAAAA,GAAOJ,MAAAA;AAAAA;AAAAA,UAECK,aAAAA;EACRC,MAAAA;EACAH,OAAAA,EAASH,MAAAA;EACTI,IAAAA,YAAgBJ,MAAAA;AAAAA;AAAAA,UAERO,aAAAA;EACRE,SAAAA,CAAUC,GAAAA,EAAKZ,YAAAA,GAAeU,OAAAA,CAAQH,aAAAA;EACtCM,QAAAA,CAASD,GAAAA,EAAKZ,YAAAA,GAAeU,OAAAA,CAAQH,aAAAA;EACrCZ,KAAAA,CAAMiB,GAAAA,EAAKZ,YAAAA,GAAeU,OAAAA,CAAQH,aAAAA;EAClCO,QAAAA,CAASF,GAAAA,EAAKZ,YAAAA,GAAeU,OAAAA,CAAQH,aAAAA;EACrCQ,QAAAA,IAAYR,aAAAA;EACZS,WAAAA,CAAYrB,KAAAA,WAAgBe,OAAAA,CAAQhB,QAAAA;AAAAA;AAAAA;AAAAA,KAIjCuB,WAAAA,IAAetB,KAAAA,UAAeuB,OAAAA,EAAS/C,gBAAAA,KAAqBuC,OAAAA,CAAQhB,QAAAA;AAAAA,UAC/DyB,UAAAA;EACRH,WAAAA,EAAaC,WAAAA;EACbG,QAAAA;EACA5B,WAAAA;EACAC,oBAAAA;EACA4B,cAAAA;EACAC,QAAAA,GAAWb,aAAAA;EACXc,YAAAA;AAAAA;AAAAA"}
|