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

@kitsuneislife/miau-index

v1.1.0

Published

A powerful TypeScript anime indexer that aggregates and unifies anime data from multiple sources including episodes, seasons, and torrents

Readme

🐱 Miau-Index

A powerful TypeScript anime indexer that aggregates and unifies anime data from multiple sources

npm version npm downloads TypeScript License: MIT Tests

📋 About

Miau-Index is a powerful TypeScript library designed to aggregate, unify, and normalize anime data from multiple external sources like MyAnimeList, AniList, Kitsu, and more. The project offers a robust and scalable architecture to manage complete anime information, including:

  • 📺 Basic information (title, type, status, episodes)
  • ⭐ Ratings and rankings from multiple sources
  • 📝 Synopses and descriptions
  • 🎭 Genres, themes, and demographics
  • 🎬 Detailed seasons and episodes
  • 👥 Characters, voice actors, and staff
  • 🏢 Studios and producers
  • 🔗 Anime relations (sequels, prequels, etc.)
  • 🧲 NEW: Torrent indexing from Nyaa.si (optional extension)

✨ Features

🌟 Priority: Open and Free Sources

  • Zero API Keys Required: Works perfectly without any configuration
  • AniList: Public and completely free GraphQL API
  • Kitsu: Public and completely free JSON:API
  • MyAnimeList: OPTIONAL - only if you have/want to use an API key
  • Automatic Preference: Prioritizes open sources by default

Core Features

  • Data Unification: Combines information from multiple APIs to create a complete and accurate record
  • Type-Safe: Fully typed with TypeScript for maximum safety
  • Extensible: Modular architecture allows easy addition of new providers
  • 🆕 Nyaa Extension: Optional torrent indexing with quality detection, metadata extraction, and smart filtering

Validation and Security

  • Zod Schemas: Robust runtime validation for all data models
  • Type Guards: Helper functions for type checking
  • Error Handling: Custom error classes for better error management
  • Input Sanitization: Protection against injection attacks

Performance

  • Cache Service: In-memory caching system with configurable TTL
  • Rate Limiting: Intelligent request rate control
  • Retry Logic: Automatic retry with exponential backoff
  • Timeout Configuration: Configurable request timeouts

Developer Experience

  • Logging: Configurable logging system with multiple levels
  • Helper Utilities: 15+ ready-to-use helper functions
  • Comprehensive Tests: 113+ automated tests (98.3% passing)
  • Full Documentation: Complete API documentation and guides
  • Metrics & Observability: Built-in metrics tracking for monitoring

🚀 Installation

npm install @kitsuneislife/miau-index

Optional: Nyaa Torrent Extension

npm install @kitsuneislife/miau-index @kitsuneislife/nyaa

📖 Basic Usage

import { MiauIndex, DataSource } from '@kitsuneislife/miau-index';

// Initialize the indexer
// Works WITHOUT API KEYS - uses open sources (AniList, Kitsu)
const miauIndex = new MiauIndex({
  // All settings are optional!
  malApiKey: 'your-mal-api-key', // OPTIONAL: only if you have MAL API key
  enabledProviders: {
    myAnimeList: true, // Ignored if no API key
    aniList: true,     // ✓ Open source - NO API key needed
    kitsu: true,       // ✓ Open source - NO API key needed
  },
  preferOpenSources: true, // Prioritize open sources (default: true)
  enableLogging: true,
});

// Fetch specific anime from AniList
const anime = await miauIndex.fetchAnime([
  { source: DataSource.ANILIST, id: '5114' }
]);

console.log(anime.title.romaji); // "Fullmetal Alchemist: Brotherhood"
console.log(anime.ratings); // Ratings with score and votes

// Search anime by title (searches all providers)
const results = await miauIndex.searchAnime('Cowboy Bebop', 10);

// Get seasonal anime
const winterAnime = await miauIndex.getSeasonalAnime(2024, 'winter');

// Search in local repository
const localResults = await miauIndex.searchLocal('Naruto', 5);

// Check provider health
const health = await miauIndex.checkProviders();
console.log(health); // { ANILIST: true, MYANIMELIST: true, ... }

// Repository statistics
const stats = await miauIndex.getStats();
console.log(stats.totalAnime); // Total stored anime

🆕 Nyaa Torrent Extension

import { MiauIndex } from '@kitsuneislife/miau-index';
import { TorrentQuality } from '@kitsuneislife/miau-index';

// Enable Nyaa extension
const miauIndex = new MiauIndex({
  enableNyaa: true, // Enable torrent indexing
  nyaaOptions: {
    autoIndex: true,
    minSeeders: 5,
    preferredQuality: TorrentQuality.FULL_HD_1080p,
    enableCache: true,
    cacheTTL: 3600000, // 1 hour
    timeout: 30000,
    maxRetries: 3,
  },
});

// Index torrents for an anime
const torrents = await miauIndex.indexTorrents(anime);
console.log(`Found ${torrents.length} torrents`);

// Get best torrent for an episode
const bestTorrent = await miauIndex.getBestTorrent(anime, 1);
console.log(bestTorrent.magnetLink);

// Search with filters
const filtered = await miauIndex.searchTorrents(anime, {
  quality: TorrentQuality.FULL_HD_1080p,
  minSeeders: 10,
});

// Get metrics
const metrics = miauIndex.getNyaaMetrics();
console.log(`Cache hit rate: ${metrics.cacheHitRate.toFixed(2)}%`);

🌸 Extensão Nyaa (OPCIONAL)

Miau-Index inclui uma extensão TOTALMENTE OPCIONAL para indexar torrents de anime do Nyaa.si. Esta extensão usa o pacote @kitsuneislife/nyaa para buscar e associar torrents aos animes.

Instalação da Extensão

npm install @kitsuneislife/nyaa

Características da Extensão Nyaa

  • 🔍 Indexação Automática: Busca torrents para animes e episódios
  • 📊 Metadata Completa: Extrai qualidade, codec, idiomas, release group
  • 🎯 Associação Inteligente: Liga torrents aos episódios corretos
  • 🌐 Multi-Idioma: Suporte para áudio e legendas em vários idiomas
  • 📦 Batches: Detecta e indexa torrents com múltiplos episódios
  • Filtros Avançados: Busca por qualidade, idioma, seeders, etc.
  • 📈 Estatísticas: Analytics detalhados sobre torrents

Uso da Extensão Nyaa

import { MiauIndex, DataSource } from '@kitsuneislife/miau-index';
import { TorrentQuality, TorrentLanguage } from '@kitsuneislife/miau-index';

// Habilitar extensão Nyaa
const miauIndex = new MiauIndex({
  enableNyaa: true, // ✓ ATIVA a extensão de torrents
  nyaaOptions: {
    autoIndex: true,
    minSeeders: 5,
    trustedOnly: false,
    preferredQuality: TorrentQuality.FULL_HD_1080p,
    preferredLanguages: [TorrentLanguage.JAPANESE, TorrentLanguage.ENGLISH],
  },
});

// Verificar se está habilitada
console.log(miauIndex.isNyaaEnabled); // true

// Buscar anime
const anime = await miauIndex.fetchAnime([
  { source: DataSource.ANILIST, id: '21' } // One Piece
]);

// 1. Indexar todos os torrents do anime
const torrents = await miauIndex.indexTorrents(anime);
console.log(`${torrents.length} torrents encontrados`);

// 2. Indexar torrents de episódio específico
const ep1Torrents = await miauIndex.indexEpisodeTorrents(anime, 1);

// 3. Buscar torrents com filtros
const filtered = await miauIndex.searchTorrents(anime, {
  quality: TorrentQuality.FULL_HD_1080p,
  subtitleLanguage: TorrentLanguage.ENGLISH,
  minSeeders: 10,
  episodeNumber: 1,
});

// 4. Obter melhor torrent para episódio
const best = await miauIndex.getBestTorrent(anime, 1);
console.log(best?.magnetLink);
console.log(best?.metadata.quality);
console.log(best?.metadata.releaseGroup);

// 5. Estatísticas de torrents
const stats = await miauIndex.getTorrentStats(anime.id);
console.log(`Total: ${stats.totalTorrents}`);
console.log(`Média de seeders: ${stats.averageSeeders}`);
console.log(`Por qualidade:`, stats.byQuality);
console.log(`Por idioma:`, stats.byLanguage);

// 6. Atualizar informações do torrent (seeders/leechers)
const updated = await miauIndex.refreshTorrent(best.id);

Tipos de Torrent

Qualidades

  • SD_480p: 480p
  • HD_720p: 720p
  • FULL_HD_1080p: 1080p (padrão)
  • UHD_2160p / UHD_4K: 4K/2160p
  • RAW: Raw (sem legendas)

Idiomas

  • JAPANESE: Japonês
  • ENGLISH: Inglês
  • PORTUGUESE_BR: Português (BR)
  • SPANISH: Espanhol
  • FRENCH: Francês
  • GERMAN: Alemão
  • ITALIAN: Italiano
  • RUSSIAN: Russo

🎬 Episode & Season Fetching

Miau-Index v1.1.0+ supports detailed episode and season fetching from multiple providers with automatic organization and torrent association.

Features

  • 📺 Complete Episode Metadata: Title, synopsis, duration, aired date, images
  • 📅 Auto Season Organization: Automatically organizes episodes into seasons (13-episode heuristic)
  • 🔗 Torrent Association: Links torrents to specific episodes
  • 🌐 Multi-Provider Fallback: Tries multiple providers for episode data
  • 🎯 Provider-Specific Data:
    • AniList: GraphQL with airing schedule and streaming metadata
    • Kitsu: Full REST API with detailed episode information
    • Jikan: Complete MAL episode data with filler/recap flags
    • MyAnimeList: Basic episode list from count

Usage

import { MiauIndex } from '@kitsuneislife/miau-index';

const miauIndex = new MiauIndex();

// Search for anime
const results = await miauIndex.searchAnime('Steins Gate');
const anime = results[0];

// Fetch episodes with metadata
const episodes = await miauIndex.getEpisodes(anime);
console.log(`Found ${episodes.length} episodes`);

// Display first episode info
const ep1 = episodes[0];
console.log(ep1.title);         // "Episode 1: Prologue of the Beginning and End"
console.log(ep1.synopsis);      // Episode description
console.log(ep1.duration);      // 24 minutes
console.log(ep1.aired);         // Date object
console.log(ep1.filler);        // false
console.log(ep1.recap);         // false

// Get anime with complete episode data
const completeData = await miauIndex.getAnimeWithEpisodes(anime.id);
console.log(completeData.anime);
console.log(completeData.episodes);
console.log(completeData.seasons); // Auto-organized seasons

// Seasons are automatically created
if (completeData.seasons) {
  completeData.seasons.forEach(season => {
    console.log(`Season ${season.seasonNumber}: ${season.episodes.length} episodes`);
  });
}

Episode-Torrent Integration

When using the Nyaa extension, episodes and torrents are automatically associated:

const miauIndex = new MiauIndex({
  enableNyaa: true,
});

// Search and index
const results = await miauIndex.searchAnime('Cowboy Bebop');
const anime = results[0];

// Index torrents (creates episodes automatically)
await miauIndex.indexTorrents(anime);

// Get complete data with torrents
const data = await miauIndex.getAnimeWithEpisodes(anime.id);

// Associate torrents with episodes
await miauIndex.associateTorrentsWithEpisodes(anime.id);

// Get best torrent for specific episode
const bestForEp1 = await miauIndex.getBestTorrent(anime, 1);
console.log(`Best torrent for episode 1: ${bestForEp1?.title}`);

Episode Model

interface Episode {
  id: string;                    // Unique ID
  animeId: string;              // Parent anime ID
  number: number;               // Episode number
  title?: string;               // Episode title
  synopsis?: string;            // Episode description
  duration?: number;            // Duration in minutes
  aired?: Date;                 // Air date
  images?: {                    // Episode thumbnail
    small?: string;
    medium?: string;
    large?: string;
    original?: string;
  };
  filler?: boolean;             // Is filler episode
  recap?: boolean;              // Is recap episode
  externalIds: ExternalId[];    // Provider IDs
  createdAt: Date;
  updatedAt: Date;
}

interface AnimeSeason {
  id: string;
  animeId: string;
  seasonNumber: number;
  title?: string;
  episodeCount: number;
  episodes?: string[];          // Episode IDs
  aired?: {
    start?: Date;
    end?: Date;
  };
  externalIds: ExternalId[];
  createdAt: Date;
  updatedAt: Date;
}

🌸 Jikan Provider (FREE MyAnimeList Data)

Miau-Index v1.1.0+ includes the Jikan provider - a free, no-API-key provider for MyAnimeList data powered by Jikan API.

Features

  • Zero Configuration: No API key required
  • 🌐 Complete MAL Data: Full anime information from MyAnimeList
  • 📺 Episode Support: Paginated episode fetching with filler/recap flags
  • 📅 Seasonal Anime: Browse anime by season and year
  • Rate Limiting: Respects Jikan's 60 requests/minute limit
  • 💾 24h Cache: Matches Jikan's caching strategy

Auto-Initialization

Jikan is automatically initialized by default:

const miauIndex = new MiauIndex(); // Jikan is ready to use!

// Search uses Jikan (among other providers)
const results = await miauIndex.searchAnime('Naruto');

// Fetch seasonal anime
const winter2023 = await miauIndex.getSeasonalAnime(2023, 'winter');

Priority System

  1. AniList (open source, no key required)
  2. Kitsu (open source, no key required)
  3. Jikan (unofficial MAL, no key required) ← NEW
  4. MyAnimeList (official, requires API key, overrides Jikan)
// Without MAL API key: Uses Jikan for MAL data
const miauIndex = new MiauIndex(); 

// With MAL API key: Uses official MAL API (overrides Jikan)
const miauIndexOfficial = new MiauIndex({
  malApiKey: 'your-mal-client-id',
});

Jikan-Specific Features

import { JikanProvider } from '@kitsuneislife/miau-index';

// Use Jikan directly
const jikan = new JikanProvider();

// Fetch anime by MAL ID
const anime = await jikan.fetchAnimeById('1'); // Cowboy Bebop

// Search anime
const results = await jikan.searchAnime('One Piece', 10);

// Get seasonal anime
const summer2023 = await jikan.getSeasonalAnime(2023, 'summer');

// Fetch episodes (with pagination)
const episodes = await jikan.fetchEpisodes('anime-id', '21'); // One Piece episodes

// Check availability
const available = await jikan.isAvailable(); // true

Rate Limiting & Caching

Jikan respects API limits and caches aggressively:

  • Rate Limit: 55 requests/minute (stays under 60/min limit)
  • Cache Duration: 24 hours (matches Jikan's server-side cache)
  • Retry Logic: 3 retries with 2-second delay
  • Timeout: 15 seconds per request

Example showing cache benefits:

const jikan = new JikanProvider();

// First call: Hits Jikan API (~200-500ms)
const anime1 = await jikan.fetchAnimeById('1');

// Second call: From cache (<1ms)
const anime2 = await jikan.fetchAnimeById('1');

console.log(anime1.id === anime2.id); // true
  • CHINESE: Chinês
  • KOREAN: Coreano
  • MULTI: Múltiplos idiomas

Tipos de Release

  • EPISODE: Episódio individual
  • BATCH: Lote de episódios
  • SEASON: Temporada completa
  • COMPLETE: Série completa
  • MOVIE: Filme
  • OVA: OVA
  • SPECIAL: Especial

Metadata Extraída

Cada torrent inclui metadata completa extraída do título:

  • ✅ Qualidade (480p, 720p, 1080p, 4K)
  • ✅ Codec (H.264, HEVC/H.265, AV1)
  • ✅ Idiomas de áudio (Dual Audio detectado)
  • ✅ Idiomas de legendas (Multi-sub detectado)
  • ✅ Release group
  • ✅ Tipo de release (episódio, batch, etc.)
  • ✅ Range de episódios (para batches)

Exemplo Completo

Veja o arquivo examples/nyaa-extension.ts para exemplos completos de uso.

npx ts-node examples/nyaa-extension.ts

⚙️ Configuração

Crie um arquivo .env baseado no .env.example:

# MyAnimeList API
MAL_CLIENT_ID=seu_client_id
MAL_CLIENT_SECRET=seu_client_secret

# AniList API
ANILIST_CLIENT_ID=seu_client_id
ANILIST_CLIENT_SECRET=seu_client_secret

# Kitsu API
KITSU_API_KEY=sua_api_key

# Configurações da aplicação
NODE_ENV=development
LOG_LEVEL=info
REPOSITORY_TYPE=memory
CACHE_ENABLED=true
CACHE_TTL=3600
RATE_LIMIT_ENABLED=true
RATE_LIMIT_RPM=60

🏗️ Arquitetura

Estrutura de Diretórios

src/
├── config/           # Configurações da aplicação
├── models/          # Modelos de dados (Anime, Episode, People)
├── providers/       # Provedores de dados externos (MAL, AniList, Kitsu)
├── repositories/    # Camada de persistência
├── services/        # Serviços de lógica de negócio
├── types/           # Definições de tipos TypeScript
├── utils/           # Utilitários (logger, errors)
├── example.ts       # Exemplo de uso
└── index.ts         # Ponto de entrada principal

Componentes Principais

Modelos

  • Anime: Modelo principal com todas as informações unificadas
  • Episode: Informações de episódios individuais
  • AnimeSeason: Agrupamento de episódios por temporada
  • Character: Personagens e dubladores
  • Studio: Informações de estúdios

Provedores

  • BaseAnimeProvider: Classe abstrata base para todos os provedores
  • MyAnimeListProvider: Integração completa com MyAnimeList
  • AniListProvider: Integração completa com AniList (GraphQL)
  • KitsuProvider: Integração completa com Kitsu

Serviços

  • AnimeUnificationService: Serviço principal que unifica dados de múltiplas fontes usando estratégias de consenso e prioridade

🔧 Desenvolvimento

Scripts Disponíveis

# Instalar dependências
npm install

# Compilar TypeScript
npm run build

# Executar exemplo
npm run dev

# Executar aplicação compilada
npm start

# Testes
npm test
npm run test:watch

# Linting
npm run lint
npm run lint:fix

# Formatação
npm run format
npm run format:check

Adicionar um Novo Provedor

  1. Crie uma nova classe que estende BaseAnimeProvider
  2. Implemente os métodos obrigatórios:
    • getSource(): Retorna o DataSource
    • fetchAnimeById(): Busca anime por ID externo
    • searchAnime(): Busca animes por query
    • getSeasonalAnime(): Busca animes de uma temporada
import { BaseAnimeProvider } from './BaseProvider';
import { DataSource } from '../types/common';

export class NovoProvider extends BaseAnimeProvider {
  constructor() {
    super('https://api.exemplo.com');
  }

  getSource(): DataSource {
    return DataSource.NOVO_PROVIDER;
  }

  async fetchAnimeById(externalId: string): Promise<Anime | null> {
    // Implementação
  }

  // ... outros métodos
}
  1. Registre o provedor no MiauIndex:
const novoProvider = new NovoProvider();
miauIndex.registerProvider(novoProvider);

📊 Tipos de Dados

AnimeType

  • TV
  • MOVIE
  • OVA
  • ONA
  • SPECIAL
  • MUSIC

AnimeStatus

  • AIRING
  • FINISHED
  • NOT_YET_AIRED
  • CANCELLED

DataSource

  • MYANIMELIST
  • ANILIST
  • KITSU
  • ANIDB
  • TMDB

🤝 Contributing

Contributions are welcome! Please read our Contributing Guide for details on our code of conduct and the process for submitting pull requests.

Quick Start for Contributors

  1. Fork the repository
  2. Clone your fork: git clone https://github.com/YOUR_USERNAME/miau-index.git
  3. Install dependencies: npm install
  4. Create a branch: git checkout -b feature/my-feature
  5. Make your changes and add tests
  6. Run tests: npm test
  7. Commit: git commit -m "feat: add my feature"
  8. Push: git push origin feature/my-feature
  9. Open a Pull Request

📝 License

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

🙏 Acknowledgments

📮 Support

🔗 Links


Made with ❤️ by kitsuneislife

🧪 Testes

npm test

Os testes estão configurados com Jest e incluem:

  • Testes unitários para modelos
  • Testes de integração para serviços
  • Testes de providers

🤝 Contribuindo

Contribuições são bem-vindas! Por favor:

  1. Faça um fork do projeto
  2. Crie uma branch para sua feature (git checkout -b feature/MinhaFeature)
  3. Commit suas mudanças (git commit -m 'Adiciona MinhaFeature')
  4. Push para a branch (git push origin feature/MinhaFeature)
  5. Abra um Pull Request

📝 Licença

Este projeto está sob a licença MIT. Veja o arquivo LICENSE para mais detalhes.

🙏 Agradecimentos

  • MyAnimeList
  • AniList
  • Kitsu
  • Comunidade de anime

📧 Contato

Para dúvidas ou sugestões, abra uma issue no GitHub.


Feito com ❤️ e TypeScript