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

@cstar.help/js

v0.10.3

Published

Official TypeScript SDK for the cStar customer support platform

Readme

@cstar.help/js

Official TypeScript SDK for the cStar customer support platform.

  • Zero dependencies — works with Node.js 18+ native fetch
  • TypeScript-first — full type definitions included
  • Six entry points — tree-shake what you don't need
  • ESM + CJS — works everywhere

Install

npm install @cstar.help/js

Which SDK Do I Need?

cStar has one package with six entry points, each designed for a different context:

| Import | Use Case | Runs On | Auth Required | Key Type | | -------------------------- | ----------------------------------------- | ----------------- | ------------- | -------------------- | | @cstar.help/js | Admin dashboard / backend integration | Server only | Yes | Secret (sk_*) | | @cstar.help/js/chat | Customer chat widget | Browser | Yes | Publishable (pk_*) | | @cstar.help/js/library | Public knowledge base | Browser or server | No | None | | @cstar.help/js/community | Public community forum | Browser or server | No | None | | @cstar.help/js/webhook | Webhook signature verification | Server only | No | Signing secret | | @cstar.help/js/auth | Authentication utilities | Server only | Yes | Secret (sk_*) |

The Security Model

cStar uses two key types to control access — the same pattern as Stripe and Supabase:

Secret keys (sk_live_*, sk_test_*)
├── Full CRUD on all resources
├── Settings, billing, analytics, game system
├── Team member management, audit log
├── AI actions, automations, SLA rules
└── NEVER expose in client-side code

Publishable keys (pk_live_*, pk_test_*)
├── Read-only on public data (tickets, customers, articles)
├── Used by the chat widget for customer-facing features
├── Safe to include in browser bundles
└── Cannot write, delete, or access sensitive endpoints

Rule of thumb: If you're building a custom support dashboard for your team, use CStarClient with a secret key on your backend. If you're adding chat to your website, use ChatClient with a publishable key in the browser.


Server-Side: Admin API Client

⚠️ Server-side only. CStarClient requires a secret key (sk_*) and must never be used in browser code. The SDK will warn you if it detects a browser environment.

Manage tickets, customers, articles, team members, settings, game system, and everything else.

import { CStarClient } from '@cstar.help/js';

const cstar = new CStarClient({
	apiKey: process.env.CSTAR_SECRET_KEY, // sk_live_... or sk_test_...
	teamId: process.env.CSTAR_TEAM_ID
});

// List open tickets
const { data: tickets } = await cstar.tickets.list({ status: 'open' });

// Create a ticket
const { data: ticket } = await cstar.tickets.create({
	title: 'Help with billing',
	customerId: 'cus_abc123'
});

// Auto-paginate through all tickets
for await (const ticket of cstar.tickets.listAutoPaginating({ status: 'open' })) {
	console.log(ticket.title);
}

Full Resource Reference

Core Resources — Tickets, customers, and knowledge base.

| Resource | Methods | | ------------------------ | ----------------------------------------------------------------------------------------------- | | cstar.tickets | .list() .get(id) .create(params) .update(id, params) .del(id) .listAutoPaginating() | | cstar.tickets.messages | .list(ticketId) .create(ticketId, params) | | cstar.customers | .list() .get(id) .create(params) .update(id, params) .del(id) .listAutoPaginating() | | cstar.articles | .list() .get(id) .create(params) .update(id, params) .del(id) .listAutoPaginating() | | cstar.categories | .list() .get(id) .create(params) .update(id, params) .del(id) |

Team & Configuration — Members, settings, and customization.

| Resource | Methods | | ----------------------------- | ---------------------------------------------------------------------------------------------------------------------- | | cstar.members | .list() .get(id) .update(id, params) .del(id) | | cstar.members.invites | .list() .create(params) .del(id) | | cstar.settings | .get() .update(params) .getBusinessHours() .updateBusinessHours(params) .getWidget() .updateWidget(params) | | cstar.settings.statuses | .list() .create(params) .update(key, params) .del(key) .reorder(keys) | | cstar.settings.quickReplies | .list() .create(params) .update(id, params) .del(id) .reorder(ids) | | cstar.customFields | .list() .get(id) .create(params) .update(id, params) .del(id) .reorder(ids) | | cstar.notifications | .list() .unreadCount() .markRead(id) .markAllRead() |

Operations — Analytics, bulk actions, and data management.

| Resource | Methods | | ---------------------- | --------------------------------------------------------------------------------------- | | cstar.analytics | .overview(params?) .agents(params?) .csatStats(params?) .csatResponses(params?) | | cstar.sla | .list() .get(id) .create(params) .update(id, params) .del(id) | | cstar.bulk | .update(params) .del(params) | | cstar.export | .create(params) | | cstar.import | .create(params) .logs(params?) .getLog(id) | | cstar.search | .query(params) | | cstar.tags | .list() .create(name) .del(name) | | cstar.activity | .list(params?) | | cstar.auditLog | .list(params?) | | cstar.customerGroups | .list() .get(id) .create(params) .update(id, params) .del(id) |

Gamification — The full game system.

| Resource | Methods | | ------------------------- | --------------------------------------------------------------------------------------------------- | | cstar.game | .player(params?) .getPlayer(memberId) .leaderboard(params?) .myRank(params?) | | cstar.game.boss | .current() .isActive() .spawn(params?) .damage(params) .defeats(params?) .getDefeat(id) | | cstar.game.achievements | .list(params?) .unlocked(params) .get(id, params?) | | cstar.game.quests | .today(params?) .history(params?) | | cstar.game.puzzles | .today(params?) .complete(params) .streak(params) .leaderboard(params?) | | cstar.game.oneUps | .list(params?) .send(params) .remaining(params) | | cstar.game.highFives | .list(params?) .send(params) .canSend(teamId, params) | | cstar.game.cosmetics | .list(params?) .getPreferences(params) .updatePreferences(params) | | cstar.game.seasons | .list() .current() .stats(seasonId, params) | | cstar.game.skills | .get(params) .allocate(params) .reset(params) |

Advanced — AI, automations, views, billing, webhooks.

| Resource | Methods | | ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | cstar.ai | .run(params) .autoTag(ticketId) .suggestReply(ticketId) .summarize(ticketId) .improve(text) | | cstar.automations | .list() .get(id) .create(params) .update(id, params) .del(id) .toggle(id) .reorder(ids) .test(id, params) .executions(id) .allExecutions() .evaluate(params) | | cstar.views | .list() .get(id) .create(params) .update(id, params) .del(id) .execute(id, params?) | | cstar.billing | .subscription() .portal(params?) | | cstar.webhooks | .list() .get(id) .create(params) .update(id, params) .del(id) .test(id) | | cstar.community.posts | .list() .get(id) .create(params) .update(id, params) .del(id) | | cstar.community.topics | .list() .get(id) | | cstar.attachments | .list(params?) .get(id) .del(id) |

Usage Examples

// Team analytics
const { data: overview } = await cstar.analytics.overview({ period: 'week' });
console.log(`${overview.tickets.open} open tickets this week`);

// SLA rules
const { data: rules } = await cstar.sla.list();

// Boss battle
const { data: boss } = await cstar.game.boss.current();
if (boss.active) {
	console.log(`${boss.name} — ${boss.health}/${boss.maxHealth} HP`);
}

// AI-powered reply suggestion
const { data: suggestion } = await cstar.ai.suggestReply('tkt_abc123');

// Bulk close resolved tickets
await cstar.bulk.update({
	resource: 'tickets',
	ids: ['tkt_1', 'tkt_2', 'tkt_3'],
	data: { status: 'closed' }
});

// Export data
const { data: exportResult } = await cstar.export.create({
	resources: [{ type: 'tickets', filters: { status: 'closed' } }],
	format: 'csv'
});

// Saved views
const { data: view } = await cstar.views.create({
	name: 'Urgent Unresolved',
	entityType: 'tickets',
	filters: { priority: 'urgent', status: 'open' }
});
const { data: results } = await cstar.views.execute(view.id);

// Search across everything
const { data: searchResults } = await cstar.search.query({
	query: 'billing issue',
	types: ['tickets', 'customers']
});

Client-Side: Chat Widget SDK

Build custom chat experiences in the browser. Uses a publishable key — safe for frontend code.

import { ChatClient } from '@cstar.help/js/chat';

const chat = new ChatClient({ teamSlug: 'acme' });

// Identify the customer (HMAC signature from your server)
await chat.identify(
	{ externalId: 'usr_123', email: '[email protected]', name: 'Jane', timestamp: Date.now() / 1000 },
	hmacSignature
);

// List conversations
const { conversations } = await chat.conversations.list();

// Send a message
await chat.messages.send('tkt_abc123', 'Thanks for the help!');

// Subscribe to new messages
const unsubscribe = chat.onMessage('tkt_abc123', (message) => {
	console.log(`${message.sender_name}: ${message.content}`);
});

// Clean up
chat.disconnect();

Client-Side: Public Knowledge Base

Search and browse your public help center — no authentication required.

import { LibraryClient } from '@cstar.help/js/library';

const library = new LibraryClient({ teamSlug: 'acme' });

const categories = await library.categories();
const results = await library.search('reset password');
const article = await library.article('how-to-reset-password');

Client-Side: Public Community

Browse your public community forum — no authentication required.

import { CommunityClient } from '@cstar.help/js/community';

const community = new CommunityClient({ teamSlug: 'acme' });

const topics = await community.topics();
const { posts } = await community.posts({ topicSlug: 'feature-requests', sort: 'votes' });
const { post, comments } = await community.post('dark-mode-support');

Server-Side: Webhook Verification

Verify incoming webhook signatures on your server.

import { constructEvent } from '@cstar.help/js/webhook';

// In your webhook handler
const event = constructEvent(rawBody, signature, 'whsec_your_secret');

switch (event.type) {
	case 'ticket.created':
		console.log('New ticket:', event.data.title);
		break;
	case 'customer.created':
		console.log('New customer:', event.data.email);
		break;
}

For edge runtimes (Cloudflare Workers, Deno), use the async variant:

import { constructEventAsync } from '@cstar.help/js/webhook';
const event = await constructEventAsync(rawBody, signature, secret);

Configuration

const cstar = new CStarClient({
	apiKey: 'sk_live_...', // Required — must be a secret key (sk_*)
	teamId: 'tm_...', // Required — your team ID
	baseUrl: 'https://...', // Optional — defaults to https://www.cstar.help
	version: '2026-03-01', // Optional — API version header
	maxRetries: 3, // Optional — retry attempts for 5xx/429
	timeout: 30000 // Optional — request timeout in ms
});

Test Mode

Test mode is auto-detected from your API key prefix:

const cstar = new CStarClient({
	apiKey: 'sk_test_abc123...',
	teamId: 'tm_your_team_id'
});

console.log(cstar.isTestMode); // true
// All operations use test data — no real customers affected

Error Handling

All API errors throw typed exceptions:

import {
	CStarError,
	CStarAuthenticationError,
	CStarRateLimitError,
	CStarNotFoundError,
	CStarValidationError
} from '@cstar.help/js';

try {
	await cstar.tickets.get('tkt_nonexistent');
} catch (err) {
	if (err instanceof CStarNotFoundError) {
		console.log('Ticket not found:', err.message);
	} else if (err instanceof CStarValidationError) {
		console.log('Invalid param:', err.param);
	} else if (err instanceof CStarRateLimitError) {
		console.log('Rate limited, retry after:', err.retryAfter, 'seconds');
	} else if (err instanceof CStarAuthenticationError) {
		console.log('Bad API key');
	} else if (err instanceof CStarError) {
		console.log('API error:', err.code, err.statusCode);
	}
}

Idempotency

Safely retry create/update operations:

const { data: ticket } = await cstar.tickets.create(
	{ title: 'Billing issue', customerId: 'cus_abc' },
	{ idempotencyKey: 'create-billing-issue-usr123' }
);

Requirements

  • Node.js 18+ (for native fetch and AbortSignal.timeout)
  • TypeScript 5.0+ (for type definitions)

License

MIT