UNPKG

services-as-software

Version:

Primitives for building AI-powered services that operate as software

145 lines (136 loc) 3.89 kB
/** * Endpoint helper for defining service endpoints */ import type { EndpointDefinition, PricingConfig, JSONSchema } from './types.js' /** * Endpoint configuration (input to Endpoint function) */ export interface EndpointConfig<TInput = unknown, TOutput = unknown> { /** Endpoint name */ name: string /** Description of what this endpoint does */ description?: string /** HTTP method (for REST endpoints) */ method?: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' /** Path pattern (e.g., '/users/:id') */ path?: string /** Input schema */ input?: JSONSchema /** Output schema */ output?: JSONSchema /** Handler function */ handler: EndpointDefinition<TInput, TOutput>['handler'] /** Pricing specific to this endpoint */ pricing?: PricingConfig /** Rate limiting */ rateLimit?: { requests: number window: number // milliseconds } /** Whether authentication is required */ requiresAuth?: boolean } /** * Create an endpoint definition * * @example * ```ts * const translateEndpoint = Endpoint({ * name: 'translate', * description: 'Translate text between languages', * method: 'POST', * path: '/translate', * input: { * type: 'object', * properties: { * text: { type: 'string', description: 'Text to translate' }, * from: { type: 'string', description: 'Source language code' }, * to: { type: 'string', description: 'Target language code' }, * }, * required: ['text', 'to'], * additionalProperties: false, * }, * output: { * type: 'object', * properties: { * translatedText: { type: 'string' }, * confidence: { type: 'number' }, * }, * required: ['translatedText'], * additionalProperties: false, * }, * handler: async (input, context) => { * // Translation logic here * return { * translatedText: `Translated: ${input.text}`, * confidence: 0.95, * } * }, * pricing: { * model: 'per-use', * pricePerUnit: 0.01, * currency: 'USD', * }, * rateLimit: { * requests: 100, * window: 60000, // 1 minute * }, * }) * ``` */ export function Endpoint<TInput = unknown, TOutput = unknown>( config: EndpointConfig<TInput, TOutput> ): EndpointDefinition<TInput, TOutput> { return { name: config.name, description: config.description, method: config.method || 'POST', path: config.path || `/${config.name}`, input: config.input, output: config.output, handler: config.handler, pricing: config.pricing, rateLimit: config.rateLimit, requiresAuth: config.requiresAuth !== false, // Default to true } } /** * Create a GET endpoint */ export function GET<TInput = unknown, TOutput = unknown>( config: Omit<EndpointConfig<TInput, TOutput>, 'method'> ): EndpointDefinition<TInput, TOutput> { return Endpoint({ ...config, method: 'GET' }) } /** * Create a POST endpoint */ export function POST<TInput = unknown, TOutput = unknown>( config: Omit<EndpointConfig<TInput, TOutput>, 'method'> ): EndpointDefinition<TInput, TOutput> { return Endpoint({ ...config, method: 'POST' }) } /** * Create a PUT endpoint */ export function PUT<TInput = unknown, TOutput = unknown>( config: Omit<EndpointConfig<TInput, TOutput>, 'method'> ): EndpointDefinition<TInput, TOutput> { return Endpoint({ ...config, method: 'PUT' }) } /** * Create a DELETE endpoint */ export function DELETE<TInput = unknown, TOutput = unknown>( config: Omit<EndpointConfig<TInput, TOutput>, 'method'> ): EndpointDefinition<TInput, TOutput> { return Endpoint({ ...config, method: 'DELETE' }) } /** * Create a PATCH endpoint */ export function PATCH<TInput = unknown, TOutput = unknown>( config: Omit<EndpointConfig<TInput, TOutput>, 'method'> ): EndpointDefinition<TInput, TOutput> { return Endpoint({ ...config, method: 'PATCH' }) }