
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
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.
npm install -g aion-cli
# 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
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 TypeScript code
aion generate schema.aion -o ./generated
# What you get:
# ✓ TypeScript types
# ✓ Express routes
# ✓ Client SDK
# ✓ Zod validators
# ✓ All fully typed!
aion initInitialize 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 generateGenerate 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 mockStart 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:
/docs/api/schemaaion docsGenerate 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 validateValidate an AION schema file.
aion validate <schema> [options]
Options:
--verbose Show detailed validation info
Examples:
aion validate schema.aion
aion validate schema.aion --verbose
Every .aion file follows this structure:
api ServiceName(version: X.Y.Z) {
// Entity definitions
entity EntityName {
// fields...
}
// API endpoints
endpoints {
// routes...
}
}
| 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) |
| 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) |
| 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]") |
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
}
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 {
// 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
}
}
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
}
}
}
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[]
}
}
}
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")
}
}
}
// 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);
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: 'user@example.com',
name: 'John Doe'
});
const users = await client.getUsers();
From a single .aion file, you get:
types.ts)export interface User {
id: UUID;
email: Email;
name: string;
age?: number;
role: UserRole;
created_at: Timestamp;
}
export type UserRole = "admin" | "user" | "guest";
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
});
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');
}
}
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()
});
entity User {
id: @uuid(generated) // Auto-generate UUID
created_at: @timestamp(auto) // Auto-set on creation
updated_at: @timestamp(auto) // Auto-update on modification
}
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
}
// Bad
status: @string
// Good
status: @enum("draft", "published", "archived")
entity Post {
author: -> User // Post belongs to User
}
entity User {
posts: <- Post[] // User has many Posts
}
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")
}
Contributions are welcome! Please feel free to submit a Pull Request.
MIT © AION Team
Built with:
Made with ❤️ by the AION Team
Write your API once. Get everything else free.
FAQs
Zero-boilerplate API development platform
We found that aion-cli demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.