Skip to content

SmooAI/utils

Repository files navigation

@smooai/utils — TypeScript utilities, zero boilerplate

npm Smoo AI license

downloads TypeScript

Features  ·  Install  ·  Usage  ·  Platform


The foundation utilities that power every Smoo AI service. They handle the repetitive infrastructure work — error handling, request tracking, validation, environment detection — so you focus on features. Type-safe, production-tested, zero configuration.

✨ Features

Stop copy-pasting the same utility functions across projects. One package gives you:

  • ✅ Production-tested utilities used across every Smoo AI service
  • ✅ Type-safe implementations with full TypeScript support
  • ✅ AWS Lambda integration that just works
  • ✅ Human-readable error messages your support team will thank you for
  • ✅ Sensible defaults out of the box — no configuration required

Concretely, that means a battle-tested Lambda apiHandler, schema validation that produces human-readable errors, case-insensitive collections for HTTP headers, production-ready Hono apps for Lambda, file discovery, environment detection, type-safe error handling, async helpers, and global phone-number validation.

📦 Install

pnpm add @smooai/utils

🚀 Usage

🚀 Lambda error handling

Stop writing try-catch blocks in every Lambda function. The apiHandler wrapper handles parsing, validation, error handling, logging, and response formatting:

import { apiHandler } from '@smooai/utils';

// Before: boilerplate everywhere
export const handler = async (event, context) => {
    try {
        // Parse body
        // Validate input
        // Handle errors
        // Format response
        // Log everything
    } catch (error) {
        // More error handling
    }
};

// After: focus on your logic
export const handler = apiHandler(async (event, context) => {
    const user = await createUser(event.body);
    return { statusCode: 201, body: user };
});
// Automatic error handling, logging, and response formatting

🎯 Validation with human-readable errors

Your users — and your support team — deserve better than ValidationError at path[0].nested.field:

import { handleSchemaValidation, HumanReadableSchemaError } from '@smooai/utils';

const userSchema = z.object({
    email: z.string().email(),
    phone: validateAndTransformPhoneNumber,
    age: z.number().min(18),
});

try {
    const user = handleSchemaValidation(userSchema, data);
    // user.phone is guaranteed to be E.164 format: +12125551234
} catch (error) {
    if (error instanceof HumanReadableSchemaError) {
        console.log(error.humanReadableMessage);
        // "Email must be a valid email address. Phone must be a valid phone number. Age must be at least 18."
    }
}

🔍 Case-insensitive collections for HTTP headers

Because Content-Type, content-type, and CONTENT-TYPE should all just work:

import { CaseInsensitiveMap } from '@smooai/utils';

const headers = new CaseInsensitiveMap([
    ['Content-Type', 'application/json'],
    ['X-API-KEY', 'secret'],
]);

headers.get('content-type'); // 'application/json'
headers.has('X-Api-Key'); // true
headers.get('CONTENT-TYPE'); // 'application/json'

🏭 Production-ready Hono apps for Lambda

Set up a fully configured API in one line:

import { createAwsLambdaHonoApp } from '@smooai/utils';

const app = createAwsLambdaHonoApp();

app.get('/health', (c) => c.json({ status: 'healthy' }));

app.post('/users', async (c) => {
    // Automatic request ID tracking
    // Built-in error handling
    // Pretty JSON in development
    const user = await createUser(await c.req.json());
    return c.json(user, 201);
});

export const handler = handle(app);

📁 Smart file discovery

Find configuration files without hardcoding paths:

import { findFile } from '@smooai/utils';

// Searches up the directory tree until it finds the file
const configPath = await findFile('smoo.config.json');
const packageJson = await findFile('package.json');

// Perfect for:
// - Finding project root
// - Loading environment-specific configs
// - Locating test fixtures

🌍 Environment detection

import { isRunningInProd, isRunningLocally } from '@smooai/utils';

if (isRunningLocally()) {
    // Enable debug logging
    // Use local database
    // Show detailed errors
}

if (isRunningInProd()) {
    // Use production services
    // Enable monitoring
    // Sanitize error messages
}

🛡️ Type-safe error handling

Transform cryptic errors into actionable messages:

import { ApiError, errorHandler } from '@smooai/utils';

const processPayment = errorHandler(
    async (orderId: string) => {
        // Throws ApiError with 404 status
        if (!order) throw new ApiError('Order not found', 404);

        // Validation errors become 400s with details
        const validated = handleSchemaValidation(schema, data);

        // Unexpected errors are logged and sanitized
        return await chargeCard(order);
    },
    {
        logger: console,
        onError: (error) => notifyOps(error),
    },
);

⏱️ Async utilities

import { sleep } from '@smooai/utils';

// Rate limiting made easy
for (const batch of batches) {
    await processBatch(batch);
    await sleep(1000); // Wait 1 second between batches
}

// Retry with exponential backoff
async function retryWithBackoff(fn, attempts = 3) {
    for (let i = 0; i < attempts; i++) {
        try {
            return await fn();
        } catch (error) {
            if (i === attempts - 1) throw error;
            await sleep(Math.pow(2, i) * 1000);
        }
    }
}

📞 Global phone-number validation

import { validateAndTransformPhoneNumber } from '@smooai/utils';

// Accepts multiple formats, outputs E.164
const phoneSchema = z.object({
    phone: validateAndTransformPhoneNumber,
});

phoneSchema.parse({ phone: '(212) 555-1234' });
// { phone: '+12125551234' }

phoneSchema.parse({ phone: '+44 20 7946 0958' });
// { phone: '+442079460958' }

phoneSchema.parse({ phone: '555-1234' });
// Throws: "Phone must be a valid phone number"

🔧 Built for production

Every utility in this package is:

  • 🔒 Type-safe — full TypeScript support with strict types
  • Performance tested — optimized for real-world usage
  • 📊 Battle-tested — used in production at Smoo AI
  • 📚 Well-documented — clear examples and use cases
  • 🔄 Maintained — regular updates and improvements

Testing

pnpm test

Linting

pnpm lint

🧩 Part of Smoo AI

@smooai/utils is built and open-sourced by Smoo AI — the AI-powered business platform with AI built into every product: CRM, customer support, campaigns, field service, observability, and developer tools.

🤝 Contributing

We're still developing our contribution processes. If you'd like to contribute or have questions, reach out through the contact information below.

📄 License

MIT — see LICENSE.

📬 Contact

Brent Rager

Smoo GitHub: https://github.com/SmooAI

(back to top)


Built by Smoo AI — AI built into every product.

About

Shared TypeScript utilities for SmooAI — Lambda error handling, production-ready Hono apps, smart retries, schema validation with human-readable errors, and environment detection.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors