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.
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.
pnpm add @smooai/utilsStop 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 formattingYour 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."
}
}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'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);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 fixturesimport { 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
}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),
},
);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);
}
}
}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"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
pnpm testpnpm lint@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.
- π§° More open source from Smoo AI β smoo.ai/open-source
- π§© Sibling packages β @smooai/logger, @smooai/fetch, @smooai/file, @smooai/config
We're still developing our contribution processes. If you'd like to contribute or have questions, reach out through the contact information below.
MIT β see LICENSE.
Brent Rager
Smoo GitHub: https://github.com/SmooAI
Built by Smoo AI β AI built into every product.
