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

@howuse/feedback-node

v0.5.0

Published

Pure Node.js SDK for user feedback and activation management (no Go/koffi dependencies)

Downloads

122

Readme

@howuse/feedback-node

纯 Node.js SDK for user feedback and activation management(无需 Go/koffi 依赖).

安装

npm install @howuse/feedback-node

或者使用本地路径安装:

npm install ./feedback-sdk-node

要求

  • Node.js >= 18.0.0(内置 fetch API)

快速开始

Node.js 示例

import { initFeedbackClient } from '@howuse/feedback-node';

async function main() {
  // 初始化客户端
  const client = await initFeedbackClient({
    baseUrl: 'http://localhost:8080',
    softwareId: 1,
    version: '1.0.0',
    machineCodePath: './machine-codes', // 机器码存放目录
  });

  // 检查是否可用
  if (!client.enabled) {
    console.warn('SDK is disabled, some features may not work');
    return;
  }

  // 提交反馈
  const feedbackResult = await client.feedback({
    content: 'This is a test feedback',
    email: '[email protected]', // 可选
  });
  console.log('Feedback result:', feedbackResult);

  // 激活软件(机器码会自动使用)
  const activateResult = await client.activate({
    code: 'your-activation-code',
  });
  console.log('Activation result:', activateResult);

  // 检查激活状态(机器码会自动使用)
  const checkResult = await client.check();
  if (checkResult.expired) {
    console.log('License expired:', checkResult.reason);
  } else {
    console.log('License valid until:', checkResult.expireAt);
  }
}

main().catch(console.error);

Electron 主进程示例

在 Electron 的 main.jsmain.ts 中:

import { app, BrowserWindow } from 'electron';
import { initFeedbackClient } from '@howuse/feedback-node';

let feedbackClient: any;

async function initApp() {
  // 初始化 SDK
  feedbackClient = await initFeedbackClient({
    baseUrl: 'http://localhost:8080',
    softwareId: 1,
    version: app.getVersion(),
  });

  // 根据 enabled 状态决定是否显示反馈入口
  if (feedbackClient.enabled) {
    // 可以设置全局菜单或窗口中的反馈按钮
  }
}

app.whenReady().then(() => {
  initApp();
  createWindow();
});

API 参考

initFeedbackClient(options: InitOptions): Promise<FeedbackClient>

初始化 Feedback 客户端。

参数:

  • options.baseUrl (string): 服务器基础 URL
  • options.softwareId (number): 软件 ID
  • options.version (string): 软件版本号
  • options.machineCodePath (string): 机器码存放目录路径
  • options.timeoutMs (number, 可选): 请求超时时间(毫秒),默认 30000

返回值:

返回一个 FeedbackClient 实例。即使初始化失败,也不会抛出异常,而是返回 enabled=false 的客户端。

FeedbackClient

属性

  • enabled: boolean - 指示 SDK 是否可用

方法

feedback(data: FeedbackPayload): Promise<FeedbackResult>

提交用户反馈。

参数:

  • data.content (string): 反馈内容(必填)
  • data.email (string, 可选): 邮箱地址

返回值:

{
  success: boolean;
  id?: number;
  error?: string;
}
activate(data: ActivationRequest): Promise<ActivationResult>

激活软件(机器码会自动从初始化时保存的位置读取)。

参数:

  • data.code (string): 激活码

返回值:

{
  success: boolean;
  expireAt?: string;
  error?: string;
}
check(): Promise<ActivationCheckResponse>

检查激活状态(机器码会自动从初始化时保存的位置读取)。

重要: 如果调用失败(网络错误或服务器返回非 2xx),SDK 会直接返回 expired: true,而不是抛出异常。这确保了在无法联系服务端时,默认按"授权已到期"处理。

参数:

无需参数(机器码会自动使用)

返回值:

{
  expired: boolean;
  activated?: boolean;
  expireAt?: string;
  reason?: string;
}

错误处理

SDK 采用"安全降级"策略:

  1. 初始化失败:不会抛出异常,而是返回 enabled=false 的客户端
  2. 方法调用:当 enabled=false 时,所有方法都会返回失败结果,而不是抛出异常
  3. 激活检查失败check 方法在失败时会返回 expired: true,确保在无法联系服务端时默认按"授权已到期"处理

实现说明

此 SDK 使用纯 Node.js 实现,无需 Go 语言或 koffi 依赖。所有功能(包括机器码生成、HTTP 请求等)都通过 Node.js 内置模块实现:

  • 机器码生成:基于系统用户名的 MD5 哈希 + UUID
  • HTTP 客户端:使用 Node.js 18+ 内置的 fetch API
  • 文件操作:使用 Node.js fs 模块

机器码

机器码会自动生成并保存在指定的 machineCodePath 目录中。机器码格式为 32 位字符串,由以下两部分组成:

  • 前 16 位:系统用户名的 MD5 哈希值前 16 位
  • 后 16 位:UUID 的后 16 位

如果目录中已存在机器码文件(32 位文件名的文件),SDK 会自动使用现有的机器码,确保同一台机器上的机器码保持一致。

类型定义

所有类型都可以从包中导入:

import type {
  InitOptions,
  FeedbackPayload,
  ActivationRequest,
  ActivationCheckRequest,
  // ... 其他类型
} from '@howuse/feedback-node';

许可证

MIT