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

@cjwddz/service-manager

v0.0.1

Published

A service management framework for Node.js applications with daemon support

Readme

@cjwddz/service-manager

一个支持守护进程的 Node.js 服务管理框架。

特性

  • 🚀 易于使用:只需实现 start() 方法
  • 🔄 生命周期钩子beforeStartafterStartbeforeStopbeforeRestartafterRestartonUpdateAvailable
  • 📊 自动状态检查:框架自动提供状态和健康检查
  • 🛠️ CLI 命令startstoprestartstatus
  • 🔒 进程管理:PID 文件管理、优雅关闭
  • 🔁 自动重启:可配置的自动重启,支持重启限制和退避策略
  • 🔄 自动更新检查:自动检查更新,支持自定义检查逻辑
  • 📝 日志管理:自动日志文件管理

安装

npm install @cjwddz/service-manager

快速开始

最小示例

// src/index.ts
import { createService } from '@cjwddz/service-manager';
import { Hono } from 'hono';
import { serve } from '@hono/node-server';

const app = new Hono();
app.get('/', (c) => c.json({ message: 'Hello' }));

// 只需调用 createService(),框架自动处理一切:
// - 守护进程模式检测和自动运行
// - CLI 命令注册
// - 所有管理逻辑
createService({
  name: 'my-service',
  start: async () => {
    return serve({
      fetch: app.fetch,
      port: 3000,
    });
  },
});
// bin/cli.ts
#!/usr/bin/env node
import '../src/index.js'; // 注册服务
import '@cjwddz/service-manager/cli'; // 注册 CLI 命令

使用生命周期钩子

// src/index.ts
import { createService, IService, UpdateInfo } from '@cjwddz/service-manager';
import { Hono } from 'hono';
import { serve } from '@hono/node-server';
import { initDatabase, closeDatabase } from './db';

class MyService implements IService {
  async start() {
    const app = new Hono();
    app.get('/', (c) => c.json({ message: 'Hello' }));

    return serve({
      fetch: app.fetch,
      port: 3000,
    });
  }

  hooks = {
    beforeStart: async () => {
      await initDatabase();
    },

    afterStart: async () => {
      await registerToRegistry();
    },

    beforeStop: async () => {
      await saveState();
      await closeDatabase();
    },

    beforeRestart: async () => {
      await backupData();
    },

    afterRestart: async () => {
      await verifyService();
    },

    // 更新检查钩子
    onUpdateAvailable: async (updateInfo: UpdateInfo) => {
      console.log(`Update available: ${updateInfo.currentVersion} → ${updateInfo.latestVersion}`);
      // 返回 true 表示执行自动更新,false 表示只通知
      return false; // 默认只通知,不自动更新
    },
  };
}

createService(new MyService(), {
  name: 'my-service',
  version: '1.0.0',
  // 自动重启配置
  autoRestart: {
    enabled: true,
    maxRestarts: 5, // 1 分钟内最多重启 5 次
    restartWindow: 60 * 1000, // 1 分钟时间窗口
    backoff: 'exponential', // 指数退避:1s, 2s, 4s, 8s...
  },
  // 自动更新检查配置
  updateCheck: {
    enabled: true,
    interval: 24 * 60 * 60 * 1000, // 每 24 小时检查一次
    autoUpdate: false, // 默认不自动更新,只通知
    // checkFunction: customUpdateCheck, // 可选:自定义检查函数
  },
});

CLI 使用

在 package.json 中配置 CLI

{
  "name": "my-service",
  "version": "1.0.0",
  "bin": {
    "my-service": "./bin/cli.js"
  }
}

创建 CLI 入口

// bin/cli.ts
#!/usr/bin/env node
// 1. 先导入服务代码(注册服务,框架会自动处理守护进程模式)
import '../src/index.js';
// 2. 然后导入 CLI(注册命令)
import '@cjwddz/service-manager/cli';

就是这么简单! 框架会自动:

  • ✅ 检测守护进程模式并自动运行服务
  • ✅ 注册 CLI 命令
  • ✅ 处理所有管理逻辑

用户无需手动处理守护进程模式检测和 CLI 注册!

使用 CLI 命令

# 启动服务
my-service start

# 停止服务
my-service stop

# 重启服务
my-service restart

# 查看状态
my-service status

API 参考

createService(service, config?)

创建服务管理器实例。

参数:

  • service: IService - 服务实现
  • config?: Partial<ServiceConfig> - 可选配置

返回: ServiceManager

IService 接口

interface IService {
  start(): Promise<void | Server>;
  hooks?: {
    beforeStart?: () => Promise<void> | void;
    afterStart?: () => Promise<void> | void;
    beforeStop?: () => Promise<void> | void;
    beforeRestart?: () => Promise<void> | void;
    afterRestart?: () => Promise<void> | void;
    onUpdateAvailable?: (updateInfo: UpdateInfo) => Promise<boolean> | boolean;
  };
}

ServiceConfig 接口

interface ServiceConfig {
  name: string;
  version?: string;
  cwd?: string;
  dataDir?: string;
  pidFile?: string;
  logFile?: string;
  startTimeout?: number;
  stopTimeout?: number;
  restartDelay?: number;
  autoRestart?: {
    enabled: boolean;
    maxRestarts?: number; // 最大重启次数(默认:5)
    restartWindow?: number; // 重启时间窗口(毫秒,默认:60000)
    restartDelay?: number; // 重启延迟(毫秒,默认:1000)
    backoff?: 'linear' | 'exponential'; // 退避策略(默认:exponential)
    baseDelay?: number; // 基础延迟(毫秒,默认:1000)
  };
  updateCheck?: {
    enabled: boolean; // 是否启用更新检查(默认:false)
    interval?: number; // 检查间隔(毫秒,默认:24小时)
    autoUpdate?: boolean; // 是否自动更新(默认:false)
    checkFunction?: () => Promise<UpdateInfo | null>; // 自定义检查函数
  };
  env?: Record<string, string>;
  stdout?: string | 'inherit' | 'ignore';
  stderr?: string | 'inherit' | 'ignore';
}

UpdateInfo 接口

interface UpdateInfo {
  currentVersion: string;
  latestVersion: string;
  packageName: string;
  updateAvailable: boolean;
  changelog?: string;
  [key: string]: any;
}

工作原理

  1. 框架控制管理逻辑:所有 start/stop/restart 逻辑都由框架处理
  2. 业务代码提供钩子:您的代码实现 start() 和可选的生命周期钩子
  3. 自动状态检查:框架自动检查进程状态、运行时间和健康状态
  4. 进程管理:框架管理 PID 文件、信号处理和优雅关闭
  5. 自动重启:如果启用,框架会自动重启失败的服务,支持重启限制和退避策略
  6. 更新检查:框架自动检查更新并通过钩子通知

自动重启保护机制

框架防止无限重启循环:

  • 重启限制:时间窗口内的最大重启次数(默认:1 分钟内最多 5 次)
  • 退避策略:重启之间的指数或线性延迟
  • 时间窗口:时间窗口过期后重启计数器重置

退避策略示例

指数退避(exponential)

  • 第 1 次重启:等待 1 秒
  • 第 2 次重启:等待 2 秒
  • 第 3 次重启:等待 4 秒
  • 第 4 次重启:等待 8 秒
  • 第 5 次重启:等待 16 秒

线性退避(linear)

  • 第 1 次重启:等待 1 秒
  • 第 2 次重启:等待 2 秒
  • 第 3 次重启:等待 3 秒
  • 第 4 次重启:等待 4 秒
  • 第 5 次重启:等待 5 秒

更新检查

框架可以自动检查更新:

  • 默认行为:检查 npm registry 中的包更新
  • 可自定义:您可以提供自定义的 checkFunction 来覆盖默认逻辑
  • 基于钩子:当有更新可用时,会调用 onUpdateAvailable 钩子
  • 自动更新:可选的自动更新(默认禁用以确保安全)

默认更新检查逻辑

  1. 读取 package.json 获取包名和当前版本
  2. 检查是否是 npm 包(排除本地包)
  3. 查询 npm registry 获取最新版本
  4. 比较版本号
  5. 如果有更新,调用 onUpdateAvailable 钩子

自定义更新检查

import { defaultUpdateCheck, UpdateInfo } from '@cjwddz/service-manager';

async function customUpdateCheck(): Promise<UpdateInfo | null> {
  // 使用默认检查
  const result = await defaultUpdateCheck();

  // 添加自定义逻辑
  if (result && result.updateAvailable) {
    // 从 GitHub API 获取 changelog
    const changelog = await fetchChangelog(result.latestVersion);
    return {
      ...result,
      changelog,
    };
  }

  return result;
}

createService(
  {
    start: async () => {
      /* ... */
    },
  },
  {
    updateCheck: {
      enabled: true,
      checkFunction: customUpdateCheck, // 使用自定义检查函数
    },
  }
);

许可证

MIT