npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

crunchycone-lib

v0.1.44

Published

TypeScript library providing abstractions for CrunchyCone Starter Projects

Readme

CrunchyCone Library

TypeScript Apache License Tests npm version

A comprehensive TypeScript library providing unified abstractions for email services, storage providers, and template engines. Designed for CrunchyCone Starter Projects but flexible enough for any TypeScript/JavaScript application.

🚀 Features

✉️ Email Services

  • Unified API across 7+ email providers (SendGrid, Resend, Amazon SES, SMTP, Mailgun, CrunchyCone, Console)
  • Provider abstraction - switch providers without code changes
  • Provider availability checking - programmatically check if dependencies are available
  • Built-in templates with MJML v4 + LiquidJS templating
  • Template includes - reusable components with {% include 'filename' %}
  • Multi-language support with automatic fallbacks
  • Development-friendly console provider for testing

📁 Storage Services

  • Multi-provider support (AWS S3, Google Cloud, Azure Blob, CrunchyCone, LocalStorage, and more)
  • Provider availability checking - detect available storage providers
  • File streaming with range request support
  • Metadata management and search capabilities
  • Public/private file visibility controls
  • External ID mapping for easy integration

🤖 AI Services

  • Unified AI interface across OpenAI, Anthropic, and CrunchyCone providers
  • Provider abstraction - switch AI providers without code changes
  • Streaming support for real-time response generation
  • Chat and generation APIs with consistent interfaces
  • Provider availability checking - detect installed AI SDKs
  • Zero required dependencies - install only the providers you need

🛡️ Authentication & API Client

  • API-first authentication with CLI fallback for CrunchyCone services
  • CrunchyCone API Client for direct API access (user info, project details)
  • Unified auth service supporting multiple authentication methods
  • Environment variable and keychain support (keytar)
  • CLI fallback via crunchycone-cli auth check
  • Production-ready authentication for containerized environments

🌍 Environment & Secrets Management

  • Unified environment management across local development and CrunchyCone platform
  • Automatic provider detection via CRUNCHYCONE_PLATFORM=1 environment variable
  • Local .env file management with proper parsing, escaping, and serialization
  • Remote secrets management via CrunchyCone API (write-only for security)
  • Environment variables supported in both local and platform environments
  • Bulk operations for efficient variable/secrets management

📦 Installation

npm install crunchycone-lib

Optional Dependencies (Install as needed)

# For AI services
npm install openai                # OpenAI provider
npm install @anthropic-ai/sdk     # Anthropic provider

# For AWS services (S3 storage, SES email)
npm install @aws-sdk/client-s3 @aws-sdk/client-ses @aws-sdk/s3-request-presigner

# For Google Cloud Storage
npm install @google-cloud/storage

# For Azure Storage
npm install @azure/storage-blob

# For MJML v4 email templating (responsive email templates)
npm install mjml
npm install --save-dev @types/mjml

# Note: liquidjs and html-to-text are included as dependencies

🔧 Quick Start

Email Service

import { createEmailService } from 'crunchycone-lib';

// Create email service (uses environment variables for configuration)
const emailService = createEmailService('sendgrid');

// Send email
const result = await emailService.sendEmail({
  to: '[email protected]',
  subject: 'Hello World',
  textBody: 'Hello from CrunchyCone!',
  htmlBody: '<h1>Hello from CrunchyCone!</h1>'
});

console.log(`Email sent with ID: ${result.messageId}`);

Provider Availability Checking

import { isEmailProviderAvailable, getAvailableEmailProviders, isStorageProviderAvailable, getAvailableStorageProviders } from 'crunchycone-lib';

// Check if specific providers are available (has dependencies installed)
const sendGridAvailable = await isEmailProviderAvailable('sendgrid');
const s3Available = await isStorageProviderAvailable('s3');

console.log('SendGrid available:', sendGridAvailable);
console.log('S3 available:', s3Available);

// Get all available providers
const availableEmailProviders = await getAvailableEmailProviders();
const availableStorageProviders = await getAvailableStorageProviders();

console.log('Available email providers:', availableEmailProviders);
// Output: ['console', 'smtp', 'crunchycone', 'mailgun'] (+ others if dependencies installed)

console.log('Available storage providers:', availableStorageProviders);  
// Output: ['localstorage', 'crunchycone'] (+ others if dependencies installed)

// Check provider availability on service instances
const emailService = createEmailService('console');
const available = await emailService.isAvailable();
console.log('Service available:', available); // true

Specific Provider Import (No Optional Dependencies)

// Import specific providers to avoid loading optional dependencies
import { AmazonSESEmailService } from 'crunchycone-lib/email/providers/amazon-ses';
import { S3CompatibleProvider } from 'crunchycone-lib/storage/providers/s3';

// Only loads when the provider is actually used
const emailService = new AmazonSESEmailService();
const storageProvider = new S3CompatibleProvider(config);

Storage Service

import { StorageService } from 'crunchycone-lib/storage';

const storage = new StorageService({
  provider: 'crunchycone',
  config: {
    projectId: 'your-project-id'
  }
});

// Upload file
const result = await storage.uploadFile('my-file.txt', fileBuffer, {
  externalId: 'user-avatar-123',
  visibility: 'public'
});

// Get public URL
const url = await storage.getFileUrl(result.key);
console.log(`File available at: ${url}`);

Email Templates (MJML v4 + LiquidJS)

import { createEmailTemplateService } from 'crunchycone-lib/email/templates';

const templates = createEmailTemplateService({
  provider: 'filesystem',
  templatesPath: './templates/email'
});

// Render template with data and includes
const rendered = await templates.renderTemplate('welcome', 'en', {
  userName: 'John Doe',
  appName: 'MyApp',
  activationUrl: 'https://app.example.com/activate/123'
});

// Send templated email
await emailService.sendEmail({
  to: '[email protected]',
  subject: rendered.subject,
  html: rendered.html,
  text: rendered.text
});

Environment & Secrets Management

The environment service automatically detects your runtime environment and provides the appropriate functionality:

import { getCrunchyConeEnvironmentService, isPlatformEnvironment } from 'crunchycone-lib';

const envService = getCrunchyConeEnvironmentService();

// Check environment
console.log('Platform environment:', isPlatformEnvironment()); // true if CRUNCHYCONE_PLATFORM=1

// Environment variables (works locally and in platform)
await envService.setEnvVar('DATABASE_URL', 'postgres://localhost/myapp');
const dbUrl = await envService.getEnvVar('DATABASE_URL');

// List all environment variables
const allVars = await envService.listEnvVars();

// Bulk operations
await envService.setEnvVars({
  API_TIMEOUT: '30000',
  DEBUG_MODE: 'true',
  APP_NAME: 'MyApp'
});

// Secrets (only works in platform environment)
if (envService.supportsSecrets()) {
  await envService.setSecret('JWT_SECRET', 'your-secret-key');
  await envService.setSecret('API_TOKEN', 'secret-api-token');
  
  // List secret names (values are never returned for security)
  const secretNames = await envService.listSecretNames();
  console.log('Available secrets:', secretNames); // ['JWT_SECRET', 'API_TOKEN']
}

Environment Detection:

  • Local Development (default): Manages .env files, secrets operations are no-ops
  • Platform Environment (CRUNCHYCONE_PLATFORM=1): Uses CrunchyCone API for both env vars and secrets

Template Structure with Includes:

templates/email/
├── en/
│   ├── includes/
│   │   ├── header.liquid
│   │   └── footer.liquid
│   └── welcome/
│       ├── template-html.mjml (uses {% include 'header' %})
│       └── subject.liquid

AI Services

Unified interface for AI providers (OpenAI, Anthropic, CrunchyCone):

import { createAIService } from '@crunchycone/crunchycone-lib';

// Create AI service
const ai = createAIService('openai');

// Generate response
const response = await ai.generate('What is TypeScript?');
console.log(response.content);

// Chat with history
const chatResponse = await ai.chat({
  messages: [
    { role: 'system', content: 'You are helpful' },
    { role: 'user', content: 'Hello!' }
  ],
  temperature: 0.7
});

// Streaming
const stream = await ai.streamGenerate('Tell me a story');
for await (const chunk of stream.stream) {
  process.stdout.write(chunk.content);
}

See docs/AI_SERVICE.md for complete documentation.

Service Provider Discovery

Programmatically discover available service providers across all services:

import { getEmailProviders, getStorageProviders, getAllServiceProviders } from 'crunchycone-lib';

// Get all email providers
const emailProviders = await getEmailProviders();

// Get only available providers (dependencies installed)
const availableProviders = await getEmailProviders({ onlyAvailable: true });

// Get storage providers with availability information
const storageProviders = await getStorageProviders({ checkAvailability: true });

// Get all providers across all services
const allProviders = await getAllServiceProviders();
console.log(`Found ${allProviders.email.length} email providers`);
console.log(`Found ${allProviders.storage.length} storage providers`);
console.log(`Found ${allProviders.ai.length} AI providers`);

Each provider includes:

  • Name, ID, and icon (base64 data URL for immediate use)
  • Required environment variables with validation rules and descriptions
  • Availability status (checks if dependencies are installed)
  • Documentation links and usage examples
  • Sensitive field indicators for secure handling

Total Providers: 23 providers across 4 service types

  • 7 Email providers (SMTP, SendGrid, Resend, Amazon SES, Mailgun, CrunchyCone, Console)
  • 11 Storage providers (LocalStorage, AWS S3, Google Cloud, Azure, R2, DigitalOcean, Wasabi, Backblaze, S3-Compatible, CrunchyCone)
  • 3 AI providers (OpenAI, Anthropic, CrunchyCone)
  • 2 Environment providers (Local .env, CrunchyCone Remote)

See Service Provider Discovery for full documentation.

📚 Documentation

🔐 Environment Variables

The library uses environment variables for configuration. Here are the key ones:

Environment & Secrets Management

# Platform Detection
CRUNCHYCONE_PLATFORM=1                # Enables CrunchyCone platform mode (uses API)

# CrunchyCone API (required for platform mode)
CRUNCHYCONE_API_KEY=your_api_key      # API key for CrunchyCone services
CRUNCHYCONE_PROJECT_ID=your_project   # Project ID for environment/secrets API
CRUNCHYCONE_API_URL=https://api.crunchycone.com  # Optional: custom API URL

AI Services

# Provider Selection
CRUNCHYCONE_AI_PROVIDER=openai                    # Default provider (openai, anthropic, crunchycone)

# OpenAI
CRUNCHYCONE_OPENAI_API_KEY=sk-...                 # OpenAI API key
CRUNCHYCONE_OPENAI_DEFAULT_MODEL=gpt-4o           # Default model

# Anthropic
CRUNCHYCONE_ANTHROPIC_API_KEY=sk-ant-...          # Anthropic API key
CRUNCHYCONE_ANTHROPIC_DEFAULT_MODEL=claude-sonnet-4-5-20250929  # Default model

# CrunchyCone AI (uses existing CrunchyCone credentials)
CRUNCHYCONE_API_KEY=your_api_key
CRUNCHYCONE_PROJECT_ID=your_project_id

Email Services

# SendGrid
CRUNCHYCONE_SENDGRID_API_KEY=your_sendgrid_api_key
[email protected]

# Resend
CRUNCHYCONE_RESEND_API_KEY=your_resend_api_key
[email protected]

# CrunchyCone
CRUNCHYCONE_API_KEY=your_crunchycone_api_key

Storage Services

# CrunchyCone Storage
CRUNCHYCONE_API_KEY=your_crunchycone_api_key
CRUNCHYCONE_PROJECT_ID=your_project_id

# AWS S3
CRUNCHYCONE_AWS_ACCESS_KEY_ID=your_access_key
CRUNCHYCONE_AWS_SECRET_ACCESS_KEY=your_secret_key
CRUNCHYCONE_AWS_REGION=us-west-2

See the documentation for complete environment variable lists.

📁 Module Structure

The library is organized into focused modules with zero optional dependencies at the main entry point:

// Core exports (no optional dependencies)
import { createEmailService, EmailService, isEmailProviderAvailable, getAvailableEmailProviders, getCrunchyConeEnvironmentService, isPlatformEnvironment } from 'crunchycone-lib';

// AI services (no optional dependencies in core)
import { createAIService, isAIProviderAvailable, getAvailableAIProviders } from 'crunchycone-lib/ai';

// Email services (no optional dependencies)
import { createEmailService, isEmailProviderAvailable, getAvailableEmailProviders } from 'crunchycone-lib/email';

// Email templates (core functionality, no optional dependencies)
import { createEmailTemplateService } from 'crunchycone-lib/email/templates';

// Storage services (loads core without providers)
import { StorageService, isStorageProviderAvailable, getAvailableStorageProviders } from 'crunchycone-lib/storage';

// Authentication utilities (no optional dependencies)
import { getCrunchyConeAPIKey } from 'crunchycone-lib/auth';

// Environment & Secrets Management (no optional dependencies)
import { getCrunchyConeEnvironmentService, isPlatformEnvironment } from 'crunchycone-lib/environment';

// Specific AI providers (only loads when imported)
import { OpenAIService } from 'crunchycone-lib/ai/providers/openai';
import { AnthropicService } from 'crunchycone-lib/ai/providers/anthropic';

// Specific email providers (only loads when imported)
import { AmazonSESEmailService } from 'crunchycone-lib/email/providers/amazon-ses';
import { SendGridEmailService } from 'crunchycone-lib/email/providers/sendgrid';

// Specific storage providers (only loads when imported)
import { S3CompatibleProvider } from 'crunchycone-lib/storage/providers/s3';
import { GCPStorageProvider } from 'crunchycone-lib/storage/providers/gcp';
import { AzureStorageProvider } from 'crunchycone-lib/storage/providers/azure';

// Template engines (only loads when imported)
import { MJMLLiquidEngine } from 'crunchycone-lib/email/templates/engines/mjml-liquid';

// Next.js API helpers
import { createApiHandler } from 'crunchycone-lib/api-external';

🎯 Zero Optional Dependencies at Import

The main entry point (crunchycone-lib) and core modules can be imported without installing any optional dependencies (cloud provider SDKs, MJML, etc.). Optional dependencies are only required when you import and use specific providers or template engines.

Example: Email-only usage (no storage, cloud, or MJML dependencies needed):

import { createEmailService } from 'crunchycone-lib';

// Only requires core dependencies - works without AWS, Azure, GCP SDKs, or MJML!
const emailService = createEmailService('console');

Example: MJML templates (requires MJML to be installed):

import { MJMLLiquidEngine } from 'crunchycone-lib/email/templates/engines/mjml-liquid';

// Requires: npm install mjml
const mjmlEngine = new MJMLLiquidEngine(templateProvider);

🧪 Testing

# Run all tests
npm test

# Run tests in watch mode
npm run test:watch

# Run with coverage
npm run test:coverage

# Lint code
npm run lint

# Fix lint issues
npm run lint:fix

🔧 Development

# Build the library
npm run build

# Clean build artifacts
npm run clean

# Test email functionality
npm run email-test

# Test storage functionality
npm run storage-test

# Interactive storage CLI
npm run storage-cli

📊 Provider Support Matrix

Email Providers

| Provider | Status | Dependencies | Features | |----------|---------|-------------|----------| | Console | ✅ Built-in | None | Development/testing | | SMTP | ✅ Ready | nodemailer | Self-hosted | | SendGrid | ✅ Ready | @sendgrid/mail | Transactional | | Resend | ✅ Ready | resend | Modern API | | Amazon SES | ✅ Ready | @aws-sdk/client-ses | AWS ecosystem | | Mailgun | ✅ Ready | mailgun-js | Reliable delivery | | CrunchyCone | ✅ Ready | None | Integrated platform |

Storage Providers

| Provider | Status | Dependencies | Features | |----------|---------|-------------|----------| | LocalStorage | ✅ Built-in | None | Development/testing | | CrunchyCone | ✅ Ready | None | Integrated platform | | AWS S3 | ✅ Ready | @aws-sdk/client-s3 | Industry standard | | Google Cloud | ✅ Ready | @google-cloud/storage | GCP ecosystem | | Azure Blob | ✅ Ready | @azure/storage-blob | Azure ecosystem | | R2 (Cloudflare) | ✅ Ready | S3-compatible | Edge storage | | DigitalOcean Spaces | ✅ Ready | S3-compatible | Simple cloud | | Backblaze B2 | ✅ Ready | S3-compatible | Cost-effective | | Wasabi | ✅ Ready | S3-compatible | Hot storage |

🤝 Contributing

  1. Fork the repository
  2. Create a feature branch: git checkout -b feature/amazing-feature
  3. Make your changes and add tests
  4. Ensure tests pass: npm test
  5. Commit your changes: git commit -m 'Add amazing feature'
  6. Push to the branch: git push origin feature/amazing-feature
  7. Open a Pull Request

📄 License

This project is licensed under the Apache License 2.0 - see the LICENSE file for details.

🔗 Related Projects

💬 Support


Built with ❤️ and lots of 🍨 by the CrunchyCone team