Skip to content

Mangaka-bot/spindle

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

19 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Spindle

A lightweight, singleton-based CLI multi-spinner library for Node.js. Run multiple spinners simultaneously without visual corruption, with automatic console interception.

Node.js Downloads npm Types

Installation · Quick Start · API


✨ Features

  • 🔄 Multiple Concurrent Spinners - Run as many spinners as you need
  • 🎨 Customizable Colors - 17 color options for spinner customization
  • 📝 Console Interception - console.log and friends work seamlessly without breaking spinners
  • Final States - Complete spinners with success, failure, warning, or info icons
  • 🧹 Automatic Cleanup - Graceful handling of process exit, SIGINT, and SIGTERM
  • 📦 Singleton Architecture - Centralized render management for flicker-free output

Installation

npm install @shoru/spindle

📦 Installation

npm install @shoru/spindle

Requires Node.js 18+


Quick Start

import { spindle } from '@shoru/spindle';

const spinner = spindle('Loading...').start();

// Do some async work
await someAsyncTask();

spinner.succeed('Done!');

API

Creating a Spindle

import { spindle, Spindle } from '@shoru/spindle';

// Using factory function (recommended)
const spinner = spindle('Initial text');

// Using constructor
const spinner = new Spindle('Initial text');

Methods

.start(text?)

Starts the spinner. Optionally updates the text.

spinner.start();
spinner.start('New loading message...');

.stop()

Stops the spinner without displaying a final message.

spinner.stop();

.succeed(text?)

Stops with a green checkmark (✔).

spinner.succeed('Task completed successfully');

.fail(text?)

Stops with a red cross (✖).

spinner.fail('Task failed');

.warn(text?)

Stops with a yellow warning sign (⚠).

spinner.warn('Task completed with warnings');

.info(text?)

Stops with a blue info icon (ℹ).

spinner.info('Additional information');

Properties

.text / .title

Get or set the spinner text. Both properties are interchangeable.

spinner.text = 'Downloading files...';
console.log(spinner.text); // 'Downloading files...'

.color

Get or set the spinner color.

spinner.color = 'magenta';

.isSpinning

Check if the spinner is currently active.

if (spinner.isSpinning) {
  spinner.succeed('Finished');
}

Available Colors

Standard Bright
black gray/grey
red redBright
green greenBright
yellow yellowBright
blue blueBright
magenta magentaBright
cyan cyanBright
white whiteBright

Default: cyan

RendererManager

The RendererManager singleton coordinates all active spinners. You typically don't need to interact with it directly, but it's available for advanced use cases.

import { RendererManager } from '@shoru/spindle';

// Check if any spinners are active
if (RendererManager.isActive()) {
  console.log('Spinners are running');
}

// Get count of active spinners
const count = RendererManager.getActiveCount();

// Force reset all spinners (use with caution)
RendererManager.reset(true);

TypeScript Support

Full TypeScript support with exported types:

import { 
  Spindle, 
  spindle, 
  SpinnerColor, 
  FinalState, 
  TaskState,
  Renderable 
} from '@shoru/spindle';

const color: SpinnerColor = 'cyan';
const state: FinalState = 'completed';

How It Works

  1. Singleton Renderer: A single RendererManager coordinates all spinner instances
  2. Console Interception: When spinners are active, console methods are intercepted and buffered
  3. Unified Rendering: All spinners render to a single output using log-update
  4. Clean Output: Buffered logs are flushed above the spinner display
  5. Graceful Cleanup: Process signals trigger proper cleanup to restore console state

🤝 Contributing

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

  1. Fork the repository
  2. Create feature branch git checkout -b feature/amazing-feature
  3. Commit changes git commit -m 'Add amazing feature'
  4. Push git push origin feature/amazing-feature
  5. Open Pull Request

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


Made with ❤️ for the Node.js CLI community

⬆ Back to Top