@silkweave/nestjs 1.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +17 -0
- package/.turbo/turbo-check.log +4 -0
- package/README.md +210 -0
- package/build/index.d.mts +315 -0
- package/build/index.d.mts.map +1 -0
- package/build/index.mjs +9231 -0
- package/build/index.mjs.map +1 -0
- package/eslint.config.mjs +93 -0
- package/package.json +52 -0
- package/src/adapter/mcp.ts +55 -0
- package/src/adapter/rest.ts +179 -0
- package/src/adapter/trpc.ts +82 -0
- package/src/decorator/action.ts +38 -0
- package/src/decorator/actions.ts +25 -0
- package/src/index.ts +12 -0
- package/src/lib/discovery.ts +90 -0
- package/src/lib/executionContext.ts +76 -0
- package/src/lib/filter.ts +26 -0
- package/src/lib/guards.ts +64 -0
- package/src/lib/metadata.ts +45 -0
- package/src/lib/silkweave.module.ts +52 -0
- package/src/lib/silkweave.service.ts +58 -0
- package/src/lib/slot.ts +51 -0
- package/src/lib/types.ts +37 -0
- package/tsconfig.json +25 -0
- package/tsconfig.tsbuildinfo +1 -0
- package/tsdown.config.ts +7 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
$ tsdown
|
|
2
|
+
[34mℹ[39m [34mtsdown v0.21.8[39m powered by [38;2;255;126;23mrolldown v1.0.0-rc.15[39m
|
|
3
|
+
[34mℹ[39m config file: [4m/Users/atomic/projects/silkweave/silkweave/packages/nestjs/tsdown.config.ts[24m
|
|
4
|
+
[34mℹ[39m entry: [34msrc/index.ts[39m
|
|
5
|
+
[34mℹ[39m tsconfig: [34mtsconfig.json[39m
|
|
6
|
+
[34mℹ[39m Build start
|
|
7
|
+
[34mℹ[39m Cleaning 4 files
|
|
8
|
+
[34mℹ[39m Hint: consider adding [34mdeps.onlyBundle[39m option to avoid unintended bundling of dependencies, or set [34mdeps.onlyBundle: false[39m to disable this hint.
|
|
9
|
+
See more at [4mhttps://tsdown.dev/options/dependencies#deps-onlybundle[24m
|
|
10
|
+
Detected dependencies in bundle:
|
|
11
|
+
- [34mrxjs[39m
|
|
12
|
+
[34mℹ[39m [2mbuild/[22m[1mindex.mjs[22m [2m336.69 kB[22m [2m│ gzip: 48.97 kB[22m
|
|
13
|
+
[34mℹ[39m [2mbuild/[22mindex.mjs.map [2m574.23 kB[22m [2m│ gzip: 86.16 kB[22m
|
|
14
|
+
[34mℹ[39m [2mbuild/[22mindex.d.mts.map [2m 2.82 kB[22m [2m│ gzip: 1.03 kB[22m
|
|
15
|
+
[34mℹ[39m [2mbuild/[22m[32m[1mindex.d.mts[22m[39m [2m 14.64 kB[22m [2m│ gzip: 4.94 kB[22m
|
|
16
|
+
[34mℹ[39m 4 files, total: 928.38 kB
|
|
17
|
+
[32m✔[39m Build complete in [32m815ms[39m
|
package/README.md
ADDED
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
# @silkweave/nestjs
|
|
2
|
+
|
|
3
|
+
NestJS adapter for [Silkweave](https://github.com/silkweave/silkweave). Define actions as method decorators on Nest providers, then expose them simultaneously over REST, tRPC, and MCP Streamable HTTP — all mounted on the running Nest HTTP server so Nest middleware, guards, and lifecycle hooks stay coherent.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pnpm add @silkweave/core @silkweave/nestjs @nestjs/common @nestjs/core @nestjs/platform-express reflect-metadata
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
> NestJS dev workflows need decorator-aware transforms. Recommend `@swc-node/register` (`node --import @swc-node/register/esm-register src/main.ts`) or the standard `nest start` CLI; plain `tsx` doesn't emit decorator metadata.
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
// users.actions.ts
|
|
17
|
+
import { Injectable, UseGuards } from '@nestjs/common'
|
|
18
|
+
import { type SilkweaveContext } from '@silkweave/core'
|
|
19
|
+
import { Action, Actions } from '@silkweave/nestjs'
|
|
20
|
+
import z from 'zod/v4'
|
|
21
|
+
import { AdminGuard } from './admin.guard.js'
|
|
22
|
+
|
|
23
|
+
const ListInput = z.object({ activeOnly: z.coerce.boolean().optional() })
|
|
24
|
+
const GetInput = z.object({ id: z.string() })
|
|
25
|
+
const BanInput = z.object({ id: z.string(), reason: z.string() })
|
|
26
|
+
|
|
27
|
+
@Injectable()
|
|
28
|
+
@Actions('users')
|
|
29
|
+
export class UserActions {
|
|
30
|
+
constructor(private readonly db: DbService) {}
|
|
31
|
+
|
|
32
|
+
@Action({
|
|
33
|
+
description: 'List users',
|
|
34
|
+
input: ListInput,
|
|
35
|
+
kind: 'query'
|
|
36
|
+
})
|
|
37
|
+
list(input: z.infer<typeof ListInput>, _ctx: SilkweaveContext) {
|
|
38
|
+
return this.db.listUsers(input.activeOnly)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
@Action({
|
|
42
|
+
description: 'Get a single user by ID',
|
|
43
|
+
input: GetInput,
|
|
44
|
+
kind: 'query'
|
|
45
|
+
})
|
|
46
|
+
get(input: z.infer<typeof GetInput>) {
|
|
47
|
+
return this.db.getUser(input.id)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
@UseGuards(AdminGuard)
|
|
51
|
+
@Action({
|
|
52
|
+
description: 'Ban a user',
|
|
53
|
+
input: BanInput,
|
|
54
|
+
transports: ['rest', 'trpc'] // exclude from MCP tools
|
|
55
|
+
})
|
|
56
|
+
ban(input: z.infer<typeof BanInput>) {
|
|
57
|
+
return this.db.banUser(input.id, input.reason)
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
```ts
|
|
63
|
+
// app.module.ts
|
|
64
|
+
import { Module } from '@nestjs/common'
|
|
65
|
+
import { mcp, rest, SilkweaveModule, trpc } from '@silkweave/nestjs'
|
|
66
|
+
import { AdminGuard } from './admin.guard.js'
|
|
67
|
+
import { UserActions } from './users.actions.js'
|
|
68
|
+
|
|
69
|
+
@Module({
|
|
70
|
+
imports: [
|
|
71
|
+
SilkweaveModule.forRoot({
|
|
72
|
+
silkweave: { name: 'my-app', description: 'My App', version: '1.0.0' },
|
|
73
|
+
adapters: [
|
|
74
|
+
rest({ basePath: '/api' }),
|
|
75
|
+
trpc({ basePath: '/trpc' }),
|
|
76
|
+
mcp({ basePath: '/' })
|
|
77
|
+
]
|
|
78
|
+
})
|
|
79
|
+
],
|
|
80
|
+
providers: [AdminGuard, UserActions]
|
|
81
|
+
})
|
|
82
|
+
export class AppModule {}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
```ts
|
|
86
|
+
// main.ts
|
|
87
|
+
import 'reflect-metadata'
|
|
88
|
+
import { NestFactory } from '@nestjs/core'
|
|
89
|
+
import { AppModule } from './app.module.js'
|
|
90
|
+
|
|
91
|
+
const app = await NestFactory.create(AppModule)
|
|
92
|
+
await app.listen(8080)
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
The `users.list` and `users.get` actions are now reachable via:
|
|
96
|
+
|
|
97
|
+
- **REST:** `GET /api/users/list?activeOnly=true` and `GET /api/users/get?id=1`
|
|
98
|
+
- **tRPC:** `client.usersList.query({ activeOnly: true })` and `client.usersGet.query({ id: '1' })`
|
|
99
|
+
- **MCP:** tools `UsersList` and `UsersGet`
|
|
100
|
+
|
|
101
|
+
`users.ban` skips MCP per its `transports: ['rest', 'trpc']` and is guarded by `@UseGuards(AdminGuard)` on every transport that has an HTTP request.
|
|
102
|
+
|
|
103
|
+
## Decorators
|
|
104
|
+
|
|
105
|
+
### `@Action(options)` (method decorator)
|
|
106
|
+
|
|
107
|
+
| Option | Type | Default | Description |
|
|
108
|
+
|--------|------|---------|-------------|
|
|
109
|
+
| `name` | `string` | kebab-cased method name | Override the action name. Joined with the class prefix via `.` |
|
|
110
|
+
| `description` | `string` | *required* | Human-readable summary. Used as MCP tool description |
|
|
111
|
+
| `input` | `z.ZodObject` | *required* | Zod object schema for the action's input |
|
|
112
|
+
| `output` | `z.ZodObject` | — | Optional output schema (used by tRPC type inference) |
|
|
113
|
+
| `kind` | `'query' \| 'mutation'` | `'mutation'` | `'query'` → GET in REST, `.query()` in tRPC. `'mutation'` → POST / `.mutation()` |
|
|
114
|
+
| `transports` | `('rest' \| 'trpc' \| 'mcp')[]` | all | Allowlist of transports that expose this action |
|
|
115
|
+
| `isEnabled` | `(ctx) => boolean` | — | Dynamic gate (AND-combined with `transports`) |
|
|
116
|
+
| `toolResult` | `(response, ctx) => CallToolResult` | — | Custom MCP `CallToolResult` formatter |
|
|
117
|
+
|
|
118
|
+
### `@Actions(prefix?)` (class decorator)
|
|
119
|
+
|
|
120
|
+
Groups a class's actions under a common prefix. Joined to method-level names with a dot.
|
|
121
|
+
|
|
122
|
+
```ts
|
|
123
|
+
@Actions('users')
|
|
124
|
+
class UserActions {
|
|
125
|
+
@Action({ ... }) list(...) {} // action name: 'users.list'
|
|
126
|
+
@Action({ name: 'top' }) ... {} // action name: 'users.top'
|
|
127
|
+
}
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
Accepts either a string (shorthand) or `{ prefix, transports }` for a class-wide transport default.
|
|
131
|
+
|
|
132
|
+
## Adapters
|
|
133
|
+
|
|
134
|
+
### `rest(options?)`
|
|
135
|
+
|
|
136
|
+
Maps actions to REST routes on the Nest HTTP server.
|
|
137
|
+
|
|
138
|
+
| Option | Type | Default | Description |
|
|
139
|
+
|--------|------|---------|-------------|
|
|
140
|
+
| `basePath` | `string` | `'/'` | URL prefix joined to each action's path |
|
|
141
|
+
| `auth` | `AuthConfig` | — | `@silkweave/auth` bearer-token config |
|
|
142
|
+
|
|
143
|
+
Routes follow `{basePath}/{action-name-with-slashes}` where dots in action names become slashes:
|
|
144
|
+
|
|
145
|
+
- `users.list` (query) → `GET /api/users/list`
|
|
146
|
+
- `users.ban` (mutation) → `POST /api/users/ban`
|
|
147
|
+
|
|
148
|
+
Input is parsed from `req.query` (queries) or `req.body` (mutations) and validated against the action's Zod schema; validation failures return HTTP 400 with the Zod issues.
|
|
149
|
+
|
|
150
|
+
### `trpc(options?)`
|
|
151
|
+
|
|
152
|
+
Mounts a tRPC HTTP handler built from `@silkweave/trpc`'s `buildRouter`.
|
|
153
|
+
|
|
154
|
+
| Option | Type | Default | Description |
|
|
155
|
+
|--------|------|---------|-------------|
|
|
156
|
+
| `basePath` | `string` | `'/trpc'` | URL prefix the tRPC handler listens on |
|
|
157
|
+
| `auth` | `AuthConfig` | — | `@silkweave/auth` bearer-token config |
|
|
158
|
+
|
|
159
|
+
Action names with dots (e.g. `users.list`) collapse to camelCase procedure keys (`usersList`) — flat router in v1.
|
|
160
|
+
|
|
161
|
+
### `mcp(options?)`
|
|
162
|
+
|
|
163
|
+
Mounts MCP Streamable HTTP at `{basePath}/mcp`, plus optional OAuth routes when `auth.provider` is set. Reuses `@silkweave/mcp`'s `createMcpExpressHandler`.
|
|
164
|
+
|
|
165
|
+
| Option | Type | Default | Description |
|
|
166
|
+
|--------|------|---------|-------------|
|
|
167
|
+
| `basePath` | `string` | `'/'` | Mount point for the MCP sub-app |
|
|
168
|
+
| `auth` | `AuthConfig` | — | Bearer-token / OAuth 2.1 config |
|
|
169
|
+
| `cors` | `CorsOptions \| boolean` | `true` | CORS config (see `@silkweave/mcp`) |
|
|
170
|
+
|
|
171
|
+
## Guards & DI
|
|
172
|
+
|
|
173
|
+
Native NestJS `@UseGuards()` and `@UseInterceptors()` on `@Action` methods run for every HTTP-backed transport. Guards receive an `ExecutionContext` with the HTTP request in `switchToHttp().getRequest()`. The `Reflector` is also wired up so guards can read custom metadata.
|
|
174
|
+
|
|
175
|
+
Action methods are normal Nest provider methods — inject services via the constructor as usual.
|
|
176
|
+
|
|
177
|
+
```ts
|
|
178
|
+
@Injectable()
|
|
179
|
+
class MyActions {
|
|
180
|
+
constructor(
|
|
181
|
+
private readonly db: DbService,
|
|
182
|
+
private readonly cache: CacheService
|
|
183
|
+
) {}
|
|
184
|
+
|
|
185
|
+
@UseGuards(AuthGuard, RateLimitGuard)
|
|
186
|
+
@Action({ description: '...', input: z.object({...}) })
|
|
187
|
+
async myAction(input, ctx) {
|
|
188
|
+
return this.db.query(...)
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
## Action name → transport path
|
|
194
|
+
|
|
195
|
+
| Action name | REST path | tRPC procedure | MCP tool |
|
|
196
|
+
|-------------|-----------|----------------|----------|
|
|
197
|
+
| `hello` | `/hello` | `hello` | `Hello` |
|
|
198
|
+
| `users.list` | `/users/list` | `usersList` | `UsersList` |
|
|
199
|
+
| `posts.get-by-id` | `/posts/get-by-id` | `postsGetById` | `PostsGetById` |
|
|
200
|
+
|
|
201
|
+
## Notes
|
|
202
|
+
|
|
203
|
+
- **Lifecycle:** adapters mount their route slots in `OnModuleInit` (before Nest's 404 catch-all is installed) and populate the handlers in `OnApplicationBootstrap` after `@Action` discovery.
|
|
204
|
+
- **Express only by default.** `@nestjs/platform-fastify` requires `@fastify/express` registered upfront so Nest can serve Express-style middleware (used by all three adapters internally).
|
|
205
|
+
- **Query coercion for REST queries:** request query strings are always strings; use `z.coerce.boolean()` / `z.coerce.number()` in your Zod schemas for queries.
|
|
206
|
+
- **`reflect-metadata`** must be imported once at the top of your entry file (typical Nest requirement).
|
|
207
|
+
|
|
208
|
+
## License
|
|
209
|
+
|
|
210
|
+
ISC. See [LICENSE](./LICENSE).
|
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
import { CreateMcpExpressHandlerOptions } from "@silkweave/mcp";
|
|
2
|
+
import { CanActivate, DynamicModule, OnApplicationBootstrap, OnApplicationShutdown, OnModuleInit, Type } from "@nestjs/common";
|
|
3
|
+
import { AuthConfig } from "@silkweave/auth";
|
|
4
|
+
import { Action as Action$1, ActionKind, AdapterGenerator, Silkweave, SilkweaveContext, SilkweaveOptions } from "@silkweave/core";
|
|
5
|
+
import z$1 from "zod/v4";
|
|
6
|
+
import { InferTrpcRouter } from "@silkweave/trpc";
|
|
7
|
+
import { DiscoveryService, HttpAdapterHost, MetadataScanner, ModuleRef, Reflector } from "@nestjs/core";
|
|
8
|
+
|
|
9
|
+
//#region src/lib/types.d.ts
|
|
10
|
+
/**
|
|
11
|
+
* A Silkweave NestJS adapter. Each transport (REST, tRPC, MCP) implements this
|
|
12
|
+
* shape: given a Nest `HttpAdapterHost`, it (a) immediately mounts a
|
|
13
|
+
* placeholder middleware slot on Nest's running HTTP server during
|
|
14
|
+
* `OnModuleInit` — which is critical because Nest installs its 404 catch-all
|
|
15
|
+
* later in `init()`, before `OnApplicationBootstrap` fires; routes registered
|
|
16
|
+
* after the catch-all are unreachable — and (b) returns a core
|
|
17
|
+
* `AdapterGenerator` whose `start(actions)` populates that slot with the real
|
|
18
|
+
* handler.
|
|
19
|
+
*
|
|
20
|
+
* Adapters mount onto Nest's HTTP server instead of owning their own, so Nest
|
|
21
|
+
* middleware, lifecycle hooks, and request scoping remain coherent.
|
|
22
|
+
*/
|
|
23
|
+
interface NestSilkweaveAdapter {
|
|
24
|
+
/** Adapter discriminator — set on the silkweave context as `ctx.get('adapter')`. */
|
|
25
|
+
readonly name: 'rest' | 'trpc' | 'mcp';
|
|
26
|
+
/**
|
|
27
|
+
* Reserve the adapter's route prefix on the Nest HTTP server *now* (before
|
|
28
|
+
* Nest's 404 catch-all is installed) and return the core `AdapterGenerator`
|
|
29
|
+
* that will populate the slot during `silkweave().start()`.
|
|
30
|
+
*/
|
|
31
|
+
install(host: HttpAdapterHost): AdapterGenerator;
|
|
32
|
+
}
|
|
33
|
+
interface SilkweaveModuleOptions {
|
|
34
|
+
/** Identity for the silkweave instance — surfaced to MCP clients, OpenAPI, etc. */
|
|
35
|
+
silkweave: SilkweaveOptions;
|
|
36
|
+
/** Adapters to mount. Examples: `rest()`, `trpc()`, `mcp()`. */
|
|
37
|
+
adapters: NestSilkweaveAdapter[];
|
|
38
|
+
/** Initial context keys (equivalent to chaining `.set(key, value)` on the builder). */
|
|
39
|
+
context?: Record<string, unknown>;
|
|
40
|
+
}
|
|
41
|
+
declare const SILKWEAVE_MODULE_OPTIONS = "__silkweave_module_options__";
|
|
42
|
+
//#endregion
|
|
43
|
+
//#region src/adapter/mcp.d.ts
|
|
44
|
+
interface McpAdapterOptions extends Omit<CreateMcpExpressHandlerOptions, 'auth'> {
|
|
45
|
+
/** URL prefix at which the MCP sub-app is mounted. Default `'/'` — the MCP transport then lives at `/mcp`, OAuth routes at `/authorize`, etc. */
|
|
46
|
+
basePath?: string;
|
|
47
|
+
/** Optional bearer-token / OAuth auth applied to MCP requests. Same shape as `@silkweave/mcp`'s `http()` auth. */
|
|
48
|
+
auth?: AuthConfig;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* MCP Streamable HTTP adapter for `@silkweave/nestjs`. Builds the same Express
|
|
52
|
+
* sub-app that `@silkweave/mcp`'s `http()` adapter uses internally (via
|
|
53
|
+
* `createMcpExpressHandler`) and mounts it on Nest's running HTTP server at
|
|
54
|
+
* the configured base path.
|
|
55
|
+
*
|
|
56
|
+
* Routes provided by the mounted sub-app:
|
|
57
|
+
* - `POST /mcp`, `GET /mcp`, `DELETE /mcp` — MCP Streamable HTTP transport
|
|
58
|
+
* - `GET /resource/:id` — sideload resources (large MCP responses)
|
|
59
|
+
* - `GET /.well-known/oauth-protected-resource` (when `auth.resourceUrl`/`auth.authorizationServers` set)
|
|
60
|
+
* - `GET /authorize`, `POST /token`, `POST /register`, `GET /auth/callback` (when `auth.provider` set)
|
|
61
|
+
*
|
|
62
|
+
* Note: this adapter mounts an Express sub-app. On `@nestjs/platform-fastify`,
|
|
63
|
+
* register `@fastify/express` before this adapter so Nest can serve Express
|
|
64
|
+
* middleware.
|
|
65
|
+
*/
|
|
66
|
+
declare function mcp(options?: McpAdapterOptions): NestSilkweaveAdapter;
|
|
67
|
+
//#endregion
|
|
68
|
+
//#region src/adapter/rest.d.ts
|
|
69
|
+
interface RestAdapterOptions {
|
|
70
|
+
/** URL prefix at which the REST routes are mounted. e.g. `'/api'` → `POST /api/users/list`. Default: `'/'`. */
|
|
71
|
+
basePath?: string;
|
|
72
|
+
/** Optional bearer-token auth applied to every REST action. */
|
|
73
|
+
auth?: AuthConfig;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* REST adapter for `@silkweave/nestjs`. Mounts each discovered `@Action` as a
|
|
77
|
+
* route on Nest's running HTTP server:
|
|
78
|
+
*
|
|
79
|
+
* - `kind: 'query'` → `GET ${basePath}/${actionName-with-slashes}` (input read from query string)
|
|
80
|
+
* - `kind: 'mutation'` → `POST ${basePath}/${actionName-with-slashes}` (input read from JSON body)
|
|
81
|
+
*
|
|
82
|
+
* Works on `@nestjs/platform-express` out of the box. For
|
|
83
|
+
* `@nestjs/platform-fastify`, register `@fastify/express` before this adapter
|
|
84
|
+
* so Nest can serve Express-style middleware.
|
|
85
|
+
*/
|
|
86
|
+
declare function rest(options?: RestAdapterOptions): NestSilkweaveAdapter;
|
|
87
|
+
//#endregion
|
|
88
|
+
//#region src/adapter/trpc.d.ts
|
|
89
|
+
interface TrpcAdapterOptions {
|
|
90
|
+
/** URL prefix at which the tRPC handler is mounted. Default `'/trpc'`. */
|
|
91
|
+
basePath?: string;
|
|
92
|
+
/** Optional bearer-token auth applied to every tRPC procedure. */
|
|
93
|
+
auth?: AuthConfig;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* tRPC adapter for `@silkweave/nestjs`. Builds a tRPC router from discovered
|
|
97
|
+
* `@Action` methods via `@silkweave/trpc`'s `buildRouter` and mounts the
|
|
98
|
+
* resulting `createExpressMiddleware()` at the configured base path on Nest's
|
|
99
|
+
* underlying HTTP server.
|
|
100
|
+
*
|
|
101
|
+
* Action names with dots (e.g. `users.list` from `@Actions('users')`) collapse
|
|
102
|
+
* to camelCase procedure keys (`usersList`) for v1 — flat router only.
|
|
103
|
+
*
|
|
104
|
+
* Works on `@nestjs/platform-express`. On `@nestjs/platform-fastify`, register
|
|
105
|
+
* `@fastify/express` first so Nest can mount Express-style middleware.
|
|
106
|
+
*/
|
|
107
|
+
declare function trpc(options?: TrpcAdapterOptions): NestSilkweaveAdapter;
|
|
108
|
+
//#endregion
|
|
109
|
+
//#region src/lib/metadata.d.ts
|
|
110
|
+
declare const ACTION_METADATA = "__silkweave_action__";
|
|
111
|
+
declare const ACTIONS_METADATA = "__silkweave_actions__";
|
|
112
|
+
type Transport = 'rest' | 'trpc' | 'mcp';
|
|
113
|
+
interface ActionMetadata<I extends object = object, O extends object = object> {
|
|
114
|
+
/** Action name. Defaults to the kebab-cased method name. */
|
|
115
|
+
name?: string;
|
|
116
|
+
/** Human-readable description. Becomes the MCP tool description and REST OpenAPI summary. */
|
|
117
|
+
description: string;
|
|
118
|
+
/** Zod object schema for the action's input. */
|
|
119
|
+
input: z$1.ZodType<I> & {
|
|
120
|
+
shape: Record<string, z$1.ZodTypeAny>;
|
|
121
|
+
};
|
|
122
|
+
/** Optional Zod object schema for the action's output (used by tRPC type inference). */
|
|
123
|
+
output?: z$1.ZodType<O> & {
|
|
124
|
+
shape: Record<string, z$1.ZodTypeAny>;
|
|
125
|
+
};
|
|
126
|
+
/** `'query'` (GET in REST, `.query()` in tRPC) or `'mutation'` (POST in REST, `.mutation()` in tRPC). Default: `'mutation'`. */
|
|
127
|
+
kind?: ActionKind;
|
|
128
|
+
/** Allowlist of transports that should expose this action. Default: all registered transports. */
|
|
129
|
+
transports?: Transport[];
|
|
130
|
+
/** Dynamic enable check (in addition to `transports`). AND-combined with the transports filter. */
|
|
131
|
+
isEnabled?: (context: SilkweaveContext) => boolean;
|
|
132
|
+
/** Custom MCP `CallToolResult` formatter. See `@silkweave/mcp`'s `smartToolResult`. */
|
|
133
|
+
toolResult?: Action$1<I, O>['toolResult'];
|
|
134
|
+
/** CLI positional-argument keys (unused for HTTP-only adapters, kept for parity with `createAction`). */
|
|
135
|
+
args?: (keyof I)[];
|
|
136
|
+
/** Custom MCP tool name override. If unset, derived from action name as PascalCase. */
|
|
137
|
+
mcpToolName?: string;
|
|
138
|
+
}
|
|
139
|
+
interface ActionsClassMetadata {
|
|
140
|
+
/** Prefix joined to the method-level action name with a dot. e.g. `Actions('users')` + method `list` → `users.list`. */
|
|
141
|
+
prefix?: string;
|
|
142
|
+
/** Class-level transports allowlist. Method-level `transports` overrides; otherwise inherits this. */
|
|
143
|
+
transports?: Transport[];
|
|
144
|
+
}
|
|
145
|
+
interface ResultToolResult<O extends object = object> {
|
|
146
|
+
toolResult?: Action$1<object, O>['toolResult'];
|
|
147
|
+
}
|
|
148
|
+
type AnyActionMetadata = ActionMetadata<object, object> & ResultToolResult<object>;
|
|
149
|
+
declare const ACTION_RESPONSE_KEY = "__silkweave_response__";
|
|
150
|
+
//#endregion
|
|
151
|
+
//#region src/decorator/action.d.ts
|
|
152
|
+
/**
|
|
153
|
+
* Method decorator that registers a Silkweave action.
|
|
154
|
+
*
|
|
155
|
+
* The decorated method becomes an Action and is exposed via every adapter
|
|
156
|
+
* configured on `SilkweaveModule` (REST/tRPC/MCP), unless `transports` is
|
|
157
|
+
* provided to restrict it.
|
|
158
|
+
*
|
|
159
|
+
* The method receives `(input, context)` where `input` is the parsed Zod input
|
|
160
|
+
* and `context` is the `SilkweaveContext` (with `logger`, `request`, optional
|
|
161
|
+
* `auth`). The class instance is a normal Nest provider, so other services can
|
|
162
|
+
* be injected via the constructor.
|
|
163
|
+
*
|
|
164
|
+
* @example
|
|
165
|
+
* ```ts
|
|
166
|
+
* @Injectable()
|
|
167
|
+
* @Actions('users')
|
|
168
|
+
* export class UserActions {
|
|
169
|
+
* constructor(private db: DbService) {}
|
|
170
|
+
*
|
|
171
|
+
* @Action({
|
|
172
|
+
* description: 'List users',
|
|
173
|
+
* input: z.object({ limit: z.number().optional() }),
|
|
174
|
+
* kind: 'query'
|
|
175
|
+
* })
|
|
176
|
+
* list(input: { limit?: number }, ctx: SilkweaveContext) {
|
|
177
|
+
* return this.db.listUsers(input.limit)
|
|
178
|
+
* }
|
|
179
|
+
* }
|
|
180
|
+
* ```
|
|
181
|
+
*/
|
|
182
|
+
declare function Action<I extends object = object, O extends object = object>(options: ActionMetadata<I, O>): MethodDecorator;
|
|
183
|
+
//#endregion
|
|
184
|
+
//#region src/decorator/actions.d.ts
|
|
185
|
+
/**
|
|
186
|
+
* Class decorator that groups a provider's `@Action` methods under a common
|
|
187
|
+
* prefix. The prefix is joined to each method's action name with a dot
|
|
188
|
+
* (e.g. `@Actions('users')` + method `list` → action name `users.list`).
|
|
189
|
+
*
|
|
190
|
+
* The class itself remains a normal Nest provider — add `@Injectable()`
|
|
191
|
+
* separately so it can be resolved by the DI container.
|
|
192
|
+
*
|
|
193
|
+
* Accepts either a prefix string (shorthand) or a full options object:
|
|
194
|
+
* ```ts
|
|
195
|
+
* @Actions('users')
|
|
196
|
+
* @Actions({ prefix: 'users', transports: ['rest', 'trpc'] })
|
|
197
|
+
* ```
|
|
198
|
+
*/
|
|
199
|
+
declare function Actions(prefixOrOptions?: string | ActionsClassMetadata): ClassDecorator;
|
|
200
|
+
//#endregion
|
|
201
|
+
//#region src/lib/discovery.d.ts
|
|
202
|
+
declare class ActionDiscovery {
|
|
203
|
+
private readonly discovery;
|
|
204
|
+
private readonly scanner;
|
|
205
|
+
private readonly reflector;
|
|
206
|
+
private readonly moduleRef;
|
|
207
|
+
constructor(discovery: DiscoveryService, scanner: MetadataScanner, reflector: Reflector, moduleRef: ModuleRef);
|
|
208
|
+
/**
|
|
209
|
+
* Walk every Nest provider, find methods annotated with `@Action`, and build
|
|
210
|
+
* a list of core `Action` objects ready to feed into `silkweave().actions()`.
|
|
211
|
+
*
|
|
212
|
+
* Action invocation is wrapped to (a) run `@UseGuards` guards declared on the
|
|
213
|
+
* method or its class against the incoming HTTP request (read from
|
|
214
|
+
* `ctx.get('request')`) and (b) bind `this` to the resolved Nest provider so
|
|
215
|
+
* DI-injected dependencies remain available.
|
|
216
|
+
*/
|
|
217
|
+
discover(): Action$1[];
|
|
218
|
+
private toAction;
|
|
219
|
+
}
|
|
220
|
+
//#endregion
|
|
221
|
+
//#region src/lib/filter.d.ts
|
|
222
|
+
/**
|
|
223
|
+
* Compile a `transports` allowlist + optional user `isEnabled` into a single
|
|
224
|
+
* `(ctx) => boolean` callback compatible with `Action.isEnabled`.
|
|
225
|
+
*
|
|
226
|
+
* - If `transports` is omitted, the action runs on every adapter.
|
|
227
|
+
* - If `transports` is set, the action is gated on `ctx.get<string>('adapter')`
|
|
228
|
+
* matching one of the listed transports. Each adapter in `@silkweave/nestjs`
|
|
229
|
+
* forks its context with `{ adapter: 'rest' | 'trpc' | 'mcp' }`.
|
|
230
|
+
* - If both `transports` and `userIsEnabled` are set, they are AND-combined.
|
|
231
|
+
*/
|
|
232
|
+
declare function buildIsEnabled(transports: Transport[] | undefined, userIsEnabled: ((ctx: SilkweaveContext) => boolean) | undefined): ((ctx: SilkweaveContext) => boolean) | undefined;
|
|
233
|
+
//#endregion
|
|
234
|
+
//#region src/lib/guards.d.ts
|
|
235
|
+
type GuardRef = Type<CanActivate> | CanActivate;
|
|
236
|
+
/**
|
|
237
|
+
* Read `@UseGuards(...)` metadata for both the method and its class and merge
|
|
238
|
+
* the two lists. Method-level guards run AFTER class-level guards (matching
|
|
239
|
+
* Nest's own behavior).
|
|
240
|
+
*/
|
|
241
|
+
declare function collectGuards(reflector: Reflector, classRef: Type<unknown>, handler: (...args: unknown[]) => unknown): GuardRef[];
|
|
242
|
+
/**
|
|
243
|
+
* Run the configured guards against an HTTP request. Throws `ForbiddenException`
|
|
244
|
+
* if any guard rejects, mirroring Nest's HTTP request-pipeline behavior.
|
|
245
|
+
*
|
|
246
|
+
* Pass `null` for `response` when running on top of a tRPC or MCP request that
|
|
247
|
+
* doesn't surface a raw response object; guards that introspect the response
|
|
248
|
+
* will receive `null`.
|
|
249
|
+
*/
|
|
250
|
+
declare function runGuards(guards: GuardRef[], moduleRef: ModuleRef, reflector: Reflector, classRef: Type<unknown>, handler: (...args: unknown[]) => unknown, request: unknown, response: unknown): Promise<void>;
|
|
251
|
+
//#endregion
|
|
252
|
+
//#region src/lib/silkweave.module.d.ts
|
|
253
|
+
/**
|
|
254
|
+
* Root module for `@silkweave/nestjs`.
|
|
255
|
+
*
|
|
256
|
+
* Discovers every `@Action`-decorated method across the Nest app via
|
|
257
|
+
* `DiscoveryService`, builds core `Action` objects from them, and mounts the
|
|
258
|
+
* configured adapters (`rest()`, `trpc()`, `mcp()`) onto Nest's running HTTP
|
|
259
|
+
* server during `OnApplicationBootstrap`.
|
|
260
|
+
*
|
|
261
|
+
* @example
|
|
262
|
+
* ```ts
|
|
263
|
+
* import { Module } from '@nestjs/common'
|
|
264
|
+
* import { SilkweaveModule, rest, trpc, mcp } from '@silkweave/nestjs'
|
|
265
|
+
* import { UsersModule } from './users.module.js'
|
|
266
|
+
*
|
|
267
|
+
* @Module({
|
|
268
|
+
* imports: [
|
|
269
|
+
* SilkweaveModule.forRoot({
|
|
270
|
+
* silkweave: { name: 'app', description: 'My App', version: '1.0.0' },
|
|
271
|
+
* adapters: [
|
|
272
|
+
* rest({ basePath: '/api' }),
|
|
273
|
+
* trpc({ basePath: '/trpc' }),
|
|
274
|
+
* mcp({ basePath: '/mcp' })
|
|
275
|
+
* ]
|
|
276
|
+
* }),
|
|
277
|
+
* UsersModule
|
|
278
|
+
* ]
|
|
279
|
+
* })
|
|
280
|
+
* export class AppModule {}
|
|
281
|
+
* ```
|
|
282
|
+
*/
|
|
283
|
+
declare class SilkweaveModule {
|
|
284
|
+
static forRoot(options: SilkweaveModuleOptions): DynamicModule;
|
|
285
|
+
}
|
|
286
|
+
//#endregion
|
|
287
|
+
//#region src/lib/silkweave.service.d.ts
|
|
288
|
+
/**
|
|
289
|
+
* Coordinates the Nest lifecycle for `@silkweave/nestjs`:
|
|
290
|
+
*
|
|
291
|
+
* - `onModuleInit`: each configured adapter calls `install(host)` to reserve a
|
|
292
|
+
* placeholder middleware slot at its base path. This must happen here, not
|
|
293
|
+
* in `onApplicationBootstrap`, because Nest installs its 404 catch-all later
|
|
294
|
+
* during `init()` — routes registered after the catch-all are unreachable.
|
|
295
|
+
*
|
|
296
|
+
* - `onApplicationBootstrap`: discovers every `@Action` method, then drives the
|
|
297
|
+
* standard `silkweave().adapter(...).actions(...).start()` flow, which calls
|
|
298
|
+
* each adapter's `start(actions)` to populate the slot reserved earlier.
|
|
299
|
+
*/
|
|
300
|
+
declare class SilkweaveService implements OnModuleInit, OnApplicationBootstrap, OnApplicationShutdown {
|
|
301
|
+
private readonly options;
|
|
302
|
+
private readonly discovery;
|
|
303
|
+
private readonly httpAdapterHost;
|
|
304
|
+
private builder?;
|
|
305
|
+
private readonly generators;
|
|
306
|
+
constructor(options: SilkweaveModuleOptions, discovery: ActionDiscovery, httpAdapterHost: HttpAdapterHost);
|
|
307
|
+
onModuleInit(): void;
|
|
308
|
+
onApplicationBootstrap(): Promise<void>;
|
|
309
|
+
onApplicationShutdown(): Promise<void>;
|
|
310
|
+
/** Access the underlying silkweave builder once bootstrap has completed. */
|
|
311
|
+
getBuilder(): Silkweave | undefined;
|
|
312
|
+
}
|
|
313
|
+
//#endregion
|
|
314
|
+
export { ACTIONS_METADATA, ACTION_METADATA, ACTION_RESPONSE_KEY, Action, ActionDiscovery, ActionMetadata, Actions, type ActionsClassMetadata, AnyActionMetadata, type InferTrpcRouter, McpAdapterOptions, NestSilkweaveAdapter, RestAdapterOptions, ResultToolResult, SILKWEAVE_MODULE_OPTIONS, SilkweaveModule, SilkweaveModuleOptions, SilkweaveService, type Transport, TrpcAdapterOptions, buildIsEnabled, collectGuards, mcp, rest, runGuards, trpc };
|
|
315
|
+
//# sourceMappingURL=index.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/lib/types.ts","../src/adapter/mcp.ts","../src/adapter/rest.ts","../src/adapter/trpc.ts","../src/lib/metadata.ts","../src/decorator/action.ts","../src/decorator/actions.ts","../src/lib/discovery.ts","../src/lib/filter.ts","../src/lib/guards.ts","../src/lib/silkweave.module.ts","../src/lib/silkweave.service.ts"],"mappings":"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"}
|