Skip to main content
ClaudeWave
Skill71 estrellas del repoactualizado yesterday

adonisjs

>-

Instalar en Claude Code
Copiar
git clone --depth 1 https://github.com/TerminalSkills/skills /tmp/adonisjs && cp -r /tmp/adonisjs/skills/adonisjs ~/.claude/skills/adonisjs
Después abre una sesión nueva de Claude Code; el skill carga automáticamente.

SKILL.md

# AdonisJS

## Overview

AdonisJS is a full-stack Node.js framework — the "Laravel of Node.js." Unlike Express/Fastify where you assemble everything from packages, AdonisJS ships with an ORM (Lucid), authentication, validation (VineJS), mailer, queues, and testing out of the box. Opinionated, TypeScript-first, and production-ready.

## When to Use

- Building a complete web application (not just an API) with Node.js
- Want an opinionated framework with conventions (like Rails/Laravel)
- Need built-in auth (sessions, API tokens, social OAuth)
- Database-driven applications with migrations and models
- Teams that prefer convention over configuration

## Instructions

### Setup

```bash
npm init adonisjs@latest my-app -- --kit=web
cd my-app
node ace serve --watch
```

### Routes and Controllers

```typescript
// start/routes.ts — Route definitions
import router from "@adonisjs/core/services/router";
const UsersController = () => import("#controllers/users_controller");

router.group(() => {
  router.get("/users", [UsersController, "index"]);
  router.get("/users/:id", [UsersController, "show"]);
  router.post("/users", [UsersController, "store"]);
  router.put("/users/:id", [UsersController, "update"]);
  router.delete("/users/:id", [UsersController, "destroy"]);
}).prefix("/api");
```

```typescript
// app/controllers/users_controller.ts — Controller with validation
import type { HttpContext } from "@adonisjs/core/http";
import User from "#models/user";
import { createUserValidator, updateUserValidator } from "#validators/user";

export default class UsersController {
  async index({ request }: HttpContext) {
    const page = request.input("page", 1);
    const limit = request.input("limit", 20);
    return User.query().paginate(page, limit);
  }

  async show({ params }: HttpContext) {
    return User.findOrFail(params.id);
  }

  async store({ request, response }: HttpContext) {
    const data = await request.validateUsing(createUserValidator);
    const user = await User.create(data);
    return response.created(user);
  }

  async update({ params, request }: HttpContext) {
    const user = await User.findOrFail(params.id);
    const data = await request.validateUsing(updateUserValidator);
    user.merge(data);
    await user.save();
    return user;
  }

  async destroy({ params, response }: HttpContext) {
    const user = await User.findOrFail(params.id);
    await user.delete();
    return response.noContent();
  }
}
```

### Lucid ORM (Models and Migrations)

```typescript
// app/models/user.ts — Lucid model with relationships
import { DateTime } from "luxon";
import { BaseModel, column, hasMany } from "@adonisjs/lucid/orm";
import type { HasMany } from "@adonisjs/lucid/types/relations";
import Post from "#models/post";

export default class User extends BaseModel {
  @column({ isPrimary: true })
  declare id: number;

  @column()
  declare email: string;

  @column()
  declare name: string;

  @column({ serializeAs: null })  // Never include in JSON
  declare password: string;

  @hasMany(() => Post)
  declare posts: HasMany<typeof Post>;

  @column.dateTime({ autoCreate: true })
  declare createdAt: DateTime;

  @column.dateTime({ autoCreate: true, autoUpdate: true })
  declare updatedAt: DateTime;
}
```

```bash
# Generate migration
node ace make:migration create_users_table

# Run migrations
node ace migration:run

# Rollback
node ace migration:rollback
```

### VineJS Validation

```typescript
// app/validators/user.ts — Request validation with VineJS
import vine from "@vinejs/vine";

export const createUserValidator = vine.compile(
  vine.object({
    email: vine.string().email().unique(async (db, value) => {
      const user = await db.from("users").where("email", value).first();
      return !user;  // Must not exist
    }),
    name: vine.string().minLength(2).maxLength(100),
    password: vine.string().minLength(8).confirmed(),  // password + password_confirmation
  })
);

export const updateUserValidator = vine.compile(
  vine.object({
    name: vine.string().minLength(2).maxLength(100).optional(),
    email: vine.string().email().optional(),
  })
);
```

### Authentication

```typescript
// config/auth.ts — Auth config (sessions + API tokens)
import { defineConfig } from "@adonisjs/auth";
import { sessionGuard, sessionUserProvider } from "@adonisjs/auth/session";
import { tokensGuard, tokensUserProvider } from "@adonisjs/auth/access_tokens";

export default defineConfig({
  default: "web",
  guards: {
    web: sessionGuard({ useRememberMeTokens: true, provider: sessionUserProvider({ model: () => import("#models/user") }) }),
    api: tokensGuard({ provider: tokensUserProvider({ model: () => import("#models/user"), tokens: "accessTokens" }) }),
  },
});
```

```typescript
// app/controllers/auth_controller.ts
export default class AuthController {
  async login({ request, auth, response }: HttpContext) {
    const { email, password } = request.only(["email", "password"]);
    const user = await User.verifyCredentials(email, password);
    await auth.use("web").login(user);
    return response.redirect("/dashboard");
  }

  async apiToken({ request, auth }: HttpContext) {
    const { email, password } = request.only(["email", "password"]);
    const user = await User.verifyCredentials(email, password);
    const token = await User.accessTokens.create(user);
    return { token: token.toJSON() };
  }
}
```

## Examples

### Example 1: Full CRUD web application

**User prompt:** "Build a blog with AdonisJS — posts CRUD, user auth, and server-rendered pages."

The agent will scaffold an AdonisJS web app with Lucid models (User, Post), authentication middleware, VineJS validation, and Edge templates for the views.

### Example 2: REST API with token auth

**User prompt:** "Create a REST API with AdonisJS, API token authentication, and pagination."

The agent will set up API routes, access token guard, JSON responses with pagination, and Japa tests.

## Guidelines

- **Use `node