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 🙏

© 2026 – Pkg Stats / Ryan Hefner

aion-cli

v1.0.0

Published

Zero-boilerplate API development platform

Readme

AION CLI

npm version License: MIT Node.js Version

Zero-Boilerplate API Development Platform

Write your API once. Get everything else free.

AION is a schema-first API development platform that generates TypeScript types, API routes, client SDKs, documentation, mock servers, and more from a single .aion file.

✨ Features

  • 🚀 Zero Boilerplate - Write schema once, generate everything
  • 📝 Type-Safe - Full TypeScript support with auto-generated types
  • 🔄 Auto-Generated Code - Routes, clients, validators, docs
  • 🎯 Mock Server - Instant backend with realistic fake data
  • 📚 Interactive Docs - Beautiful API documentation with playground
  • 🔗 Relationships - First-class support for entity relationships
  • Validation - Built-in request/response validation with Zod
  • 🎨 Developer Experience - Simple, intuitive schema language

🚀 Quick Start

Installation

npm install -g aion-cli

Create Your First API

# Initialize a new project
aion init my-api

# Navigate to the project
cd my-api

# Start the mock server
aion mock schema.aion

# Visit http://localhost:3000/docs

Example Schema

Create a file called schema.aion:

api UserService(version: 1.0.0) {
    
    entity User {
        id: @uuid(generated)
        email: @email(unique, indexed)
        name: @string(min: 2, max: 100)
        age: @int(min: 18, optional)
        role: @enum("admin", "user", "guest") default: "user"
        created_at: @timestamp(auto)
    }
    
    endpoints {
        POST /users {
            body: User(email, name, age?, role?)
            returns: User
        }
        
        GET /users {
            returns: User[]
        }
        
        GET /users/:id {
            returns: User
        }
    }
}

Generate Code

# Generate TypeScript code
aion generate schema.aion -o ./generated

# What you get:
# ✓ TypeScript types
# ✓ Express routes
# ✓ Client SDK
# ✓ Zod validators
# ✓ All fully typed!

📖 CLI Commands

aion init

Initialize a new AION project with a template.

aion init <project-name> [options]

Options:
  -t, --template <name>    Template to use (basic, blog, ecommerce)
  
Examples:
  aion init my-api
  aion init blog-api --template blog

aion generate

Generate code from an AION schema.

aion generate <schema> [options]

Options:
  -o, --output <dir>       Output directory (default: ./generated)
  -t, --target <target>    Target language (typescript)
  --no-validators          Skip generating validators
  --no-docs                Skip generating documentation
  
Examples:
  aion generate schema.aion
  aion generate schema.aion -o ./src/generated

aion mock

Start a mock API server with realistic fake data.

aion mock <schema> [options]

Options:
  -p, --port <port>        Port number (default: 3000)
  -d, --delay <ms>         Response delay in ms (default: 0)
  --no-cors                Disable CORS
  
Examples:
  aion mock schema.aion
  aion mock schema.aion --port 8080 --delay 500

The mock server includes:

  • ✓ Realistic fake data with Faker.js
  • ✓ Full CRUD operations
  • ✓ Relationship population
  • ✓ Interactive documentation at /docs
  • ✓ Schema introspection at /api/schema

aion docs

Generate static API documentation.

aion docs <schema> [options]

Options:
  -o, --output <file>      Output HTML file (default: docs.html)
  -s, --serve              Serve documentation locally
  -p, --port <port>        Port for local server (default: 8080)
  -b, --base-url <url>     Base URL for API
  
Examples:
  aion docs schema.aion
  aion docs schema.aion --serve
  aion docs schema.aion -o api-docs.html

aion validate

Validate an AION schema file.

aion validate <schema> [options]

Options:
  --verbose                Show detailed validation info
  
Examples:
  aion validate schema.aion
  aion validate schema.aion --verbose

📚 AION Language Reference

File Structure

Every .aion file follows this structure:

api ServiceName(version: X.Y.Z) {
    
    // Entity definitions
    entity EntityName {
        // fields...
    }
    
    // API endpoints
    endpoints {
        // routes...
    }
}

Type System

| Type | Description | Example | |------|-------------|---------| | @string | UTF-8 text | @string(min: 2, max: 100) | | @int | 32-bit integer | @int(min: 0, max: 100) | | @float | 64-bit float | @float(precision: 2) | | @bool | Boolean | @bool | | @uuid | UUID v4 | @uuid(generated) | | @email | Validated email | @email(unique, indexed) | | @url | Validated URL | @url(protocol: "https") | | @date | ISO 8601 date | @date | | @timestamp | ISO 8601 datetime | @timestamp(auto) | | @enum | Enumeration | @enum("active", "inactive") | | @currency | Money with currency | @currency("USD", precision: 2) |

Field Modifiers

| Modifier | Description | Example | |----------|-------------|---------| | optional | Field is not required | age: @int(optional) | | unique | Unique constraint | email: @email(unique) | | indexed | Create index | email: @email(indexed) | | generated | Auto-generated | id: @uuid(generated) | | auto | Auto-timestamp | created_at: @timestamp(auto) |

Constraints

| Constraint | Applies To | Example | |------------|------------|---------| | min | string, int, float | @string(min: 2) | | max | string, int, float | @string(max: 100) | | precision | float, currency | @float(precision: 2) | | pattern | string | @string(pattern: "^[A-Z]") |

Relationships

Belongs To (Many-to-One)

entity Post {
    id: @uuid(generated)
    title: @string(max: 200)
    author: -> User              // Post belongs to User
}

Generates:

interface Post {
  id: UUID;
  title: string;
  author_id: UUID;              // Foreign key
  author?: User;                // Populated object
}

Has Many (One-to-Many)

entity User {
    id: @uuid(generated)
    name: @string(max: 100)
    posts: <- Post[]             // User has many Posts
}

Generates:

interface User {
  id: UUID;
  name: string;
  posts?: Post[];               // Related posts
}

Endpoints

endpoints {
    // Create
    POST /users {
        body: User(email, name, age?)
        returns: User
        errors: {
            400: "Invalid input"
            409: "Email already exists"
        }
        @rate_limit("10/minute")
        @auth("required")
    }
    
    // Read all
    GET /users {
        returns: User[]
    }
    
    // Read one
    GET /users/:id {
        returns: User
    }
    
    // Update
    PUT /users/:id {
        body: User(name, age)
        returns: User
    }
    
    // Delete
    DELETE /users/:id {
        returns: User
    }
}

🎯 Complete Examples

Simple Task API

api TaskAPI(version: 1.0.0) {
    
    entity Task {
        id: @uuid(generated)
        title: @string(min: 1, max: 200)
        completed: @bool default: false
        created_at: @timestamp(auto)
    }
    
    endpoints {
        POST /tasks {
            body: Task(title)
            returns: Task
        }
        
        GET /tasks {
            returns: Task[]
        }
        
        PATCH /tasks/:id {
            body: Task(title?, completed?)
            returns: Task
        }
        
        DELETE /tasks/:id {
            returns: Task
        }
    }
}

Blog API with Relationships

api BlogAPI(version: 1.0.0) {
    
    entity User {
        id: @uuid(generated)
        email: @email(unique, indexed)
        name: @string(min: 2, max: 100)
        role: @enum("admin", "author", "reader") default: "reader"
        created_at: @timestamp(auto)
        
        posts: <- Post[]
        comments: <- Comment[]
    }
    
    entity Post {
        id: @uuid(generated)
        title: @string(min: 5, max: 200)
        content: @string(min: 10)
        published: @bool default: false
        created_at: @timestamp(auto)
        
        author: -> User
        comments: <- Comment[]
    }
    
    entity Comment {
        id: @uuid(generated)
        content: @string(min: 1, max: 500)
        created_at: @timestamp(auto)
        
        post: -> Post
        author: -> User
    }
    
    endpoints {
        POST /users {
            body: User(email, name, role?)
            returns: User
        }
        
        POST /posts {
            body: Post(title, content, author_id, published?)
            returns: Post
            @auth("required")
        }
        
        GET /posts {
            returns: Post[]
        }
        
        GET /posts/:id {
            returns: Post
        }
        
        POST /posts/:postId/comments {
            body: Comment(content, author_id)
            returns: Comment
            @auth("required")
        }
        
        GET /posts/:postId/comments {
            returns: Comment[]
        }
    }
}

E-commerce API

api EcommerceAPI(version: 1.0.0) {
    
    entity Product {
        id: @uuid(generated)
        name: @string(min: 2, max: 200)
        description: @string(max: 1000)
        price: @float(min: 0, precision: 2)
        stock: @int(min: 0)
        category: @enum("electronics", "clothing", "food", "other")
        created_at: @timestamp(auto)
    }
    
    entity Order {
        id: @uuid(generated)
        total: @float(min: 0, precision: 2)
        status: @enum("pending", "processing", "shipped", "delivered")
        customer_email: @email
        created_at: @timestamp(auto)
    }
    
    endpoints {
        GET /products {
            returns: Product[]
        }
        
        POST /products {
            body: Product(name, description, price, stock, category)
            returns: Product
            @auth("admin")
        }
        
        POST /orders {
            body: Order(total, status, customer_email)
            returns: Order
        }
        
        GET /orders/:id {
            returns: Order
            @auth("required")
        }
    }
}

🔧 Integration with Existing Projects

Using Generated Code

// Import generated types and routes
import { User, CreateUserInput } from './generated/types';
import { router } from './generated/routes';
import { UserSchema } from './generated/validators';

// Use in your Express app
import express from 'express';
const app = express();

app.use('/api', router);
app.listen(3000);

Using the Client SDK

import { UserServiceClient } from './generated/client';

const client = new UserServiceClient({
  baseURL: 'http://localhost:3000',
  headers: {
    'Authorization': 'Bearer token'
  }
});

// Fully typed API calls
const user = await client.createUser({
  email: '[email protected]',
  name: 'John Doe'
});

const users = await client.getUsers();

🎨 What Gets Generated

From a single .aion file, you get:

1. TypeScript Types (types.ts)

export interface User {
  id: UUID;
  email: Email;
  name: string;
  age?: number;
  role: UserRole;
  created_at: Timestamp;
}

export type UserRole = "admin" | "user" | "guest";

2. Express Routes (routes.ts)

router.post('/users', async (req, res) => {
  const body = req.body as CreateUserRequest;
  
  const validationResult = UserSchema.safeParse(body);
  if (!validationResult.success) {
    return res.status(400).json({
      error: 'Validation failed',
      details: validationResult.error.errors
    });
  }
  
  // Your handler logic here
});

3. Client SDK (client.ts)

export class UserServiceClient {
  async createUser(data: CreateUserInput): Promise<User> {
    return this.request('POST', '/users', data);
  }
  
  async getUsers(): Promise<User[]> {
    return this.request('GET', '/users');
  }
}

4. Validators (validators.ts)

export const UserSchema = z.object({
  email: z.string().email(),
  name: z.string().min(2).max(100),
  age: z.number().int().min(18).optional(),
  role: z.enum(["admin", "user", "guest"]).optional()
});

🏗️ Best Practices

1. Use Auto-Generated Fields

entity User {
    id: @uuid(generated)              // Auto-generate UUID
    created_at: @timestamp(auto)      // Auto-set on creation
    updated_at: @timestamp(auto)      // Auto-update on modification
}

2. Set Reasonable Constraints

entity User {
    name: @string(min: 2, max: 100)   // Prevent empty or excessive names
    age: @int(min: 0, max: 150)       // Reasonable age range
    email: @email(unique)              // Ensure valid, unique emails
}

3. Use Enums for Fixed Values

// Bad
status: @string

// Good
status: @enum("draft", "published", "archived")

4. Define Clear Relationships

entity Post {
    author: -> User          // Post belongs to User
}

entity User {
    posts: <- Post[]         // User has many Posts
}

5. Document with Comments

entity Order {
    // Total includes tax and shipping
    total: @float(min: 0, precision: 2)
    
    // Status workflow: pending -> processing -> shipped -> delivered
    status: @enum("pending", "processing", "shipped", "delivered")
}

🤝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

📄 License

MIT © AION Team

🔗 Links

🙏 Acknowledgments

Built with:


Made with ❤️ by the AION Team

Write your API once. Get everything else free.