UNPKG

services-as-software

Version:

Primitives for building AI-powered services that operate as software

206 lines 6.52 kB
/** * Service implementation */ /** * Create a service from a definition * * @example * ```ts * const service = Service({ * name: 'translation-service', * version: '1.0.0', * description: 'AI-powered translation service', * pricing: { * model: 'per-use', * pricePerUnit: 0.01, * currency: 'USD', * }, * endpoints: [ * Endpoint({ * name: 'translate', * method: 'POST', * path: '/translate', * input: { * type: 'object', * properties: { * text: { type: 'string' }, * from: { type: 'string' }, * to: { type: 'string' }, * }, * required: ['text', 'to'], * }, * handler: async (input) => { * // Translation logic here * return { translatedText: input.text } * }, * }), * ], * }) * ``` */ export function Service(definition) { // Store endpoints by name for quick lookup const endpointMap = new Map(); for (const endpoint of definition.endpoints) { endpointMap.set(endpoint.name, endpoint); } // Store event handlers const eventHandlers = new Map(); if (definition.events) { for (const [event, handler] of Object.entries(definition.events)) { eventHandlers.set(event, [handler]); } } // Store scheduled tasks const scheduledTasks = new Map(); if (definition.scheduled) { for (const task of definition.scheduled) { scheduledTasks.set(task.name, task); } } // Create the service instance const service = { definition, // Call an endpoint async call(endpoint, input, context) { const ep = endpointMap.get(endpoint); if (!ep) { throw new Error(`Endpoint not found: ${endpoint}`); } // Create context if not provided const ctx = context || { requestId: generateRequestId(), entitlements: [], }; // Track usage if tracker is available if (ctx.usage && ctx.customerId) { await ctx.usage.track({ customerId: ctx.customerId, resource: endpoint, quantity: 1, timestamp: new Date(), }); } // Call the handler return ep.handler(input, ctx); }, // Ask a question async ask(question, context) { return service.call('ask', { question, context }); }, // Deliver results async deliver(orderId, results) { return service.call('deliver', { orderId, results }); }, // Execute a task async do(action, input) { return service.call('do', { action, input }); }, // Generate content async generate(prompt, options) { return service.call('generate', { prompt, options }); }, // Type checking/validation async is(value, type) { return service.call('is', { value, type }); }, // Send notification async notify(notification) { return service.call('notify', notification); }, // Place an order async order(product, quantity) { return service.call('order', { product, quantity }); }, // Request a quote async quote(product, quantity) { return service.call('quote', { product, quantity }); }, // Subscribe to a plan async subscribe(planId) { return service.call('subscribe', { planId }); }, // Get entitlements async entitlements() { return service.call('entitlements', {}); }, // Get KPIs async kpis() { const result = {}; if (definition.kpis) { for (const kpi of definition.kpis) { result[kpi.id] = await kpi.calculate(); } } return result; }, // Get OKRs async okrs() { if (!definition.okrs) { return []; } // Calculate current values for key results const okrs = await Promise.all(definition.okrs.map(async (okr) => { const keyResults = await Promise.all(okr.keyResults.map(async (kr) => ({ ...kr, current: await kr.measure(), }))); return { ...okr, keyResults }; })); return okrs; }, // Register event handler on(event, handler) { const handlers = eventHandlers.get(event) || []; handlers.push({ event, handler: handler, }); eventHandlers.set(event, handlers); }, // Schedule recurring task every(schedule, handler) { const taskName = `task-${scheduledTasks.size + 1}`; scheduledTasks.set(taskName, { name: taskName, schedule, handler: (_input, context) => handler(context), enabled: true, }); }, // Add queue processor queue(name, handler) { // Queue processing would typically integrate with a queue system // For now, we add it as an event handler service.on(`queue:${name}`, handler); }, // Get service as RPC target asRPC() { // This would integrate with the RPC system from ai-functions // For now, return a placeholder return { _type: 'rpc-target', service: definition.name, version: definition.version, }; }, // Get service as API routes asAPI() { // This would generate HTTP/REST API routes // For now, return a placeholder with route definitions return definition.endpoints.map((ep) => ({ method: ep.method || 'POST', path: ep.path || `/${ep.name}`, handler: ep.handler, })); }, }; return service; } /** * Generate a unique request ID */ function generateRequestId() { return `req_${Date.now()}_${Math.random().toString(36).substring(2, 15)}`; } //# sourceMappingURL=service.js.map