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

vellio-nestjs

v0.1.0-rc.1

Published

Vellio Server SDK — NestJS implementation (vellio-nestjs)

Readme

vellio-nestjs

Vellio Server SDK — NestJS 实现。在你的业务服务中接入 JWT 门禁配额预检用量上报配置同步 四项核心能力。

当前版本 0.1.0-rc.1 处于 Release Candidate 阶段,API 形态已对齐 SERVER_SDK.md 设计规范,欢迎对接联调;正式 GA 前可能仍有小范围调整。


前置要求

| 依赖 | 版本 | 说明 | | ---------------- | ------------------------------ | ------------------------------------------------- | | Node.js | >=20 | NestJS 11 官方最低要求 | | NestJS | ^11.0.0 | DynamicModule 模式 | | Redis | >=6(建议 7.x) | 用于 JWKS / Entitlement 快照 / Reserve 锁 | | Control Plane | 由 Vellio 提供 controlPlaneUrl | 用于 M2M Token 换取、WS 配置同步、用量上报 | | TypeScript 配置 | emitDecoratorMetadata: true + experimentalDecorators: true | NestJS DI 必须 |

Peer dependencies(需在宿主项目自行安装):

pnpm add @nestjs/common @nestjs/core ioredis rxjs ws

安装

正式发布前以 tarball 方式分发:

# 由 Vellio 团队提供 vellio-nestjs-0.1.0-rc.1.tgz
pnpm add file:./vellio-nestjs-0.1.0-rc.1.tgz

快速开始

1. 注册模块

同步配置

// app.module.ts
import { Module } from '@nestjs/common';
import { VellioServerModule } from 'vellio-nestjs';

@Module({
  imports: [
    VellioServerModule.forRoot({
      controlPlaneUrl: process.env.VELLIO_CONTROL_PLANE_URL!,
      projectId: process.env.VELLIO_PROJECT_ID!,
      clientSecret: process.env.VELLIO_CLIENT_SECRET!,
      redis: process.env.REDIS_URL!, // 或 ioredis 配置对象
    }),
  ],
})
export class AppModule {}

异步配置(推荐,配合 @nestjs/config):

import { ConfigModule, ConfigService } from '@nestjs/config';

VellioServerModule.forRootAsync({
  imports: [ConfigModule],
  inject: [ConfigService],
  useFactory: (config: ConfigService) => ({
    controlPlaneUrl: config.getOrThrow('VELLIO_CONTROL_PLANE_URL'),
    projectId: config.getOrThrow('VELLIO_PROJECT_ID'),
    clientSecret: config.getOrThrow('VELLIO_CLIENT_SECRET'),
    redis: config.getOrThrow('REDIS_URL'),
    failOpen: false, // 高风险场景:Control Plane 断连时拒绝请求
  }),
});

VellioServerModule@Global() 模块,注册一次即可在全项目注入。

2. 在路由上挂载门禁(推荐用法)

@VellioGuard 自动完成 JWT 验签 → Reserve(预扣)→ Confirm(请求成功后异步上报)/ Rollback(请求失败时同步回滚)

import { Controller, Post, Body } from '@nestjs/common';
import {
  VellioGuard,
  VellioContext,
  type VellioRequestContext,
} from 'vellio-nestjs';

@Controller('ai')
export class AiController {
  @Post('generate')
  @VellioGuard({
    capability: 'ai.text.tokens',
    estimatedAmount: (req) => req.body.maxTokens, // 动态预估
  })
  async generate(
    @Body() dto: { maxTokens: number; prompt: string },
    @VellioContext() ctx: VellioRequestContext,
  ) {
    // ctx.customerId / ctx.projectId 已由 SDK 自动注入
    return { ok: true, customer: ctx.customerId };
  }
}

请求方需在 Authorization: Bearer <JWT> 头中携带 Vellio 签发的 Access Token。

3. 手动调用模式(gRPC、消息队列、后台任务)

不走 HTTP 路由的场景,直接注入 VellioServerSDKService

import { Injectable } from '@nestjs/common';
import { VellioServerSDKService } from 'vellio-nestjs';
import { uuidv7 } from 'uuidv7';

@Injectable()
export class BatchJobService {
  constructor(private readonly vellio: VellioServerSDKService) {}

  async processJob(customerId: string, tokensEstimate: number) {
    const usageEventId = uuidv7();

    const reservation = await this.vellio.reserve({
      customerId,
      capabilityId: 'ai.text.tokens',
      estimatedAmount: tokensEstimate,
      idempotencyKey: usageEventId,
    });

    if (reservation.blocked) {
      throw new Error('quota exceeded');
    }

    try {
      const actualTokens = await this.runActualWork();
      await this.vellio.confirm({ usageEventId, actualAmount: actualTokens });
    } catch (err) {
      await this.vellio.rollback({ usageEventId, reason: String(err) });
      throw err;
    }
  }
}

配置项参考

VellioServerOptions(来自 src/interfaces/vellio-server-options.interface.ts):

| 字段 | 类型 | 默认值 | 说明 | | -------------------- | ------------------------- | ------- | --------------------------------------------- | | controlPlaneUrl | string | — | 必填。Vellio Control Plane 的 URL | | projectId | string | — | 必填。Vellio 项目 ID | | clientSecret | string | — | 必填。M2M 客户端密钥 | | redis | RedisOptions \| string | — | 必填。Redis 连接字符串或 ioredis 选项 | | failOpen | boolean | true | Control Plane 断连时是否放行请求 | | reportBatchSize | number | 50 | 用量批量上报阈值 | | reportIntervalMs | number | 1000 | 用量批量上报时间间隔(ms) | | reportQueueMaxSize | number | 10000 | 内存上报队列上限 | | shutdownTimeoutMs | number | 5000 | Graceful shutdown 最大等待时间(ms) |

@VellioGuard 选项

| 字段 | 类型 | 默认 | 说明 | | --------------------- | ---------------------------------------------- | ----- | ----------------------------------------------------------------------- | | capability | string | — | 必填。要门禁的 capability ID(如 ai.text.tokens) | | estimatedAmount | number \| string \| (req) => number \| string | — | 预估用量;未传则使用 Capability 的 commercial_increment | | streamMode | boolean | false | SSE / WebSocket 业务流模式 | | streamFlushInterval | number | 500 | Streaming 模式下局部 Confirm 间隔(ms) |


生命周期事件

注入 VellioServerSDKService 后通过 .on() 订阅:

constructor(private readonly vellio: VellioServerSDKService) {
  this.vellio
    .on('ready', () => logger.log('Vellio SDK ready'))
    .on('degraded', () => logger.warn('Control Plane disconnected, running degraded'))
    .on('quotaExceeded', ({ customerId, capabilityId, remainingBalance }) => {
      logger.warn(`quota exceeded: ${customerId} / ${capabilityId} (${remainingBalance})`);
    })
    .on('reportFailed', ({ events, error }) => {
      logger.error(`usage report failed: ${events.length} events`, error);
    })
    .on('queuePressure', ({ queueSize, maxSize }) => {
      logger.warn(`report queue pressure: ${queueSize}/${maxSize}`);
    });
}

事件全集:ready · degraded · startupError · authError · customerReady · entitlementChanged · quotaExceeded · reportFailed · queuePressure · queueFull · capabilityDiscovery · shutdown


Graceful Shutdown

VellioServerModule 已实现 OnApplicationShutdown,无需额外接线。请确保宿主应用启用了 NestJS shutdown hooks:

const app = await NestFactory.create(AppModule);
app.enableShutdownHooks(); // 必须,否则 SIGTERM 时上报队列可能丢失
await app.listen(3000);

关闭流程:

  1. 等待进行中的 Reserve→Confirm/Rollback(最多 shutdownTimeoutMs
  2. Flush 内存中的上报队列
  3. 超时未 flush 的事件写入 /tmp/vellio-dlq-{timestamp}.json

已知限制

  • rollback() 必须同步调用,不得改为异步队列(设计约束 G-05)
  • usageEventId 由 SDK 在 reserve() 时生成;confirm() / rollback() 不重新生成,重试用同一个 ID
  • 所有金额相关的字段全程使用 Decimal.js禁止用 number 直接做余额计算
  • failOpen: true 时 Control Plane 断连会放行请求,不要在金融/计费强一致场景使用此默认值

反馈渠道

对接过程中遇到的问题、API 不便之处、设计建议,请联系 Vellio 团队。RC 阶段欢迎深度反馈。