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

feedback-hub-core

v0.1.4

Published

Framework-agnostic feedback records, ratings, tags, priority, impact scoring, trends, and follow-up workflows.

Readme

feedback-hub-core

Framework-agnostic TypeScript core for a reusable feedback platform. It provides the objective workflow shared by Sales, HR, Marketing, Inventory, Support, Product, and other teams.

Included capabilities

  • Feedback records with department/area and subject references
  • Ratings restricted to exactly 1, 2, 3, 4, or 5
  • Required text comments and optional voice URLs
  • Categories and deduplicated tags
  • Priority: low, normal, high, or urgent
  • Explainable 0–100 impact scoring
  • Search and filtering
  • Trend analytics grouped by month, category, priority, or status
  • Follow-up task creation and completion
  • In-memory store for development and tests
  • Storage interface that can later be backed by SQLite, PostgreSQL, or another database

AI is intentionally not required. Consumers can add optional sentiment, summarization, or topic-analysis adapters later without coupling the core package to an AI provider.

Install

npm install feedback-hub-core

Usage

import { FeedbackHubCore } from 'feedback-hub-core';
import { JsonFileStore } from 'feedback-hub-core/storage';

const hub = new FeedbackHubCore(new JsonFileStore('./data/feedback-hub.json'));
const feedback = hub.createFeedback({
  area: 'sales',
  subjectId: 'account-123',
  textComment: 'The onboarding process was confusing.',
  rating: 2,
  category: 'onboarding',
  tags: ['implementation', 'docs'],
  priority: 'high',
  impactFactors: { affectedPeople: 25, strategicImportance: 4 },
  source: 'customer-interview'
});

hub.createFollowUp({
  feedbackId: feedback.id,
  title: 'Schedule an onboarding review',
  ownerId: 'customer-success-1'
});

const trends = hub.trendReport({
  from: '2026-01-01',
  to: '2026-12-31',
  groupBy: 'category'
});

Feedback contract

textComment, rating, category, and area are required. rating accepts only the exact numeric values 1, 2, 3, 4, or 5; decimals, strings, zero, and values above 5 are rejected. voiceUrl is optional and should point to audio stored by the consuming application.

Impact scoring

The built-in score is deterministic and explainable. It considers rating, priority, affected people, revenue impact, and strategic importance, producing a score from 0 to 100. Consumers can store their own impact factors and replace the calculation in a higher-level application if needed.

Persistent storage

The built-in JsonFileStore persists feedback and follow-ups to a local JSON file and reloads them when the application restarts:

import { FeedbackHubCore } from 'feedback-hub-core';
import { JsonFileStore } from 'feedback-hub-core/storage';

const hub = new FeedbackHubCore(new JsonFileStore('./data/feedback-hub.json'));

It writes atomically through a temporary file and rename. For transactional SQLite persistence, use Node.js 24's built-in node:sqlite module with SqliteStore:

import { FeedbackHubCore } from 'feedback-hub-core';
import { SqliteStore } from 'feedback-hub-core/sqlite-storage';

const store = new SqliteStore('./data/feedback-hub.sqlite');
const hub = new FeedbackHubCore(store);
process.on('SIGTERM', () => store.close());

SqliteStore creates its schema automatically, enables WAL mode, enforces ratings from 1 to 5 at the database level, and persists writes in a transaction. It requires Node.js 24 or newer and does not require a native SQLite npm dependency or Visual Studio build tools. Multiple independently hosted API instances should use a server database adapter such as PostgreSQL.

REST API

The REST adapter is available as a separate entry point so applications that only need the core do not have to use HTTP:

import { createRestApi } from 'feedback-hub-core/rest';
import { ApiKeyManager } from 'feedback-hub-core/auth';

const apiKeys = new ApiKeyManager();
const created = apiKeys.create('local development', ['feedback:read', 'feedback:write', 'analytics:read', 'followups:write']);
console.log('Save this key once:', created.key);

createRestApi(undefined, { apiKeys, requireAuthentication: true }).listen(3000);

Clients send the key using either header:

Authorization: Bearer fh_...
X-API-Key: fh_...

Only the SHA-256 hash is stored by ApiKeyManager; the raw key is returned only when it is created. Revoke a key with apiKeys.revoke(keyId). In production, replace the in-memory manager with persistent, encrypted key metadata and never log raw keys.

Run the included server during development:

npm run build
npm start

The API exposes:

| Method | Endpoint | Purpose | | --- | --- | --- | | GET | /health | Service health check | | POST | /feedback | Create feedback | | GET | /feedback | List and filter feedback | | GET | /feedback/:id | Get one feedback record | | PATCH | /feedback/:id | Update category, tags, priority, status, or impact factors | | POST | /feedback/:id/follow-ups | Create a follow-up | | GET | /feedback/:id/follow-ups | List feedback follow-ups | | GET | /follow-ups | List all follow-ups | | PATCH | /follow-ups/:id/complete | Complete a follow-up | | GET | /analytics/trends | Generate trend analytics |

Example request:

curl -X POST http://localhost:3000/feedback \
  -H "Content-Type: application/json" \
  -d '{"area":"sales","rating":2,"category":"onboarding","tags":["docs"],"priority":"high","textComment":"The onboarding guide is confusing."}'

Feedback can be filtered with query parameters such as area, category, priority, status, tags, ratingAtMost, ratingAtLeast, createdFrom, and createdTo. Trend analytics requires from and to, with an optional groupBy=month|category|priority|status.

The current REST server uses the in-memory store. For production, inject a persistent store into createRestApi(hub) and add rate limiting, tenant isolation, and audit logging. API keys should be managed by a persistent key service; the in-memory ApiKeyManager is intended for development and tests.

Integrations

The core package does not depend on Slack, Notion, Android, an HTTP framework, or an AI provider. Expose it through a REST API, MCP server, Slack/Notion adapter, or Kotlin client as a separate integration layer.

Build and test

npm install
npm run build
npm test
npm run pack:check

Keep authentication, authorization, tenant isolation, audit logging, voice-file storage, and privacy policies in the application or API layer that consumes this package.