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

@nietzsci/clavis

v0.1.0

Published

Clavis 软件授权 SDK — 离线验证 + HMAC 签名 + 设备指纹

Downloads

13

Readme

@clavis/sdk

Clavis 软件授权 SDK — 离线验证 + HMAC 签名 + 设备指纹

安装

npm install @clavis/sdk

快速开始

import { Clavis } from "@clavis/sdk";

// 初始化
const clavis = new Clavis({
  appId: "nc1a2b3c4d5e6f7g8h",       // 从 Clavis 管理后台获取
  appSecret: "your-app-secret",        // 从 Clavis 管理后台获取
  publicKey: "your-ed25519-public-key", // 从 Clavis 管理后台获取
});

// 获取机器码
const machineCode = Clavis.getMachineCode();

// 激活
const result = await clavis.activate("XXXXX-XXXXX-XXXXX-XXXXX-XXXXX", machineCode);

// 离线验证(零网络请求)
const status = clavis.verifyOffline(machineCode);
console.log(status.valid, status.tier, status.features);

// 销毁
clavis.destroy();

API

new Clavis(config)

| 参数 | 类型 | 必填 | 默认值 | 说明 | |------|------|------|--------|------| | appId | string | 是 | - | 应用 ID | | appSecret | string | 是 | - | 应用密钥 | | publicKey | string | 是 | - | Ed25519 公钥 (base64) | | baseUrl | string | 否 | https://c.nietzsci.com | API 地址 | | storagePath | string | 否 | process.cwd() | 缓存路径 | | offlineGraceDays | number | 否 | 7 | 离线宽限天数 | | heartbeatInterval | number | 否 | 3600 | 心跳间隔(秒) | | autoHeartbeat | boolean | 否 | true | 自动心跳 |

激活

const result = await clavis.activate(licenseKey, identity);
// result: { success, tier, features, expiresAt, offlineToken }

离线验证

const status = clavis.verifyOffline(identity);
// status: { valid, tier, features, expiresAt, daysRemaining, isOffline, isTrial, inGracePeriod }

混合验证(优先离线)

const status = await clavis.checkLicense(identity);

功能检查

if (clavis.hasFeature("dark_mode")) {
  // 启用深色模式
}

事件监听

// 状态变化
const unsub = clavis.onStatusChange((status) => {
  console.log("授权状态:", status);
});

// 到期提醒
clavis.onExpiring(7, () => {
  console.log("即将到期!");
});

解绑

await clavis.deactivate(licenseKey, identity);

支付

const plans = await clavis.getPricingPlans();
const url = clavis.getPaymentUrl(planId, identity);

工具函数

import { getMachineCode, getDeviceInfo, verifyOfflineToken, hashIdentity } from "@clavis/sdk";

// 设备指纹
const code = getMachineCode();        // MC-XXXX-XXXX-XXXX-XXXX
const info = getDeviceInfo();         // { os, osVersion, hostname, ... }

// 离线验签
const payload = verifyOfflineToken(token, publicKey);

// identity 哈希
const hash = hashIdentity(identity, appSecret);

安全说明

  • appSecret 不要暴露在前端代码中,仅在 Node.js 服务端使用
  • 浏览器端只能做离线验证(公钥验签),激活/心跳/解绑需通过后端代理
  • 本地缓存使用 AES-256-GCM 加密,防止直接读取 token