> ## Documentation Index
> Fetch the complete documentation index at: https://sonamu.cartanova.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# stub

> Generate code stubs for rapid development

export const FileItem = ({name, description, children}) => {
  const isLeaf = !children;
  const getFileExtension = filename => {
    if (filename.endsWith('/')) return null;
    const match = filename.match(/\.([^.]+)$/);
    return match ? match[1].toUpperCase() : null;
  };
  const getExtensionStyle = ext => {
    const styles = {
      TS: {
        backgroundColor: '#3178c6',
        color: 'white'
      },
      TSX: {
        backgroundColor: '#3178c6',
        color: 'white'
      },
      JS: {
        backgroundColor: '#f7df1e',
        color: 'black'
      },
      JSX: {
        backgroundColor: '#f7df1e',
        color: 'black'
      },
      JSON: {
        backgroundColor: '#ffd700',
        color: 'black'
      },
      YML: {
        backgroundColor: '#cb171e',
        color: 'white'
      },
      YAML: {
        backgroundColor: '#cb171e',
        color: 'white'
      },
      SQL: {
        backgroundColor: '#e38c00',
        color: 'white'
      },
      SH: {
        backgroundColor: '#4eaa25',
        color: 'white'
      },
      MD: {
        backgroundColor: '#083fa1',
        color: 'white'
      },
      CSS: {
        backgroundColor: '#563d7c',
        color: 'white'
      },
      HTML: {
        backgroundColor: '#e34c26',
        color: 'white'
      },
      ENV: {
        backgroundColor: '#6c757d',
        color: 'white'
      }
    };
    return styles[ext] || ({
      backgroundColor: '#6c757d',
      color: 'white'
    });
  };
  const ext = getFileExtension(name);
  const extStyle = ext ? getExtensionStyle(ext) : null;
  return <div style={{
    marginLeft: '30px'
  }}>
      <div style={{
    display: 'flex',
    alignItems: 'center',
    gap: '4px'
  }}>
        <span style={{
    position: 'relative',
    display: 'inline-block'
  }}>
          <span className="file-icon">{isLeaf && !name.endsWith("/") ? "📄" : "📁"}</span>
          {ext && <span style={{
    position: 'absolute',
    bottom: '2px',
    right: '0px',
    fontSize: '5px',
    fontWeight: 'bold',
    padding: '1px',
    borderRadius: '2px',
    lineHeight: '1',
    minWidth: '8px',
    textAlign: 'center',
    ...extStyle
  }}>
              {ext}
            </span>}
        </span>
        <code>{name}</code>
        {description && <span className="description"> - {description}</span>}
      </div>
      {children}
    </div>;
};

export const FileTree = ({children}) => {
  return <div className="file-tree" style={{
    margin: '20px',
    marginLeft: '-30px'
  }}>{children}</div>;
};

The `pnpm stub` command auto-generates **code templates** to reduce repetitive work. You can quickly create Practice scripts or new Entities to speed up development.

## Commands

### practice - Generate Practice Script

Generate scripts for temporary experiments or data processing.

```bash theme={null}
pnpm stub practice <name>
```

**Example**:

```bash theme={null}
pnpm stub practice test-api

# Generated:
# src/practices/p1-test-api.ts
# Automatically opens in VS Code
# Run command copied to clipboard
```

**Generated file**:

```typescript title="src/practices/p1-test-api.ts" theme={null}
import { Sonamu } from "sonamu";

console.clear();
console.log("p1-test-api.ts");

Sonamu.runScript(async () => {
  // TODO
});
```

**Run**:

```bash theme={null}
# Paste from clipboard (Cmd+V)
pnpm node -r dotenv/config --enable-source-maps dist/practices/p1-test-api.js
```

### entity - Generate Entity

Create a new Entity. By default, **template cones** are automatically generated along with the Entity.

```bash theme={null}
pnpm stub entity <entityId> [options]
```

**Options**:

| Option       | Description                                                           | Example                               |
| ------------ | --------------------------------------------------------------------- | ------------------------------------- |
| (none)       | Generate Entity with template cones (default behavior)                | `pnpm stub entity Product`            |
| `--ai`       | Generate Entity with LLM-powered cones (`ANTHROPIC_API_KEY` required) | `pnpm stub entity Product --ai`       |
| `--no-cones` | Generate Entity only, skip cone generation                            | `pnpm stub entity Product --no-cones` |

**Examples**:

```bash theme={null}
# Default: Generate Entity with template cones
pnpm stub entity Product
# ✓ Entity 'Product' created with template cones
# 💡 Tip: Run 'pnpm sonamu cone gen Product' to improve with AI

# Generate with AI-powered cones
pnpm stub entity Product --ai
# ✓ Entity 'Product' created
# 🌟 Generating AI-powered cones...
# ✅ Done (1234 tokens)

# Generate Entity without cones
pnpm stub entity Product --no-cones
# ✓ Entity 'Product' created without cones
```

<Note>
  Template cones can be generated without `ANTHROPIC_API_KEY`. You can later upgrade them using the `cone gen` command with AI.
</Note>

**Generated file**:

```typescript title="src/entities/Product.entity.ts" theme={null}
import type { EntityType } from "sonamu";

export const ProductEntity = {
  properties: [
    {
      name: "id",
      type: "int",
      primaryKey: true,
      autoIncrement: true,
    },
    {
      name: "title",
      type: "string",
      length: 255,
    },
    {
      name: "created_at",
      type: "datetime",
      default: "CURRENT_TIMESTAMP",
    },
  ],
} satisfies EntityType;
```

## Practice Scripts

### Use Cases

Practice scripts are useful for these tasks:

| Purpose         | Description                  | Example                       |
| --------------- | ---------------------------- | ----------------------------- |
| API Testing     | Test external API calls      | `p1-test-payment-api.ts`      |
| Data Migration  | One-time data transformation | `p2-migrate-user-data.ts`     |
| Debugging       | Validate specific logic      | `p3-debug-cache-issue.ts`     |
| Data Generation | Create test data             | `p4-create-sample-posts.ts`   |
| Analysis        | Check data statistics        | `p5-analyze-user-activity.ts` |

### Automatic Numbering

Practice files are **automatically numbered**:

<FileTree>
  <FileItem name="src/practices/">
    <FileItem name="p1-first-practice.ts" />

    <FileItem name="p2-second-practice.ts" />

    <FileItem name="p3-third-practice.ts" description="Next is p4" />
  </FileItem>
</FileTree>

When you create a new practice, it automatically gets the highest number + 1.

### Practical Examples

#### 1. API Testing

```typescript title="src/practices/p1-test-payment-api.ts" theme={null}
import { Sonamu } from "sonamu";

console.clear();
console.log("p1-test-payment-api.ts");

Sonamu.runScript(async () => {
  const paymentService = new PaymentService();

  // Test payment attempt
  const result = await paymentService.charge({
    amount: 10000,
    orderId: "TEST-001",
  });

  console.log("Payment result:", result);
});
```

#### 2. Data Migration

```typescript title="src/practices/p2-migrate-user-data.ts" theme={null}
import { Sonamu } from "sonamu";
import { UserModel } from "../models/User.model";

console.clear();
console.log("p2-migrate-user-data.ts");

Sonamu.runScript(async () => {
  // Get all users
  const users = await UserModel.findAll();

  for (const user of users) {
    // Migrate legacy field to new field
    await UserModel.update(user.id, {
      new_field: transformData(user.legacy_field),
    });

    console.log(`✓ Migrated user ${user.id}`);
  }

  console.log(`\n✓ Total: ${users.length} users migrated`);
});
```

#### 3. Batch Jobs

```typescript title="src/practices/p3-send-welcome-emails.ts" theme={null}
import { Sonamu } from "sonamu";
import { UserModel } from "../models/User.model";

console.clear();
console.log("p3-send-welcome-emails.ts");

Sonamu.runScript(async () => {
  // New users
  const newUsers = await UserModel.findMany({
    where: { welcome_email_sent: false },
  });

  console.log(`Sending welcome emails to ${newUsers.length} users...`);

  for (const user of newUsers) {
    try {
      await sendWelcomeEmail(user.email);
      await UserModel.update(user.id, {
        welcome_email_sent: true,
      });
      console.log(`✓ Sent to ${user.email}`);
    } catch (error) {
      console.error(`✗ Failed to send to ${user.email}:`, error);
    }
  }
});
```

## Entity Generation

### Basic Structure

Entities generated with `stub entity` include basic fields:

```typescript theme={null}
export const ProductEntity = {
  properties: [
    { name: "id", type: "int", primaryKey: true, autoIncrement: true },
    { name: "title", type: "string", length: 255 },
    { name: "created_at", type: "datetime", default: "CURRENT_TIMESTAMP" },
  ],
} satisfies EntityType;
```

### Customization

Add needed fields after generation:

```typescript theme={null}
export const ProductEntity = {
  properties: [
    // Basic fields
    { name: "id", type: "int", primaryKey: true, autoIncrement: true },
    { name: "title", type: "string", length: 255 },

    // Additional fields
    { name: "description", type: "text", nullable: true },
    { name: "price", type: "decimal", precision: 10, scale: 2 },
    { name: "stock", type: "int", default: 0 },
    { name: "category_id", type: "int" },

    // Timestamps
    { name: "created_at", type: "datetime", default: "CURRENT_TIMESTAMP" },
    { name: "updated_at", type: "datetime", onUpdate: "CURRENT_TIMESTAMP" },
  ],

  indexes: [
    { fields: ["category_id"] },
    { fields: ["title"], type: "fulltext" },
  ],

  belongsTo: [
    { entityId: "Category", as: "category" },
  ],
} satisfies EntityType;
```

## Development Workflow

### 1. Validate Ideas

```bash theme={null}
# Quickly create practice
pnpm stub practice test-idea

# Write code and run
pnpm node -r dotenv/config --enable-source-maps dist/practices/p1-test-idea.js

# Delete or keep after verification
```

### 2. Add Entity

```bash theme={null}
# Generate Entity
pnpm stub entity Order

# Write Entity definition
# src/entities/Order.entity.ts

# Create and apply migration
pnpm migrate run

# Scaffold Model
pnpm scaffold model Order
```

### 3. Data Operations

```bash theme={null}
# Generate Practice script
pnpm stub practice import-orders

# Write data processing logic
# src/practices/p1-import-orders.ts

# Run
pnpm node -r dotenv/config --enable-source-maps dist/practices/p1-import-orders.js
```

## Practical Tips

### 1. Reuse Practice Scripts

```typescript theme={null}
// ✅ Make functions reusable
async function processUsers(filter: any) {
  const users = await UserModel.findMany({ where: filter });
  // Processing logic...
}

Sonamu.runScript(async () => {
  // Reuse with various filters
  await processUsers({ role: "admin" });
  await processUsers({ role: "user" });
});
```

### 2. Error Handling

```typescript theme={null}
Sonamu.runScript(async () => {
  try {
    await riskyOperation();
  } catch (error) {
    console.error("Error occurred:", error);
    process.exit(1);  // Exit on failure
  }
});
```

### 3. Progress Display

```typescript theme={null}
Sonamu.runScript(async () => {
  const users = await UserModel.findAll();

  for (let i = 0; i < users.length; i++) {
    await processUser(users[i]);

    // Show progress
    const progress = Math.round(((i + 1) / users.length) * 100);
    console.log(`Progress: ${progress}% (${i + 1}/${users.length})`);
  }
});
```

### 4. Cleanup Practices

```bash theme={null}
# Delete completed practices
rm src/practices/p1-old-practice.ts

# Or move to archive directory
mkdir src/practices/archived
mv src/practices/p1-*.ts src/practices/archived/
```

## Cautions

<Warning>
  **Cautions when using Practice scripts**:

  1. **Production data**: Practice uses real DB. Be careful!
  2. **Backup**: Always backup before important data operations.
  3. **Transactions**: Use transactions when modifying data.
  4. **Testing**: Test in development environment before production run.
</Warning>

## Next Steps

<CardGroup cols={2}>
  <Card title="scaffold" icon="wand-magic-sparkles" href="/en/tools-and-cli/sonamu-cli/scaffold">
    Auto-generate Models with code scaffolding
  </Card>

  <Card title="Entity" icon="cube" href="/en/core-concepts/entity">
    Learn more about Entity definitions
  </Card>
</CardGroup>
