|
1 | | -import type { CollectionTool, GlobalTool, Prompt, Tool, ToolInputSchema } from './types.js' |
| 1 | +import type { MaybePromise } from 'payload' |
| 2 | + |
| 3 | +import type { |
| 4 | + CollectionTool, |
| 5 | + CollectionToolHandlerArgs, |
| 6 | + GlobalTool, |
| 7 | + GlobalToolHandlerArgs, |
| 8 | + MCPToolResponse, |
| 9 | + Prompt, |
| 10 | + PromptHandlerArgs, |
| 11 | + Tool, |
| 12 | + ToolHandlerArgs, |
| 13 | + ToolInputSchema, |
| 14 | +} from './types.js' |
2 | 15 |
|
3 | 16 | /** |
4 | | - * Two-stage builder: pass the schema/metadata first, then chain `.handler(fn)`. Splitting the |
5 | | - * call lets TypeScript resolve `TSchema` from `input` (call 1) before contextually typing the |
6 | | - * handler (call 2). A single-call API hit a TS limitation where property order in the literal |
7 | | - * decided whether `TSchema` was inferred or pinned to its default. |
8 | | - * |
9 | | - * defineCollectionTool({ description, input }) |
10 | | - * .handler(({ input }) => …) // ← input is fully typed here regardless of order |
| 17 | + * Identity helpers that exist solely so TypeScript infers `TSchema` from `input` (or |
| 18 | + * `argsSchema` for prompts) and then types the handler's `input` against it. |
11 | 19 | * |
12 | | - * Config and handler signatures are derived from `Tool` / `CollectionTool` / `GlobalTool` / |
13 | | - * `Prompt` via `Omit` + indexed access so there's no duplication with `types.ts`. |
| 20 | + * The `NoInfer<>` wrapper on the handler's args is what makes this work in a single |
| 21 | + * call: it tells TS not to use the handler signature when inferring `TSchema`, so |
| 22 | + * inference is driven solely by the schema field. |
14 | 23 | */ |
15 | 24 |
|
16 | | -export const defineTool = < |
17 | | - TSchema extends ToolInputSchema | undefined = ToolInputSchema | undefined, |
18 | | ->( |
19 | | - args: Omit<Tool<TSchema>, 'handler'>, |
20 | | -): { handler: (fn: Tool<TSchema>['handler']) => Tool } => ({ |
21 | | - handler: (fn) => ({ ...args, handler: fn }) as unknown as Tool, |
22 | | -}) |
| 25 | +export const defineTool = <TSchema extends ToolInputSchema | undefined = undefined>( |
| 26 | + tool: { |
| 27 | + handler: (args: ToolHandlerArgs<NoInfer<TSchema>>) => MaybePromise<MCPToolResponse> |
| 28 | + } & Omit<Tool<TSchema>, 'handler'>, |
| 29 | +): Tool => tool as unknown as Tool |
23 | 30 |
|
24 | | -export const defineCollectionTool = < |
25 | | - TSchema extends ToolInputSchema | undefined = ToolInputSchema | undefined, |
26 | | ->( |
27 | | - args: Omit<CollectionTool<TSchema>, 'handler'>, |
28 | | -): { handler: (fn: CollectionTool<TSchema>['handler']) => CollectionTool } => ({ |
29 | | - handler: (fn) => ({ ...args, handler: fn }) as unknown as CollectionTool, |
30 | | -}) |
| 31 | +export const defineCollectionTool = <TSchema extends ToolInputSchema | undefined = undefined>( |
| 32 | + tool: { |
| 33 | + handler: (args: CollectionToolHandlerArgs<NoInfer<TSchema>>) => MaybePromise<MCPToolResponse> |
| 34 | + } & Omit<CollectionTool<TSchema>, 'handler'>, |
| 35 | +): CollectionTool => tool as unknown as CollectionTool |
31 | 36 |
|
32 | | -export const defineGlobalTool = < |
33 | | - TSchema extends ToolInputSchema | undefined = ToolInputSchema | undefined, |
34 | | ->( |
35 | | - args: Omit<GlobalTool<TSchema>, 'handler'>, |
36 | | -): { handler: (fn: GlobalTool<TSchema>['handler']) => GlobalTool } => ({ |
37 | | - handler: (fn) => ({ ...args, handler: fn }) as unknown as GlobalTool, |
38 | | -}) |
| 37 | +export const defineGlobalTool = <TSchema extends ToolInputSchema | undefined = undefined>( |
| 38 | + tool: { |
| 39 | + handler: (args: GlobalToolHandlerArgs<NoInfer<TSchema>>) => MaybePromise<MCPToolResponse> |
| 40 | + } & Omit<GlobalTool<TSchema>, 'handler'>, |
| 41 | +): GlobalTool => tool as unknown as GlobalTool |
39 | 42 |
|
40 | 43 | export const definePrompt = <TSchema extends ToolInputSchema = ToolInputSchema>( |
41 | | - args: Omit<Prompt<TSchema>, 'handler'>, |
42 | | -): { handler: (fn: Prompt<TSchema>['handler']) => Prompt } => ({ |
43 | | - handler: (fn) => ({ ...args, handler: fn }) as unknown as Prompt, |
44 | | -}) |
| 44 | + prompt: { |
| 45 | + handler: (args: PromptHandlerArgs<NoInfer<TSchema>>) => ReturnType<Prompt<TSchema>['handler']> |
| 46 | + } & Omit<Prompt<TSchema>, 'handler'>, |
| 47 | +): Prompt => prompt as unknown as Prompt |
0 commit comments