* Invoke a function with the given context.
(ctx: FunctionCallContext)
| 118 | * Invoke a function with the given context. |
| 119 | */ |
| 120 | public invoke(ctx: FunctionCallContext): unknown { |
| 121 | const def = this.get(ctx.name); |
| 122 | if (!def) { |
| 123 | throw new Error(`Unknown function: ${ctx.name}`); |
| 124 | } |
| 125 | |
| 126 | // Validate argument count |
| 127 | const requiredArgs = def.args.filter((a) => a.required).length; |
| 128 | if (ctx.args.length < requiredArgs) { |
| 129 | throw new Error( |
| 130 | `Function ${ctx.name} requires at least ${requiredArgs} argument(s), got ${ctx.args.length}`, |
| 131 | ); |
| 132 | } |
| 133 | // Skip max args check for variadic functions |
| 134 | if (!def.variadic && ctx.args.length > def.args.length) { |
| 135 | throw new Error( |
| 136 | `Function ${ctx.name} accepts at most ${def.args.length} argument(s), got ${ctx.args.length}`, |
| 137 | ); |
| 138 | } |
| 139 | |
| 140 | // Validate DISTINCT usage |
| 141 | if (ctx.distinct && !def.supportsDistinct) { |
| 142 | throw new Error(`Function ${ctx.name} does not support DISTINCT`); |
| 143 | } |
| 144 | |
| 145 | return def.impl(ctx.args, ctx.path); |
| 146 | } |
| 147 | |
| 148 | /** |
| 149 | * Get all registered function names. |
no test coverage detected