nitrostack 1.0.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.
Files changed (290) hide show
  1. package/CHANGELOG.md +227 -0
  2. package/CONTRIBUTING.md +182 -0
  3. package/LICENSE +201 -0
  4. package/LICENSE_URLS_UPDATE_COMPLETE.md +388 -0
  5. package/NOTICE +153 -0
  6. package/README.md +571 -0
  7. package/dist/auth/api-key.d.ts +118 -0
  8. package/dist/auth/api-key.d.ts.map +1 -0
  9. package/dist/auth/api-key.js +168 -0
  10. package/dist/auth/api-key.js.map +1 -0
  11. package/dist/auth/client.d.ts +151 -0
  12. package/dist/auth/client.d.ts.map +1 -0
  13. package/dist/auth/client.js +330 -0
  14. package/dist/auth/client.js.map +1 -0
  15. package/dist/auth/index.d.ts +30 -0
  16. package/dist/auth/index.d.ts.map +1 -0
  17. package/dist/auth/index.js +43 -0
  18. package/dist/auth/index.js.map +1 -0
  19. package/dist/auth/middleware.d.ts +95 -0
  20. package/dist/auth/middleware.d.ts.map +1 -0
  21. package/dist/auth/middleware.js +260 -0
  22. package/dist/auth/middleware.js.map +1 -0
  23. package/dist/auth/pkce.d.ts +53 -0
  24. package/dist/auth/pkce.d.ts.map +1 -0
  25. package/dist/auth/pkce.js +105 -0
  26. package/dist/auth/pkce.js.map +1 -0
  27. package/dist/auth/quick-setup.d.ts +94 -0
  28. package/dist/auth/quick-setup.d.ts.map +1 -0
  29. package/dist/auth/quick-setup.js +210 -0
  30. package/dist/auth/quick-setup.js.map +1 -0
  31. package/dist/auth/server-integration.d.ts +97 -0
  32. package/dist/auth/server-integration.d.ts.map +1 -0
  33. package/dist/auth/server-integration.js +182 -0
  34. package/dist/auth/server-integration.js.map +1 -0
  35. package/dist/auth/server-metadata.d.ts +51 -0
  36. package/dist/auth/server-metadata.d.ts.map +1 -0
  37. package/dist/auth/server-metadata.js +106 -0
  38. package/dist/auth/server-metadata.js.map +1 -0
  39. package/dist/auth/simple-jwt.d.ts +88 -0
  40. package/dist/auth/simple-jwt.d.ts.map +1 -0
  41. package/dist/auth/simple-jwt.js +152 -0
  42. package/dist/auth/simple-jwt.js.map +1 -0
  43. package/dist/auth/token-store.d.ts +104 -0
  44. package/dist/auth/token-store.d.ts.map +1 -0
  45. package/dist/auth/token-store.js +205 -0
  46. package/dist/auth/token-store.js.map +1 -0
  47. package/dist/auth/token-validation.d.ts +47 -0
  48. package/dist/auth/token-validation.d.ts.map +1 -0
  49. package/dist/auth/token-validation.js +237 -0
  50. package/dist/auth/token-validation.js.map +1 -0
  51. package/dist/auth/types.d.ts +215 -0
  52. package/dist/auth/types.d.ts.map +1 -0
  53. package/dist/auth/types.js +6 -0
  54. package/dist/auth/types.js.map +1 -0
  55. package/dist/cli/commands/build.d.ts +6 -0
  56. package/dist/cli/commands/build.d.ts.map +1 -0
  57. package/dist/cli/commands/build.js +104 -0
  58. package/dist/cli/commands/build.js.map +1 -0
  59. package/dist/cli/commands/dev.d.ts +7 -0
  60. package/dist/cli/commands/dev.d.ts.map +1 -0
  61. package/dist/cli/commands/dev.js +312 -0
  62. package/dist/cli/commands/dev.js.map +1 -0
  63. package/dist/cli/commands/generate-types.d.ts +8 -0
  64. package/dist/cli/commands/generate-types.d.ts.map +1 -0
  65. package/dist/cli/commands/generate-types.js +220 -0
  66. package/dist/cli/commands/generate-types.js.map +1 -0
  67. package/dist/cli/commands/generate.d.ts +5 -0
  68. package/dist/cli/commands/generate.d.ts.map +1 -0
  69. package/dist/cli/commands/generate.js +365 -0
  70. package/dist/cli/commands/generate.js.map +1 -0
  71. package/dist/cli/commands/init.d.ts +7 -0
  72. package/dist/cli/commands/init.d.ts.map +1 -0
  73. package/dist/cli/commands/init.js +365 -0
  74. package/dist/cli/commands/init.js.map +1 -0
  75. package/dist/cli/commands/start.d.ts +6 -0
  76. package/dist/cli/commands/start.d.ts.map +1 -0
  77. package/dist/cli/commands/start.js +61 -0
  78. package/dist/cli/commands/start.js.map +1 -0
  79. package/dist/cli/index.d.ts +3 -0
  80. package/dist/cli/index.d.ts.map +1 -0
  81. package/dist/cli/index.js +47 -0
  82. package/dist/cli/index.js.map +1 -0
  83. package/dist/cli/mcp-dev-wrapper.d.ts +3 -0
  84. package/dist/cli/mcp-dev-wrapper.d.ts.map +1 -0
  85. package/dist/cli/mcp-dev-wrapper.js +116 -0
  86. package/dist/cli/mcp-dev-wrapper.js.map +1 -0
  87. package/dist/core/apikey-module.d.ts +69 -0
  88. package/dist/core/apikey-module.d.ts.map +1 -0
  89. package/dist/core/apikey-module.js +114 -0
  90. package/dist/core/apikey-module.js.map +1 -0
  91. package/dist/core/app-decorator.d.ts +58 -0
  92. package/dist/core/app-decorator.d.ts.map +1 -0
  93. package/dist/core/app-decorator.js +261 -0
  94. package/dist/core/app-decorator.js.map +1 -0
  95. package/dist/core/builders.d.ts +38 -0
  96. package/dist/core/builders.d.ts.map +1 -0
  97. package/dist/core/builders.js +129 -0
  98. package/dist/core/builders.js.map +1 -0
  99. package/dist/core/component.d.ts +105 -0
  100. package/dist/core/component.d.ts.map +1 -0
  101. package/dist/core/component.js +182 -0
  102. package/dist/core/component.js.map +1 -0
  103. package/dist/core/config-module.d.ts +55 -0
  104. package/dist/core/config-module.d.ts.map +1 -0
  105. package/dist/core/config-module.js +94 -0
  106. package/dist/core/config-module.js.map +1 -0
  107. package/dist/core/decorators/cache.decorator.d.ts +61 -0
  108. package/dist/core/decorators/cache.decorator.d.ts.map +1 -0
  109. package/dist/core/decorators/cache.decorator.js +115 -0
  110. package/dist/core/decorators/cache.decorator.js.map +1 -0
  111. package/dist/core/decorators/health-check.decorator.d.ts +80 -0
  112. package/dist/core/decorators/health-check.decorator.d.ts.map +1 -0
  113. package/dist/core/decorators/health-check.decorator.js +153 -0
  114. package/dist/core/decorators/health-check.decorator.js.map +1 -0
  115. package/dist/core/decorators/rate-limit.decorator.d.ts +62 -0
  116. package/dist/core/decorators/rate-limit.decorator.d.ts.map +1 -0
  117. package/dist/core/decorators/rate-limit.decorator.js +129 -0
  118. package/dist/core/decorators/rate-limit.decorator.js.map +1 -0
  119. package/dist/core/decorators.d.ts +151 -0
  120. package/dist/core/decorators.d.ts.map +1 -0
  121. package/dist/core/decorators.js +142 -0
  122. package/dist/core/decorators.js.map +1 -0
  123. package/dist/core/di/container.d.ts +42 -0
  124. package/dist/core/di/container.d.ts.map +1 -0
  125. package/dist/core/di/container.js +76 -0
  126. package/dist/core/di/container.js.map +1 -0
  127. package/dist/core/di/injectable.decorator.d.ts +35 -0
  128. package/dist/core/di/injectable.decorator.d.ts.map +1 -0
  129. package/dist/core/di/injectable.decorator.js +57 -0
  130. package/dist/core/di/injectable.decorator.js.map +1 -0
  131. package/dist/core/errors.d.ts +54 -0
  132. package/dist/core/errors.d.ts.map +1 -0
  133. package/dist/core/errors.js +87 -0
  134. package/dist/core/errors.js.map +1 -0
  135. package/dist/core/events/event-emitter.d.ts +50 -0
  136. package/dist/core/events/event-emitter.d.ts.map +1 -0
  137. package/dist/core/events/event-emitter.js +94 -0
  138. package/dist/core/events/event-emitter.js.map +1 -0
  139. package/dist/core/events/event.decorator.d.ts +48 -0
  140. package/dist/core/events/event.decorator.d.ts.map +1 -0
  141. package/dist/core/events/event.decorator.js +68 -0
  142. package/dist/core/events/event.decorator.js.map +1 -0
  143. package/dist/core/filters/exception-filter.decorator.d.ts +40 -0
  144. package/dist/core/filters/exception-filter.decorator.d.ts.map +1 -0
  145. package/dist/core/filters/exception-filter.decorator.js +54 -0
  146. package/dist/core/filters/exception-filter.decorator.js.map +1 -0
  147. package/dist/core/filters/exception-filter.interface.d.ts +30 -0
  148. package/dist/core/filters/exception-filter.interface.d.ts.map +1 -0
  149. package/dist/core/filters/exception-filter.interface.js +2 -0
  150. package/dist/core/filters/exception-filter.interface.js.map +1 -0
  151. package/dist/core/guards/apikey.guard.d.ts +22 -0
  152. package/dist/core/guards/apikey.guard.d.ts.map +1 -0
  153. package/dist/core/guards/apikey.guard.js +11 -0
  154. package/dist/core/guards/apikey.guard.js.map +1 -0
  155. package/dist/core/guards/guard.interface.d.ts +18 -0
  156. package/dist/core/guards/guard.interface.d.ts.map +1 -0
  157. package/dist/core/guards/guard.interface.js +2 -0
  158. package/dist/core/guards/guard.interface.js.map +1 -0
  159. package/dist/core/guards/jwt.guard.d.ts +18 -0
  160. package/dist/core/guards/jwt.guard.d.ts.map +1 -0
  161. package/dist/core/guards/jwt.guard.js +2 -0
  162. package/dist/core/guards/jwt.guard.js.map +1 -0
  163. package/dist/core/guards/oauth.guard.d.ts +35 -0
  164. package/dist/core/guards/oauth.guard.d.ts.map +1 -0
  165. package/dist/core/guards/oauth.guard.js +2 -0
  166. package/dist/core/guards/oauth.guard.js.map +1 -0
  167. package/dist/core/guards/use-guards.decorator.d.ts +25 -0
  168. package/dist/core/guards/use-guards.decorator.d.ts.map +1 -0
  169. package/dist/core/guards/use-guards.decorator.js +32 -0
  170. package/dist/core/guards/use-guards.decorator.js.map +1 -0
  171. package/dist/core/health/health-checks.resource.d.ts +14 -0
  172. package/dist/core/health/health-checks.resource.d.ts.map +1 -0
  173. package/dist/core/health/health-checks.resource.js +29 -0
  174. package/dist/core/health/health-checks.resource.js.map +1 -0
  175. package/dist/core/index.d.ts +55 -0
  176. package/dist/core/index.d.ts.map +1 -0
  177. package/dist/core/index.js +57 -0
  178. package/dist/core/index.js.map +1 -0
  179. package/dist/core/interceptors/interceptor.decorator.d.ts +37 -0
  180. package/dist/core/interceptors/interceptor.decorator.d.ts.map +1 -0
  181. package/dist/core/interceptors/interceptor.decorator.js +51 -0
  182. package/dist/core/interceptors/interceptor.decorator.js.map +1 -0
  183. package/dist/core/interceptors/interceptor.interface.d.ts +31 -0
  184. package/dist/core/interceptors/interceptor.interface.d.ts.map +1 -0
  185. package/dist/core/interceptors/interceptor.interface.js +2 -0
  186. package/dist/core/interceptors/interceptor.interface.js.map +1 -0
  187. package/dist/core/jwt-module.d.ts +51 -0
  188. package/dist/core/jwt-module.d.ts.map +1 -0
  189. package/dist/core/jwt-module.js +52 -0
  190. package/dist/core/jwt-module.js.map +1 -0
  191. package/dist/core/logger.d.ts +18 -0
  192. package/dist/core/logger.d.ts.map +1 -0
  193. package/dist/core/logger.js +51 -0
  194. package/dist/core/logger.js.map +1 -0
  195. package/dist/core/middleware/middleware.decorator.d.ts +39 -0
  196. package/dist/core/middleware/middleware.decorator.d.ts.map +1 -0
  197. package/dist/core/middleware/middleware.decorator.js +53 -0
  198. package/dist/core/middleware/middleware.decorator.js.map +1 -0
  199. package/dist/core/middleware/middleware.interface.d.ts +29 -0
  200. package/dist/core/middleware/middleware.interface.d.ts.map +1 -0
  201. package/dist/core/middleware/middleware.interface.js +2 -0
  202. package/dist/core/middleware/middleware.interface.js.map +1 -0
  203. package/dist/core/module.d.ts +74 -0
  204. package/dist/core/module.d.ts.map +1 -0
  205. package/dist/core/module.js +82 -0
  206. package/dist/core/module.js.map +1 -0
  207. package/dist/core/oauth-module.d.ts +144 -0
  208. package/dist/core/oauth-module.d.ts.map +1 -0
  209. package/dist/core/oauth-module.js +190 -0
  210. package/dist/core/oauth-module.js.map +1 -0
  211. package/dist/core/pipes/pipe.decorator.d.ts +55 -0
  212. package/dist/core/pipes/pipe.decorator.d.ts.map +1 -0
  213. package/dist/core/pipes/pipe.decorator.js +85 -0
  214. package/dist/core/pipes/pipe.decorator.js.map +1 -0
  215. package/dist/core/pipes/pipe.interface.d.ts +36 -0
  216. package/dist/core/pipes/pipe.interface.d.ts.map +1 -0
  217. package/dist/core/pipes/pipe.interface.js +2 -0
  218. package/dist/core/pipes/pipe.interface.js.map +1 -0
  219. package/dist/core/prompt.d.ts +37 -0
  220. package/dist/core/prompt.d.ts.map +1 -0
  221. package/dist/core/prompt.js +76 -0
  222. package/dist/core/prompt.js.map +1 -0
  223. package/dist/core/resource.d.ts +42 -0
  224. package/dist/core/resource.d.ts.map +1 -0
  225. package/dist/core/resource.js +90 -0
  226. package/dist/core/resource.js.map +1 -0
  227. package/dist/core/server.d.ts +72 -0
  228. package/dist/core/server.d.ts.map +1 -0
  229. package/dist/core/server.js +406 -0
  230. package/dist/core/server.js.map +1 -0
  231. package/dist/core/tool.d.ts +78 -0
  232. package/dist/core/tool.d.ts.map +1 -0
  233. package/dist/core/tool.js +190 -0
  234. package/dist/core/tool.js.map +1 -0
  235. package/dist/core/transports/http-server.d.ts +102 -0
  236. package/dist/core/transports/http-server.d.ts.map +1 -0
  237. package/dist/core/transports/http-server.js +265 -0
  238. package/dist/core/transports/http-server.js.map +1 -0
  239. package/dist/core/types.d.ts +123 -0
  240. package/dist/core/types.d.ts.map +1 -0
  241. package/dist/core/types.js +2 -0
  242. package/dist/core/types.js.map +1 -0
  243. package/dist/core/widgets/widget-examples.resource.d.ts +17 -0
  244. package/dist/core/widgets/widget-examples.resource.d.ts.map +1 -0
  245. package/dist/core/widgets/widget-examples.resource.js +28 -0
  246. package/dist/core/widgets/widget-examples.resource.js.map +1 -0
  247. package/dist/core/widgets/widget-registry.d.ts +56 -0
  248. package/dist/core/widgets/widget-registry.d.ts.map +1 -0
  249. package/dist/core/widgets/widget-registry.js +75 -0
  250. package/dist/core/widgets/widget-registry.js.map +1 -0
  251. package/dist/testing/index.d.ts +82 -0
  252. package/dist/testing/index.d.ts.map +1 -0
  253. package/dist/testing/index.js +164 -0
  254. package/dist/testing/index.js.map +1 -0
  255. package/dist/ui-next/index.d.ts +31 -0
  256. package/dist/ui-next/index.d.ts.map +1 -0
  257. package/dist/ui-next/index.js +687 -0
  258. package/dist/ui-next/index.js.map +1 -0
  259. package/dist/widgets/index.d.ts +9 -0
  260. package/dist/widgets/index.d.ts.map +1 -0
  261. package/dist/widgets/index.js +9 -0
  262. package/dist/widgets/index.js.map +1 -0
  263. package/dist/widgets/metadata.d.ts +53 -0
  264. package/dist/widgets/metadata.d.ts.map +1 -0
  265. package/dist/widgets/metadata.js +29 -0
  266. package/dist/widgets/metadata.js.map +1 -0
  267. package/dist/widgets/withToolData.d.ts +19 -0
  268. package/dist/widgets/withToolData.d.ts.map +1 -0
  269. package/dist/widgets/withToolData.js +240 -0
  270. package/dist/widgets/withToolData.js.map +1 -0
  271. package/jest.config.js +21 -0
  272. package/package.json +108 -0
  273. package/templates/typescript-auth/AI_AGENT_CLI_REFERENCE.md +702 -0
  274. package/templates/typescript-auth/AI_AGENT_SDK_REFERENCE.md +1260 -0
  275. package/templates/typescript-auth/README.md +400 -0
  276. package/templates/typescript-auth/package.json +44 -0
  277. package/templates/typescript-auth-api-key/AI_AGENT_CLI_REFERENCE.md +701 -0
  278. package/templates/typescript-auth-api-key/AI_AGENT_SDK_REFERENCE.md +1260 -0
  279. package/templates/typescript-auth-api-key/README.md +483 -0
  280. package/templates/typescript-auth-api-key/package-lock.json +124 -0
  281. package/templates/typescript-auth-api-key/package.json +29 -0
  282. package/templates/typescript-oauth/AI_AGENT_CLI_REFERENCE.md +701 -0
  283. package/templates/typescript-oauth/AI_AGENT_SDK_REFERENCE.md +1260 -0
  284. package/templates/typescript-oauth/OAUTH_SETUP.md +406 -0
  285. package/templates/typescript-oauth/README.md +350 -0
  286. package/templates/typescript-oauth/package.json +30 -0
  287. package/templates/typescript-starter/AI_AGENT_CLI_REFERENCE.md +701 -0
  288. package/templates/typescript-starter/AI_AGENT_SDK_REFERENCE.md +1260 -0
  289. package/templates/typescript-starter/README.md +312 -0
  290. package/templates/typescript-starter/package.json +32 -0
@@ -0,0 +1,1260 @@
1
+ # NitroStack SDK Reference - For AI Code Editors
2
+
3
+ **Comprehensive SDK reference for AI agents editing NitroStack v3.0 code**
4
+
5
+ ---
6
+
7
+ ## Table of Contents
8
+
9
+ 1. [Architecture Overview](#architecture-overview)
10
+ 2. [Application Bootstrap](#application-bootstrap)
11
+ 3. [Modules](#modules)
12
+ 4. [Tools](#tools)
13
+ 5. [Resources](#resources)
14
+ 6. [Prompts](#prompts)
15
+ 7. [Guards](#guards)
16
+ 8. [Middleware](#middleware)
17
+ 9. [Interceptors](#interceptors)
18
+ 10. [Pipes](#pipes)
19
+ 11. [Services & DI](#services--dependency-injection)
20
+ 12. [Decorators Reference](#decorators-reference)
21
+ 13. [Widgets](#widgets)
22
+ 14. [Health Checks](#health-checks)
23
+ 15. [Caching](#caching)
24
+ 16. [Rate Limiting](#rate-limiting)
25
+ 17. [Error Handling](#error-handling)
26
+ 18. [File Structure](#file-structure)
27
+ 19. [Import Rules](#import-rules)
28
+ 20. [Common Patterns](#common-patterns)
29
+
30
+ ---
31
+
32
+ ## Architecture Overview
33
+
34
+ NitroStack v3.0 uses **decorator-based architecture** inspired by NestJS:
35
+
36
+ - **Declarative** - Use decorators instead of factory functions
37
+ - **Modular** - Organize code into feature modules
38
+ - **DI-First** - Dependency injection for testability
39
+ - **Type-Safe** - Zod schemas for runtime validation
40
+ - **Protocol-Native** - Built for MCP protocol, not HTTP
41
+
42
+ ### Key Principles
43
+
44
+ 1. ✅ Use decorators (`@Tool`, `@Module`, `@Injectable`)
45
+ 2. ✅ No manual registration (`server.tool()`, `server.resource()`)
46
+ 3. ✅ Constructor injection for dependencies
47
+ 4. ✅ Services contain business logic, tools are thin
48
+ 5. ✅ ES modules with `.js` extensions in imports
49
+
50
+ ---
51
+
52
+ ## Application Bootstrap
53
+
54
+ ### Root Module (`app.module.ts`)
55
+
56
+ ```typescript
57
+ import { McpApp, Module } from 'nitrostack';
58
+ import { ConfigModule } from 'nitrostack/config';
59
+ import { JWTModule } from 'nitrostack/jwt';
60
+ import { ProductsModule } from './modules/products/products.module.js';
61
+ import { DatabaseService } from './services/database.service.js';
62
+
63
+ @McpApp({
64
+ server: {
65
+ name: 'my-ecommerce-server',
66
+ version: '1.0.0',
67
+ description: 'E-commerce MCP server'
68
+ },
69
+ logging: {
70
+ level: 'info' // debug | info | warn | error
71
+ }
72
+ })
73
+ @Module({
74
+ imports: [
75
+ ConfigModule.forRoot(), // Environment variables
76
+ JWTModule.forRoot(), // JWT authentication
77
+ ProductsModule, // Feature modules
78
+ OrdersModule
79
+ ],
80
+ providers: [DatabaseService], // Global services
81
+ controllers: [] // Global tools/resources
82
+ })
83
+ export class AppModule {}
84
+ ```
85
+
86
+ ### Entry Point (`index.ts`)
87
+
88
+ ```typescript
89
+ import { McpApplicationFactory } from 'nitrostack';
90
+ import { AppModule } from './app.module.js';
91
+
92
+ // Bootstrap application
93
+ McpApplicationFactory.create(AppModule);
94
+ ```
95
+
96
+ **That's it!** No manual server setup needed.
97
+
98
+ ---
99
+
100
+ ## Modules
101
+
102
+ Modules organize related features into cohesive units.
103
+
104
+ ### Basic Module
105
+
106
+ ```typescript
107
+ import { Module } from 'nitrostack';
108
+ import { ProductsTools } from './products.tools.js';
109
+ import { ProductsResources } from './products.resources.js';
110
+ import { ProductsPrompts } from './products.prompts.js';
111
+ import { ProductService } from './products.service.js';
112
+
113
+ @Module({
114
+ name: 'products',
115
+ description: 'Product catalog management',
116
+ controllers: [ProductsTools, ProductsResources, ProductsPrompts],
117
+ providers: [ProductService],
118
+ imports: [], // Other modules this depends on
119
+ exports: [] // Services to expose to other modules
120
+ })
121
+ export class ProductsModule {}
122
+ ```
123
+
124
+ ### Module with Dependencies
125
+
126
+ ```typescript
127
+ @Module({
128
+ name: 'orders',
129
+ controllers: [OrdersTools],
130
+ providers: [OrderService],
131
+ imports: [ProductsModule, UserModule], // Import other modules
132
+ exports: [OrderService] // Make OrderService available to others
133
+ })
134
+ export class OrdersModule {}
135
+ ```
136
+
137
+ ### Dynamic Modules (Advanced)
138
+
139
+ ```typescript
140
+ // Config module with options
141
+ @Module({})
142
+ export class ConfigModule {
143
+ static forRoot(options?: ConfigOptions) {
144
+ return {
145
+ module: ConfigModule,
146
+ providers: [
147
+ {
148
+ provide: 'CONFIG_OPTIONS',
149
+ useValue: options || {}
150
+ },
151
+ ConfigService
152
+ ],
153
+ exports: [ConfigService]
154
+ };
155
+ }
156
+ }
157
+ ```
158
+
159
+ ---
160
+
161
+ ## Tools
162
+
163
+ Tools are functions that AI models can call.
164
+
165
+ ### Basic Tool
166
+
167
+ ```typescript
168
+ import { Tool, ExecutionContext } from 'nitrostack';
169
+ import { z } from 'zod';
170
+
171
+ export class ProductsTools {
172
+ @Tool({
173
+ name: 'get_product',
174
+ description: 'Get product details by ID',
175
+ inputSchema: z.object({
176
+ product_id: z.string().describe('Unique product identifier')
177
+ })
178
+ })
179
+ async getProduct(input: any, ctx: ExecutionContext) {
180
+ ctx.logger.info('Fetching product', { id: input.product_id });
181
+
182
+ return {
183
+ id: input.product_id,
184
+ name: 'Example Product',
185
+ price: 99.99
186
+ };
187
+ }
188
+ }
189
+ ```
190
+
191
+ ### Tool with Examples
192
+
193
+ ```typescript
194
+ @Tool({
195
+ name: 'browse_products',
196
+ description: 'Browse products with filters',
197
+ inputSchema: z.object({
198
+ category: z.string().optional().describe('Product category'),
199
+ page: z.number().default(1).describe('Page number'),
200
+ limit: z.number().default(10).describe('Items per page')
201
+ }),
202
+ examples: {
203
+ request: { category: 'electronics', page: 1, limit: 10 },
204
+ response: {
205
+ products: [
206
+ { id: '1', name: 'Laptop', price: 999 },
207
+ { id: '2', name: 'Mouse', price: 29 }
208
+ ],
209
+ total: 2,
210
+ page: 1
211
+ }
212
+ }
213
+ })
214
+ async browseProducts(input: any, ctx: ExecutionContext) {
215
+ return {
216
+ products: [],
217
+ total: 0,
218
+ page: input.page
219
+ };
220
+ }
221
+ ```
222
+
223
+ ### Tool with Widget
224
+
225
+ ```typescript
226
+ import { Tool, Widget, ExecutionContext } from 'nitrostack';
227
+
228
+ @Tool({
229
+ name: 'get_product',
230
+ description: 'Get product details',
231
+ inputSchema: z.object({ product_id: z.string() }),
232
+ examples: {
233
+ request: { product_id: 'prod-1' },
234
+ response: { id: 'prod-1', name: 'Laptop', price: 999, image_url: '/laptop.jpg' }
235
+ }
236
+ })
237
+ @Widget('product-card') // Link to src/widgets/app/product-card/page.tsx
238
+ async getProduct(input: any, ctx: ExecutionContext) {
239
+ return await this.productService.findById(input.product_id);
240
+ }
241
+ ```
242
+
243
+ ### Tool with Guards
244
+
245
+ ```typescript
246
+ import { Tool, UseGuards, ExecutionContext } from 'nitrostack';
247
+ import { JWTGuard } from '../../guards/jwt.guard.js';
248
+
249
+ @Tool({
250
+ name: 'create_order',
251
+ description: 'Create a new order',
252
+ inputSchema: z.object({
253
+ items: z.array(z.object({
254
+ product_id: z.string(),
255
+ quantity: z.number()
256
+ }))
257
+ })
258
+ })
259
+ @UseGuards(JWTGuard) // Require authentication
260
+ async createOrder(input: any, ctx: ExecutionContext) {
261
+ const userId = ctx.auth?.subject; // Set by guard
262
+ ctx.logger.info('Creating order', { userId, items: input.items });
263
+
264
+ return await this.orderService.create(userId, input.items);
265
+ }
266
+ ```
267
+
268
+ ### Tool with Caching
269
+
270
+ ```typescript
271
+ import { Tool, Cache } from 'nitrostack';
272
+
273
+ @Tool({
274
+ name: 'get_categories',
275
+ description: 'Get all product categories',
276
+ inputSchema: z.object({})
277
+ })
278
+ @Cache({ ttl: 300 }) // Cache for 5 minutes
279
+ async getCategories() {
280
+ return await this.productService.getCategories();
281
+ }
282
+ ```
283
+
284
+ ### Tool with Rate Limiting
285
+
286
+ ```typescript
287
+ import { Tool, RateLimit } from 'nitrostack';
288
+
289
+ @Tool({
290
+ name: 'send_email',
291
+ description: 'Send email notification',
292
+ inputSchema: z.object({
293
+ to: z.string().email(),
294
+ subject: z.string(),
295
+ body: z.string()
296
+ })
297
+ })
298
+ @RateLimit({
299
+ requests: 10, // Max requests
300
+ window: '1m', // Time window (1m, 1h, 1d)
301
+ key: (ctx) => ctx.auth?.subject || 'anonymous'
302
+ })
303
+ async sendEmail(input: any, ctx: ExecutionContext) {
304
+ await this.emailService.send(input.to, input.subject, input.body);
305
+ return { success: true };
306
+ }
307
+ ```
308
+
309
+ ### Tool with DI
310
+
311
+ ```typescript
312
+ import { Injectable } from 'nitrostack';
313
+
314
+ @Injectable()
315
+ export class ProductService {
316
+ constructor(private db: DatabaseService) {}
317
+
318
+ async findById(id: string) {
319
+ return this.db.queryOne('SELECT * FROM products WHERE id = ?', [id]);
320
+ }
321
+ }
322
+
323
+ export class ProductsTools {
324
+ constructor(private productService: ProductService) {} // Auto-injected
325
+
326
+ @Tool({ name: 'get_product' })
327
+ async getProduct(input: any) {
328
+ return await this.productService.findById(input.product_id);
329
+ }
330
+ }
331
+ ```
332
+
333
+ ---
334
+
335
+ ## Resources
336
+
337
+ Resources are data schemas AI can read.
338
+
339
+ ### Basic Resource
340
+
341
+ ```typescript
342
+ import { Resource, ExecutionContext } from 'nitrostack';
343
+
344
+ @Resource({
345
+ uri: 'product://{id}',
346
+ name: 'Product Data',
347
+ description: 'Detailed product information',
348
+ mimeType: 'application/json'
349
+ })
350
+ async getProductResource(uri: string, ctx: ExecutionContext) {
351
+ const id = uri.split('://')[1]; // Extract ID from URI
352
+ const product = await this.productService.findById(id);
353
+
354
+ return {
355
+ contents: [{
356
+ uri,
357
+ mimeType: 'application/json',
358
+ text: JSON.stringify(product, null, 2)
359
+ }]
360
+ };
361
+ }
362
+ ```
363
+
364
+ ### Resource with Widget
365
+
366
+ ```typescript
367
+ @Resource({
368
+ uri: 'catalog://categories',
369
+ name: 'Product Categories',
370
+ description: 'All available product categories',
371
+ mimeType: 'application/json',
372
+ examples: {
373
+ response: {
374
+ categories: ['Electronics', 'Fashion', 'Home']
375
+ }
376
+ }
377
+ })
378
+ @Widget('categories-list')
379
+ async getCategoriesResource(uri: string, ctx: ExecutionContext) {
380
+ const categories = await this.productService.getCategories();
381
+
382
+ return {
383
+ contents: [{
384
+ uri,
385
+ mimeType: 'application/json',
386
+ text: JSON.stringify({ categories })
387
+ }]
388
+ };
389
+ }
390
+ ```
391
+
392
+ ---
393
+
394
+ ## Prompts
395
+
396
+ Prompts are conversation templates for AI.
397
+
398
+ ### Basic Prompt
399
+
400
+ ```typescript
401
+ import { Prompt, ExecutionContext } from 'nitrostack';
402
+
403
+ @Prompt({
404
+ name: 'product_review',
405
+ description: 'Generate product review template',
406
+ arguments: [
407
+ {
408
+ name: 'product_id',
409
+ description: 'ID of product to review',
410
+ required: true
411
+ },
412
+ {
413
+ name: 'rating',
414
+ description: 'Rating (1-5)',
415
+ required: false
416
+ }
417
+ ]
418
+ })
419
+ async getReviewPrompt(args: any, ctx: ExecutionContext) {
420
+ const product = await this.productService.findById(args.product_id);
421
+
422
+ return {
423
+ messages: [
424
+ {
425
+ role: 'user',
426
+ content: {
427
+ type: 'text',
428
+ text: `Write a ${args.rating || 5}-star review for: ${product.name}`
429
+ }
430
+ }
431
+ ]
432
+ };
433
+ }
434
+ ```
435
+
436
+ ### Prompt with Context
437
+
438
+ ```typescript
439
+ @Prompt({
440
+ name: 'order_summary',
441
+ description: 'Generate order summary for customer',
442
+ arguments: [
443
+ { name: 'order_id', description: 'Order ID', required: true }
444
+ ]
445
+ })
446
+ async getOrderSummaryPrompt(args: any, ctx: ExecutionContext) {
447
+ const order = await this.orderService.findById(args.order_id);
448
+
449
+ return {
450
+ messages: [
451
+ {
452
+ role: 'system',
453
+ content: {
454
+ type: 'text',
455
+ text: 'You are a helpful customer service assistant.'
456
+ }
457
+ },
458
+ {
459
+ role: 'user',
460
+ content: {
461
+ type: 'text',
462
+ text: `Summarize order #${order.id} with ${order.items.length} items, total $${order.total}`
463
+ }
464
+ }
465
+ ]
466
+ };
467
+ }
468
+ ```
469
+
470
+ ---
471
+
472
+ ## Guards
473
+
474
+ Guards implement authentication/authorization.
475
+
476
+ ### JWT Guard
477
+
478
+ ```typescript
479
+ import { Guard, ExecutionContext, Injectable } from 'nitrostack';
480
+ import jwt from 'jsonwebtoken';
481
+
482
+ @Injectable()
483
+ export class JWTGuard implements Guard {
484
+ async canActivate(context: ExecutionContext): Promise<boolean> {
485
+ const authHeader = context.metadata?.authorization;
486
+
487
+ if (!authHeader || !authHeader.startsWith('Bearer ')) {
488
+ return false;
489
+ }
490
+
491
+ const token = authHeader.substring(7);
492
+
493
+ try {
494
+ const payload = jwt.verify(token, process.env.JWT_SECRET!);
495
+
496
+ // Attach auth info to context
497
+ context.auth = {
498
+ subject: payload.sub,
499
+ email: payload.email,
500
+ ...payload
501
+ };
502
+
503
+ return true;
504
+ } catch (error) {
505
+ context.logger.warn('JWT verification failed', { error });
506
+ return false;
507
+ }
508
+ }
509
+ }
510
+ ```
511
+
512
+ ### Admin Guard
513
+
514
+ ```typescript
515
+ @Injectable()
516
+ export class AdminGuard implements Guard {
517
+ async canActivate(context: ExecutionContext): Promise<boolean> {
518
+ // Assumes JWTGuard ran first
519
+ const user = context.auth;
520
+
521
+ if (!user) {
522
+ return false;
523
+ }
524
+
525
+ // Check if user is admin
526
+ return user.role === 'admin';
527
+ }
528
+ }
529
+
530
+ // Usage: Multiple guards (all must pass)
531
+ @Tool({ name: 'delete_user' })
532
+ @UseGuards(JWTGuard, AdminGuard)
533
+ async deleteUser(input: any, ctx: ExecutionContext) {
534
+ // Only admins with valid JWT can call this
535
+ }
536
+ ```
537
+
538
+ ---
539
+
540
+ ## Middleware
541
+
542
+ Middleware runs before/after tool execution.
543
+
544
+ ### Logging Middleware
545
+
546
+ ```typescript
547
+ import { Middleware, MiddlewareInterface, ExecutionContext } from 'nitrostack';
548
+
549
+ @Middleware()
550
+ export class LoggingMiddleware implements MiddlewareInterface {
551
+ async use(context: ExecutionContext, next: () => Promise<any>): Promise<any> {
552
+ const start = Date.now();
553
+
554
+ context.logger.info('Tool starting', {
555
+ tool: context.toolName,
556
+ input: context.input
557
+ });
558
+
559
+ try {
560
+ const result = await next();
561
+
562
+ const duration = Date.now() - start;
563
+ context.logger.info('Tool completed', {
564
+ tool: context.toolName,
565
+ duration: `${duration}ms`
566
+ });
567
+
568
+ return result;
569
+ } catch (error) {
570
+ const duration = Date.now() - start;
571
+ context.logger.error('Tool failed', {
572
+ tool: context.toolName,
573
+ duration: `${duration}ms`,
574
+ error
575
+ });
576
+ throw error;
577
+ }
578
+ }
579
+ }
580
+
581
+ // Usage
582
+ @Tool({ name: 'my_tool' })
583
+ @UseMiddleware(LoggingMiddleware)
584
+ async myTool(input: any, ctx: ExecutionContext) {}
585
+ ```
586
+
587
+ ### Auth Middleware
588
+
589
+ ```typescript
590
+ @Middleware()
591
+ export class AuthMiddleware implements MiddlewareInterface {
592
+ async use(context: ExecutionContext, next: () => Promise<any>) {
593
+ if (!context.auth) {
594
+ throw new Error('Unauthorized');
595
+ }
596
+
597
+ return next();
598
+ }
599
+ }
600
+ ```
601
+
602
+ ---
603
+
604
+ ## Interceptors
605
+
606
+ Interceptors transform requests/responses.
607
+
608
+ ### Transform Interceptor
609
+
610
+ ```typescript
611
+ import { Interceptor, InterceptorInterface, ExecutionContext } from 'nitrostack';
612
+
613
+ @Interceptor()
614
+ export class TransformInterceptor implements InterceptorInterface {
615
+ async intercept(context: ExecutionContext, next: () => Promise<any>): Promise<any> {
616
+ const result = await next();
617
+
618
+ // Wrap all responses in standard format
619
+ return {
620
+ success: true,
621
+ data: result,
622
+ timestamp: new Date().toISOString(),
623
+ tool: context.toolName
624
+ };
625
+ }
626
+ }
627
+
628
+ // Usage
629
+ @Tool({ name: 'get_product' })
630
+ @UseInterceptors(TransformInterceptor)
631
+ async getProduct(input: any) {
632
+ return { id: '1', name: 'Product' };
633
+ }
634
+
635
+ // Returns:
636
+ // {
637
+ // success: true,
638
+ // data: { id: '1', name: 'Product' },
639
+ // timestamp: '2025-10-24T12:00:00Z',
640
+ // tool: 'get_product'
641
+ // }
642
+ ```
643
+
644
+ ---
645
+
646
+ ## Pipes
647
+
648
+ Pipes transform/validate input before handler execution.
649
+
650
+ ### Validation Pipe
651
+
652
+ ```typescript
653
+ import { Pipe, PipeInterface } from 'nitrostack';
654
+ import { z } from 'zod';
655
+
656
+ @Pipe()
657
+ export class ValidationPipe implements PipeInterface {
658
+ async transform(value: any, metadata: any): Promise<any> {
659
+ if (metadata.schema) {
660
+ // Validate with Zod
661
+ return metadata.schema.parse(value);
662
+ }
663
+ return value;
664
+ }
665
+ }
666
+ ```
667
+
668
+ ---
669
+
670
+ ## Services & Dependency Injection
671
+
672
+ ### Injectable Service
673
+
674
+ ```typescript
675
+ import { Injectable } from 'nitrostack';
676
+
677
+ @Injectable()
678
+ export class ProductService {
679
+ constructor(private db: DatabaseService) {} // DI
680
+
681
+ async findById(id: string) {
682
+ return this.db.queryOne('SELECT * FROM products WHERE id = ?', [id]);
683
+ }
684
+
685
+ async search(query: string) {
686
+ return this.db.query(
687
+ 'SELECT * FROM products WHERE name LIKE ?',
688
+ [`%${query}%`]
689
+ );
690
+ }
691
+
692
+ async getCategories() {
693
+ return this.db.query('SELECT DISTINCT category FROM products');
694
+ }
695
+ }
696
+ ```
697
+
698
+ ### Using Services in Tools
699
+
700
+ ```typescript
701
+ export class ProductsTools {
702
+ constructor(
703
+ private productService: ProductService,
704
+ private cacheService: CacheService
705
+ ) {} // Both auto-injected
706
+
707
+ @Tool({ name: 'search_products' })
708
+ async searchProducts(input: any, ctx: ExecutionContext) {
709
+ const results = await this.productService.search(input.query);
710
+ await this.cacheService.set(`search:${input.query}`, results);
711
+ return results;
712
+ }
713
+ }
714
+ ```
715
+
716
+ ---
717
+
718
+ ## Decorators Reference
719
+
720
+ ### Core Decorators
721
+
722
+ | Decorator | Purpose | Example |
723
+ |-----------|---------|---------|
724
+ | `@McpApp(options)` | Root application module | `@McpApp({ server: { name: 'my-server' } })` |
725
+ | `@Module(options)` | Feature module | `@Module({ name: 'products', controllers: [...] })` |
726
+ | `@Injectable()` | Mark for DI | `@Injectable() class ProductService {}` |
727
+
728
+ ### Tool Decorators
729
+
730
+ | Decorator | Purpose | Example |
731
+ |-----------|---------|---------|
732
+ | `@Tool(options)` | Define tool | `@Tool({ name: 'get_product', inputSchema: z.object({}) })` |
733
+ | `@Resource(options)` | Define resource | `@Resource({ uri: 'product://{id}' })` |
734
+ | `@Prompt(options)` | Define prompt | `@Prompt({ name: 'review_prompt' })` |
735
+
736
+ ### Feature Decorators
737
+
738
+ | Decorator | Purpose | Example |
739
+ |-----------|---------|---------|
740
+ | `@Widget(name)` | Link UI widget | `@Widget('product-card')` |
741
+ | `@UseGuards(...guards)` | Apply guards | `@UseGuards(JWTGuard, AdminGuard)` |
742
+ | `@UseMiddleware(...mw)` | Apply middleware | `@UseMiddleware(LoggingMiddleware)` |
743
+ | `@UseInterceptors(...int)` | Apply interceptors | `@UseInterceptors(TransformInterceptor)` |
744
+ | `@Cache(options)` | Cache responses | `@Cache({ ttl: 300 })` |
745
+ | `@RateLimit(options)` | Rate limiting | `@RateLimit({ requests: 10, window: '1m' })` |
746
+ | `@HealthCheck(name)` | Define health check | `@HealthCheck('database')` |
747
+
748
+ ---
749
+
750
+ ## Widgets
751
+
752
+ UI components rendered alongside tool responses.
753
+
754
+ ### Widget File Structure
755
+
756
+ ```
757
+ src/widgets/
758
+ ├── app/
759
+ │ ├── product-card/
760
+ │ │ └── page.tsx # Widget component
761
+ │ ├── products-grid/
762
+ │ │ └── page.tsx
763
+ │ └── ...
764
+ ├── types/
765
+ │ └── tool-data.ts # Generated types
766
+ ├── styles/
767
+ │ └── ecommerce.ts # Shared inline styles
768
+ ├── widget-manifest.json # Widget metadata
769
+ ├── package.json
770
+ └── next.config.js
771
+ ```
772
+
773
+ ### Basic Widget
774
+
775
+ ```typescript
776
+ 'use client';
777
+
778
+ import { useEffect, useState } from 'react';
779
+
780
+ export default function ProductCard() {
781
+ const [data, setData] = useState<any>(null);
782
+
783
+ useEffect(() => {
784
+ // Listen for data from Studio/MCP
785
+ const handleMessage = (event: MessageEvent) => {
786
+ if (event.data.type === 'toolOutput') {
787
+ setData(event.data.data);
788
+ }
789
+ };
790
+
791
+ window.addEventListener('message', handleMessage);
792
+ return () => window.removeEventListener('message', handleMessage);
793
+ }, []);
794
+
795
+ if (!data) {
796
+ return <div>Loading...</div>;
797
+ }
798
+
799
+ return (
800
+ <div style={{ padding: '20px', border: '1px solid #ddd' }}>
801
+ <h2>{data.name}</h2>
802
+ <p>Price: ${data.price}</p>
803
+ <img src={data.image_url} alt={data.name} style={{ maxWidth: '200px' }} />
804
+ </div>
805
+ );
806
+ }
807
+ ```
808
+
809
+ ### Widget with Types
810
+
811
+ ```typescript
812
+ 'use client';
813
+
814
+ import { useEffect, useState } from 'react';
815
+ import { GetProductOutput } from '../../types/tool-data';
816
+
817
+ export default function ProductCard() {
818
+ const [data, setData] = useState<GetProductOutput | null>(null);
819
+
820
+ useEffect(() => {
821
+ const handleMessage = (event: MessageEvent) => {
822
+ if (event.data.type === 'toolOutput') {
823
+ setData(event.data.data as GetProductOutput);
824
+ }
825
+ };
826
+
827
+ window.addEventListener('message', handleMessage);
828
+ return () => window.removeEventListener('message', handleMessage);
829
+ }, []);
830
+
831
+ if (!data) return <div>Loading...</div>;
832
+
833
+ // TypeScript knows data.name, data.price, etc.
834
+ return (
835
+ <div>
836
+ <h2>{data.name}</h2>
837
+ <p>${data.price}</p>
838
+ </div>
839
+ );
840
+ }
841
+ ```
842
+
843
+ ### Widget Manifest
844
+
845
+ ```json
846
+ {
847
+ "widgets": [
848
+ {
849
+ "uri": "product-card",
850
+ "name": "Product Card",
851
+ "description": "Display product details",
852
+ "toolName": "get_product",
853
+ "examples": {
854
+ "request": { "product_id": "1" },
855
+ "response": { "id": "1", "name": "Laptop", "price": 999 }
856
+ }
857
+ }
858
+ ]
859
+ }
860
+ ```
861
+
862
+ ### Linking Widget to Tool
863
+
864
+ ```typescript
865
+ @Tool({
866
+ name: 'get_product',
867
+ inputSchema: z.object({ product_id: z.string() })
868
+ })
869
+ @Widget('product-card') // Links to src/widgets/app/product-card/page.tsx
870
+ async getProduct(input: any) {
871
+ return { id: input.product_id, name: 'Laptop', price: 999 };
872
+ }
873
+ ```
874
+
875
+ ---
876
+
877
+ ## Health Checks
878
+
879
+ Monitor system health.
880
+
881
+ ### Basic Health Check
882
+
883
+ ```typescript
884
+ import { HealthCheck, Injectable } from 'nitrostack';
885
+
886
+ @Injectable()
887
+ export class SystemHealthCheck {
888
+ @HealthCheck('system')
889
+ async checkSystem() {
890
+ const uptime = process.uptime();
891
+ const memory = process.memoryUsage();
892
+
893
+ return {
894
+ status: uptime > 0 ? 'up' : 'down',
895
+ message: 'System is operational',
896
+ details: {
897
+ uptime: `${Math.floor(uptime)}s`,
898
+ memory: `${Math.round(memory.heapUsed / 1024 / 1024)}MB`
899
+ }
900
+ };
901
+ }
902
+ }
903
+ ```
904
+
905
+ ### Database Health Check
906
+
907
+ ```typescript
908
+ @Injectable()
909
+ export class DatabaseHealthCheck {
910
+ constructor(private db: DatabaseService) {}
911
+
912
+ @HealthCheck('database')
913
+ async checkDatabase() {
914
+ try {
915
+ await this.db.query('SELECT 1');
916
+ return {
917
+ status: 'up',
918
+ message: 'Database is responsive',
919
+ details: { connection: 'active' }
920
+ };
921
+ } catch (error) {
922
+ return {
923
+ status: 'down',
924
+ message: 'Database connection failed',
925
+ details: { error: error.message }
926
+ };
927
+ }
928
+ }
929
+ }
930
+ ```
931
+
932
+ ---
933
+
934
+ ## Caching
935
+
936
+ Cache tool responses for performance.
937
+
938
+ ```typescript
939
+ import { Tool, Cache } from 'nitrostack';
940
+
941
+ // Simple TTL caching
942
+ @Tool({ name: 'get_categories' })
943
+ @Cache({ ttl: 300 }) // 5 minutes
944
+ async getCategories() {
945
+ return await this.productService.getCategories();
946
+ }
947
+
948
+ // Custom cache key
949
+ @Tool({ name: 'get_product' })
950
+ @Cache({
951
+ ttl: 60,
952
+ key: (input) => `product:${input.product_id}`
953
+ })
954
+ async getProduct(input: any) {
955
+ return await this.productService.findById(input.product_id);
956
+ }
957
+ ```
958
+
959
+ ---
960
+
961
+ ## Rate Limiting
962
+
963
+ Limit tool execution frequency.
964
+
965
+ ```typescript
966
+ import { Tool, RateLimit } from 'nitrostack';
967
+
968
+ // Per-user rate limiting
969
+ @Tool({ name: 'send_email' })
970
+ @RateLimit({
971
+ requests: 10, // Max 10 requests
972
+ window: '1m', // Per 1 minute
973
+ key: (ctx) => ctx.auth?.subject || 'anon' // Key by user ID
974
+ })
975
+ async sendEmail(input: any) {
976
+ await this.emailService.send(input.to, input.subject, input.body);
977
+ return { success: true };
978
+ }
979
+
980
+ // Global rate limiting
981
+ @Tool({ name: 'expensive_operation' })
982
+ @RateLimit({
983
+ requests: 100,
984
+ window: '1h',
985
+ key: () => 'global'
986
+ })
987
+ async expensiveOperation(input: any) {
988
+ // ...
989
+ }
990
+ ```
991
+
992
+ ---
993
+
994
+ ## Error Handling
995
+
996
+ ```typescript
997
+ @Tool({ name: 'get_user' })
998
+ async getUser(input: any, ctx: ExecutionContext) {
999
+ const user = await this.userService.findById(input.user_id);
1000
+
1001
+ if (!user) {
1002
+ throw new Error('User not found');
1003
+ }
1004
+
1005
+ return user;
1006
+ }
1007
+
1008
+ // Custom error class
1009
+ export class NotFoundError extends Error {
1010
+ constructor(resource: string, id: string) {
1011
+ super(`${resource} with ID ${id} not found`);
1012
+ this.name = 'NotFoundError';
1013
+ }
1014
+ }
1015
+
1016
+ @Tool({ name: 'get_product' })
1017
+ async getProduct(input: any) {
1018
+ const product = await this.productService.findById(input.product_id);
1019
+
1020
+ if (!product) {
1021
+ throw new NotFoundError('Product', input.product_id);
1022
+ }
1023
+
1024
+ return product;
1025
+ }
1026
+ ```
1027
+
1028
+ ---
1029
+
1030
+ ## File Structure
1031
+
1032
+ ```
1033
+ src/
1034
+ ├── modules/
1035
+ │ ├── auth/
1036
+ │ │ ├── auth.module.ts
1037
+ │ │ ├── auth.tools.ts
1038
+ │ │ ├── auth.resources.ts
1039
+ │ │ ├── auth.prompts.ts
1040
+ │ │ ├── auth.service.ts
1041
+ │ │ └── guards/
1042
+ │ │ └── jwt.guard.ts
1043
+ │ ├── products/
1044
+ │ │ ├── products.module.ts
1045
+ │ │ ├── products.tools.ts
1046
+ │ │ ├── products.resources.ts
1047
+ │ │ ├── products.prompts.ts
1048
+ │ │ └── products.service.ts
1049
+ │ └── ...
1050
+ ├── services/
1051
+ │ ├── database.service.ts
1052
+ │ └── cache.service.ts
1053
+ ├── guards/
1054
+ │ ├── jwt.guard.ts
1055
+ │ └── admin.guard.ts
1056
+ ├── middleware/
1057
+ │ └── logging.middleware.ts
1058
+ ├── interceptors/
1059
+ │ └── transform.interceptor.ts
1060
+ ├── pipes/
1061
+ │ └── validation.pipe.ts
1062
+ ├── health/
1063
+ │ ├── system.health.ts
1064
+ │ └── database.health.ts
1065
+ ├── widgets/
1066
+ │ ├── app/
1067
+ │ │ ├── product-card/
1068
+ │ │ ├── products-grid/
1069
+ │ │ └── ...
1070
+ │ ├── types/
1071
+ │ │ └── tool-data.ts
1072
+ │ └── styles/
1073
+ │ └── shared.ts
1074
+ ├── app.module.ts
1075
+ └── index.ts
1076
+ ```
1077
+
1078
+ ---
1079
+
1080
+ ## Import Rules
1081
+
1082
+ ### Always Use `.js` Extensions
1083
+
1084
+ ```typescript
1085
+ // ✅ Correct
1086
+ import { ProductService } from './products.service.js';
1087
+ import { JWTGuard } from '../auth/jwt.guard.js';
1088
+ import { DatabaseService } from '../../services/database.service.js';
1089
+
1090
+ // ❌ Wrong
1091
+ import { ProductService } from './products.service';
1092
+ ```
1093
+
1094
+ ### Core Imports
1095
+
1096
+ ```typescript
1097
+ // Core decorators
1098
+ import {
1099
+ Tool,
1100
+ Resource,
1101
+ Prompt,
1102
+ Module,
1103
+ McpApp,
1104
+ Injectable,
1105
+ UseGuards,
1106
+ Cache,
1107
+ RateLimit,
1108
+ HealthCheck,
1109
+ ExecutionContext
1110
+ } from 'nitrostack';
1111
+
1112
+ // Config
1113
+ import { ConfigModule, ConfigService } from 'nitrostack/config';
1114
+
1115
+ // JWT
1116
+ import { JWTModule } from 'nitrostack/jwt';
1117
+
1118
+ // Validation
1119
+ import { z } from 'zod';
1120
+
1121
+ // Widgets (in widget files)
1122
+ import { withToolData } from 'nitrostack/widgets';
1123
+ ```
1124
+
1125
+ ---
1126
+
1127
+ ## Common Patterns
1128
+
1129
+ ### CRUD Operations
1130
+
1131
+ ```typescript
1132
+ export class ProductsTools {
1133
+ constructor(private productService: ProductService) {}
1134
+
1135
+ // Create
1136
+ @Tool({
1137
+ name: 'create_product',
1138
+ inputSchema: z.object({
1139
+ name: z.string(),
1140
+ price: z.number(),
1141
+ category: z.string()
1142
+ })
1143
+ })
1144
+ @UseGuards(JWTGuard, AdminGuard)
1145
+ async create(input: any) {
1146
+ return await this.productService.create(input);
1147
+ }
1148
+
1149
+ // Read
1150
+ @Tool({
1151
+ name: 'get_product',
1152
+ inputSchema: z.object({ product_id: z.string() })
1153
+ })
1154
+ @Cache({ ttl: 60 })
1155
+ async get(input: any) {
1156
+ return await this.productService.findById(input.product_id);
1157
+ }
1158
+
1159
+ // Update
1160
+ @Tool({
1161
+ name: 'update_product',
1162
+ inputSchema: z.object({
1163
+ product_id: z.string(),
1164
+ name: z.string().optional(),
1165
+ price: z.number().optional()
1166
+ })
1167
+ })
1168
+ @UseGuards(JWTGuard, AdminGuard)
1169
+ async update(input: any) {
1170
+ return await this.productService.update(input.product_id, input);
1171
+ }
1172
+
1173
+ // Delete
1174
+ @Tool({
1175
+ name: 'delete_product',
1176
+ inputSchema: z.object({ product_id: z.string() })
1177
+ })
1178
+ @UseGuards(JWTGuard, AdminGuard)
1179
+ async delete(input: any) {
1180
+ await this.productService.delete(input.product_id);
1181
+ return { success: true };
1182
+ }
1183
+ }
1184
+ ```
1185
+
1186
+ ### Pagination Pattern
1187
+
1188
+ ```typescript
1189
+ @Tool({
1190
+ name: 'list_products',
1191
+ inputSchema: z.object({
1192
+ page: z.number().default(1),
1193
+ limit: z.number().default(20).max(100),
1194
+ category: z.string().optional()
1195
+ })
1196
+ })
1197
+ async listProducts(input: any) {
1198
+ const offset = (input.page - 1) * input.limit;
1199
+
1200
+ const products = await this.productService.list({
1201
+ limit: input.limit,
1202
+ offset,
1203
+ category: input.category
1204
+ });
1205
+
1206
+ const total = await this.productService.count({ category: input.category });
1207
+
1208
+ return {
1209
+ products,
1210
+ pagination: {
1211
+ page: input.page,
1212
+ limit: input.limit,
1213
+ total,
1214
+ pages: Math.ceil(total / input.limit)
1215
+ }
1216
+ };
1217
+ }
1218
+ ```
1219
+
1220
+ ### Search Pattern
1221
+
1222
+ ```typescript
1223
+ @Tool({
1224
+ name: 'search_products',
1225
+ inputSchema: z.object({
1226
+ query: z.string().min(1),
1227
+ filters: z.object({
1228
+ category: z.string().optional(),
1229
+ min_price: z.number().optional(),
1230
+ max_price: z.number().optional()
1231
+ }).optional()
1232
+ })
1233
+ })
1234
+ @Cache({ ttl: 30, key: (input) => `search:${input.query}:${JSON.stringify(input.filters)}` })
1235
+ async search(input: any) {
1236
+ return await this.productService.search(input.query, input.filters);
1237
+ }
1238
+ ```
1239
+
1240
+ ---
1241
+
1242
+ ## Key Rules for AI Agents
1243
+
1244
+ 1. ✅ **Always use decorators** - No factory functions
1245
+ 2. ✅ **Constructor injection** - Never use `new ClassName()`
1246
+ 3. ✅ **Services for logic** - Tools should be thin wrappers
1247
+ 4. ✅ **Zod for schemas** - All tool inputs must have inputSchema
1248
+ 5. ✅ **Return JSON** - All tool outputs must be JSON-serializable
1249
+ 6. ✅ **ES modules** - Use `.js` in imports, not `.ts`
1250
+ 7. ✅ **ExecutionContext** - Second parameter to all handlers
1251
+ 8. ✅ **Examples** - Always include request/response examples
1252
+
1253
+ ---
1254
+
1255
+ **That's the complete NitroStack SDK reference!**
1256
+
1257
+ For more details, check:
1258
+ - `/docs/sdk/typescript/` - Full documentation
1259
+ - `/templates/typescript-starter/` - Simple example
1260
+ - `/templates/typescript-auth/` - Full-featured example