@cstar.help/js 0.3.4 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -4,7 +4,7 @@ Official TypeScript SDK for the [cStar](https://cstar.help) customer support pla
4
4
 
5
5
  - **Zero dependencies** — works with Node.js 18+ native `fetch`
6
6
  - **TypeScript-first** — full type definitions included
7
- - **Four entry points** — tree-shake what you don't need
7
+ - **Six entry points** — tree-shake what you don't need
8
8
  - **ESM + CJS** — works everywhere
9
9
 
10
10
  ## Install
@@ -13,18 +13,56 @@ Official TypeScript SDK for the [cStar](https://cstar.help) customer support pla
13
13
  npm install @cstar.help/js
14
14
  ```
15
15
 
16
- ## Quick Start
16
+ ---
17
17
 
18
- ### Server-side API Client
18
+ ## Which SDK Do I Need?
19
19
 
20
- Manage tickets, customers, articles, and webhooks with your secret API key.
20
+ cStar has one package with **six entry points**, each designed for a different context:
21
+
22
+ | Import | Use Case | Runs On | Auth Required | Key Type |
23
+ | -------------------------- | ----------------------------------------- | ----------------- | ------------- | -------------------- |
24
+ | `@cstar.help/js` | **Admin dashboard / backend integration** | Server only | Yes | Secret (`sk_*`) |
25
+ | `@cstar.help/js/chat` | Customer chat widget | Browser | Yes | Publishable (`pk_*`) |
26
+ | `@cstar.help/js/library` | Public knowledge base | Browser or server | No | None |
27
+ | `@cstar.help/js/community` | Public community forum | Browser or server | No | None |
28
+ | `@cstar.help/js/webhook` | Webhook signature verification | Server only | No | Signing secret |
29
+ | `@cstar.help/js/auth` | Authentication utilities | Server only | Yes | Secret (`sk_*`) |
30
+
31
+ ### The Security Model
32
+
33
+ cStar uses **two key types** to control access — the same pattern as Stripe and Supabase:
34
+
35
+ ```
36
+ Secret keys (sk_live_*, sk_test_*)
37
+ ├── Full CRUD on all resources
38
+ ├── Settings, billing, analytics, game system
39
+ ├── Team member management, audit log
40
+ ├── AI actions, automations, SLA rules
41
+ └── NEVER expose in client-side code
42
+
43
+ Publishable keys (pk_live_*, pk_test_*)
44
+ ├── Read-only on public data (tickets, customers, articles)
45
+ ├── Used by the chat widget for customer-facing features
46
+ ├── Safe to include in browser bundles
47
+ └── Cannot write, delete, or access sensitive endpoints
48
+ ```
49
+
50
+ > **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.
51
+
52
+ ---
53
+
54
+ ## Server-Side: Admin API Client
55
+
56
+ > **⚠️ 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.
57
+
58
+ Manage tickets, customers, articles, team members, settings, game system, and everything else.
21
59
 
22
60
  ```typescript
23
61
  import { CStarClient } from '@cstar.help/js';
24
62
 
25
63
  const cstar = new CStarClient({
26
- apiKey: 'sk_live_abc123...',
27
- teamId: 'tm_your_team_id'
64
+ apiKey: process.env.CSTAR_SECRET_KEY, // sk_live_... or sk_test_...
65
+ teamId: process.env.CSTAR_TEAM_ID
28
66
  });
29
67
 
30
68
  // List open tickets
@@ -36,18 +74,131 @@ const { data: ticket } = await cstar.tickets.create({
36
74
  customerId: 'cus_abc123'
37
75
  });
38
76
 
39
- // Get a customer with expanded fields
40
- const { data: customer } = await cstar.customers.get('cus_abc123');
41
-
42
77
  // Auto-paginate through all tickets
43
78
  for await (const ticket of cstar.tickets.listAutoPaginating({ status: 'open' })) {
44
79
  console.log(ticket.title);
45
80
  }
46
81
  ```
47
82
 
48
- ### Customer Chat (Widget SDK)
83
+ ### Full Resource Reference
84
+
85
+ **Core Resources** — Tickets, customers, and knowledge base.
49
86
 
50
- Build custom chat experiences with identity verification.
87
+ | Resource | Methods |
88
+ | ------------------------ | ----------------------------------------------------------------------------------------------- |
89
+ | `cstar.tickets` | `.list()` `.get(id)` `.create(params)` `.update(id, params)` `.del(id)` `.listAutoPaginating()` |
90
+ | `cstar.tickets.messages` | `.list(ticketId)` `.create(ticketId, params)` |
91
+ | `cstar.customers` | `.list()` `.get(id)` `.create(params)` `.update(id, params)` `.del(id)` `.listAutoPaginating()` |
92
+ | `cstar.articles` | `.list()` `.get(id)` `.create(params)` `.update(id, params)` `.del(id)` `.listAutoPaginating()` |
93
+ | `cstar.categories` | `.list()` `.get(id)` `.create(params)` `.update(id, params)` `.del(id)` |
94
+
95
+ **Team & Configuration** — Members, settings, and customization.
96
+
97
+ | Resource | Methods |
98
+ | ----------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
99
+ | `cstar.members` | `.list()` `.get(id)` `.update(id, params)` `.del(id)` |
100
+ | `cstar.members.invites` | `.list()` `.create(params)` `.del(id)` |
101
+ | `cstar.settings` | `.get()` `.update(params)` `.getBusinessHours()` `.updateBusinessHours(params)` `.getWidget()` `.updateWidget(params)` |
102
+ | `cstar.settings.statuses` | `.list()` `.create(params)` `.update(key, params)` `.del(key)` `.reorder(keys)` |
103
+ | `cstar.settings.quickReplies` | `.list()` `.create(params)` `.update(id, params)` `.del(id)` `.reorder(ids)` |
104
+ | `cstar.customFields` | `.list()` `.get(id)` `.create(params)` `.update(id, params)` `.del(id)` `.reorder(ids)` |
105
+ | `cstar.notifications` | `.list()` `.unreadCount()` `.markRead(id)` `.markAllRead()` |
106
+
107
+ **Operations** — Analytics, bulk actions, and data management.
108
+
109
+ | Resource | Methods |
110
+ | ---------------------- | --------------------------------------------------------------------------------------- |
111
+ | `cstar.analytics` | `.overview(params?)` `.agents(params?)` `.csatStats(params?)` `.csatResponses(params?)` |
112
+ | `cstar.sla` | `.list()` `.get(id)` `.create(params)` `.update(id, params)` `.del(id)` |
113
+ | `cstar.bulk` | `.update(params)` `.del(params)` |
114
+ | `cstar.export` | `.create(params)` |
115
+ | `cstar.import` | `.create(params)` `.logs(params?)` `.getLog(id)` |
116
+ | `cstar.search` | `.query(params)` |
117
+ | `cstar.tags` | `.list()` `.create(name)` `.del(name)` |
118
+ | `cstar.activity` | `.list(params?)` |
119
+ | `cstar.auditLog` | `.list(params?)` |
120
+ | `cstar.customerGroups` | `.list()` `.get(id)` `.create(params)` `.update(id, params)` `.del(id)` |
121
+
122
+ **Gamification** — The full game system.
123
+
124
+ | Resource | Methods |
125
+ | ------------------------- | --------------------------------------------------------------------------------------------------- |
126
+ | `cstar.game` | `.player(params?)` `.getPlayer(memberId)` `.leaderboard(params?)` `.myRank(params?)` |
127
+ | `cstar.game.boss` | `.current()` `.isActive()` `.spawn(params?)` `.damage(params)` `.defeats(params?)` `.getDefeat(id)` |
128
+ | `cstar.game.achievements` | `.list(params?)` `.unlocked(params)` `.get(id, params?)` |
129
+ | `cstar.game.quests` | `.today(params?)` `.history(params?)` |
130
+ | `cstar.game.puzzles` | `.today(params?)` `.complete(params)` `.streak(params)` `.leaderboard(params?)` |
131
+ | `cstar.game.oneUps` | `.list(params?)` `.send(params)` `.remaining(params)` |
132
+ | `cstar.game.highFives` | `.list(params?)` `.send(params)` `.canSend(teamId, params)` |
133
+ | `cstar.game.cosmetics` | `.list(params?)` `.getPreferences(params)` `.updatePreferences(params)` |
134
+ | `cstar.game.seasons` | `.list()` `.current()` `.stats(seasonId, params)` |
135
+ | `cstar.game.skills` | `.get(params)` `.allocate(params)` `.reset(params)` |
136
+
137
+ **Advanced** — AI, automations, views, billing, webhooks.
138
+
139
+ | Resource | Methods |
140
+ | ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
141
+ | `cstar.ai` | `.run(params)` `.autoTag(ticketId)` `.suggestReply(ticketId)` `.summarize(ticketId)` `.improve(text)` |
142
+ | `cstar.automations` | `.list()` `.get(id)` `.create(params)` `.update(id, params)` `.del(id)` `.toggle(id)` `.reorder(ids)` `.test(id, params)` `.executions(id)` `.allExecutions()` `.evaluate(params)` |
143
+ | `cstar.views` | `.list()` `.get(id)` `.create(params)` `.update(id, params)` `.del(id)` `.execute(id, params?)` |
144
+ | `cstar.billing` | `.subscription()` `.portal(params?)` |
145
+ | `cstar.webhooks` | `.list()` `.get(id)` `.create(params)` `.update(id, params)` `.del(id)` `.test(id)` |
146
+ | `cstar.community.posts` | `.list()` `.get(id)` `.create(params)` `.update(id, params)` `.del(id)` |
147
+ | `cstar.community.topics` | `.list()` `.get(id)` |
148
+ | `cstar.attachments` | `.list(params?)` `.get(id)` `.del(id)` |
149
+
150
+ ### Usage Examples
151
+
152
+ ```typescript
153
+ // Team analytics
154
+ const { data: overview } = await cstar.analytics.overview({ period: 'week' });
155
+ console.log(`${overview.tickets.open} open tickets this week`);
156
+
157
+ // SLA rules
158
+ const { data: rules } = await cstar.sla.list();
159
+
160
+ // Boss battle
161
+ const { data: boss } = await cstar.game.boss.current();
162
+ if (boss.active) {
163
+ console.log(`${boss.name} — ${boss.health}/${boss.maxHealth} HP`);
164
+ }
165
+
166
+ // AI-powered reply suggestion
167
+ const { data: suggestion } = await cstar.ai.suggestReply('tkt_abc123');
168
+
169
+ // Bulk close resolved tickets
170
+ await cstar.bulk.update({
171
+ resource: 'tickets',
172
+ ids: ['tkt_1', 'tkt_2', 'tkt_3'],
173
+ data: { status: 'closed' }
174
+ });
175
+
176
+ // Export data
177
+ const { data: exportResult } = await cstar.export.create({
178
+ resources: [{ type: 'tickets', filters: { status: 'closed' } }],
179
+ format: 'csv'
180
+ });
181
+
182
+ // Saved views
183
+ const { data: view } = await cstar.views.create({
184
+ name: 'Urgent Unresolved',
185
+ entityType: 'tickets',
186
+ filters: { priority: 'urgent', status: 'open' }
187
+ });
188
+ const { data: results } = await cstar.views.execute(view.id);
189
+
190
+ // Search across everything
191
+ const { data: searchResults } = await cstar.search.query({
192
+ query: 'billing issue',
193
+ types: ['tickets', 'customers']
194
+ });
195
+ ```
196
+
197
+ ---
198
+
199
+ ## Client-Side: Chat Widget SDK
200
+
201
+ Build custom chat experiences in the browser. Uses a publishable key — safe for frontend code.
51
202
 
52
203
  ```typescript
53
204
  import { ChatClient } from '@cstar.help/js/chat';
@@ -66,7 +217,7 @@ const { conversations } = await chat.conversations.list();
66
217
  // Send a message
67
218
  await chat.messages.send('tkt_abc123', 'Thanks for the help!');
68
219
 
69
- // Subscribe to new messages (polling)
220
+ // Subscribe to new messages
70
221
  const unsubscribe = chat.onMessage('tkt_abc123', (message) => {
71
222
  console.log(`${message.sender_name}: ${message.content}`);
72
223
  });
@@ -75,33 +226,48 @@ const unsubscribe = chat.onMessage('tkt_abc123', (message) => {
75
226
  chat.disconnect();
76
227
  ```
77
228
 
78
- ### Public Knowledge Base
229
+ ---
79
230
 
80
- Search and browse your public help center — no authentication required.
231
+ ## Client-Side: Public Knowledge Base
232
+
233
+ Search and browse your public help center — **no authentication required**.
81
234
 
82
235
  ```typescript
83
236
  import { LibraryClient } from '@cstar.help/js/library';
84
237
 
85
238
  const library = new LibraryClient({ teamSlug: 'acme' });
86
239
 
87
- // List categories
88
240
  const categories = await library.categories();
89
-
90
- // Search articles
91
241
  const results = await library.search('reset password');
92
-
93
- // Get a specific article
94
242
  const article = await library.article('how-to-reset-password');
95
243
  ```
96
244
 
97
- ### Webhook Verification
245
+ ---
246
+
247
+ ## Client-Side: Public Community
248
+
249
+ Browse your public community forum — **no authentication required**.
250
+
251
+ ```typescript
252
+ import { CommunityClient } from '@cstar.help/js/community';
253
+
254
+ const community = new CommunityClient({ teamSlug: 'acme' });
255
+
256
+ const topics = await community.topics();
257
+ const { posts } = await community.posts({ topicSlug: 'feature-requests', sort: 'votes' });
258
+ const { post, comments } = await community.post('dark-mode-support');
259
+ ```
260
+
261
+ ---
262
+
263
+ ## Server-Side: Webhook Verification
98
264
 
99
265
  Verify incoming webhook signatures on your server.
100
266
 
101
267
  ```typescript
102
268
  import { constructEvent } from '@cstar.help/js/webhook';
103
269
 
104
- // In your webhook handler (Express, Hono, etc.)
270
+ // In your webhook handler
105
271
  const event = constructEvent(rawBody, signature, 'whsec_your_secret');
106
272
 
107
273
  switch (event.type) {
@@ -114,31 +280,20 @@ switch (event.type) {
114
280
  }
115
281
  ```
116
282
 
117
- For edge environments (Cloudflare Workers, Deno), use the async variant:
283
+ For edge runtimes (Cloudflare Workers, Deno), use the async variant:
118
284
 
119
285
  ```typescript
120
286
  import { constructEventAsync } from '@cstar.help/js/webhook';
121
-
122
287
  const event = await constructEventAsync(rawBody, signature, secret);
123
288
  ```
124
289
 
125
- ## API Reference
126
-
127
- ### CStarClient
128
-
129
- | Resource | Methods |
130
- | ------------------------ | ----------------------------------------------------------------------------------------------- |
131
- | `cstar.tickets` | `.list()` `.get(id)` `.create(params)` `.update(id, params)` `.del(id)` `.listAutoPaginating()` |
132
- | `cstar.tickets.messages` | `.list(ticketId)` `.create(ticketId, params)` |
133
- | `cstar.customers` | `.list()` `.get(id)` `.create(params)` `.update(id, params)` `.del(id)` `.listAutoPaginating()` |
134
- | `cstar.articles` | `.list()` `.get(id)` `.create(params)` `.update(id, params)` `.del(id)` `.listAutoPaginating()` |
135
- | `cstar.webhooks` | `.list()` `.get(id)` `.create(params)` `.update(id, params)` `.del(id)` `.test(id)` |
290
+ ---
136
291
 
137
- ### Configuration
292
+ ## Configuration
138
293
 
139
294
  ```typescript
140
295
  const cstar = new CStarClient({
141
- apiKey: 'sk_live_...', // Required — secret or publishable key
296
+ apiKey: 'sk_live_...', // Required — must be a secret key (sk_*)
142
297
  teamId: 'tm_...', // Required — your team ID
143
298
  baseUrl: 'https://...', // Optional — defaults to https://www.cstar.help
144
299
  version: '2026-03-01', // Optional — API version header
@@ -147,26 +302,32 @@ const cstar = new CStarClient({
147
302
  });
148
303
  ```
149
304
 
150
- ### Test Mode
305
+ ## Test Mode
151
306
 
152
307
  Test mode is auto-detected from your API key prefix:
153
308
 
154
309
  ```typescript
155
- // Uses test data — no real customers affected
156
310
  const cstar = new CStarClient({
157
311
  apiKey: 'sk_test_abc123...',
158
312
  teamId: 'tm_your_team_id'
159
313
  });
160
314
 
161
315
  console.log(cstar.isTestMode); // true
316
+ // All operations use test data — no real customers affected
162
317
  ```
163
318
 
164
- ### Error Handling
319
+ ## Error Handling
165
320
 
166
321
  All API errors throw typed exceptions:
167
322
 
168
323
  ```typescript
169
- import { CStarError, CStarNotFoundError, CStarValidationError } from '@cstar.help/js';
324
+ import {
325
+ CStarError,
326
+ CStarAuthenticationError,
327
+ CStarRateLimitError,
328
+ CStarNotFoundError,
329
+ CStarValidationError
330
+ } from '@cstar.help/js';
170
331
 
171
332
  try {
172
333
  await cstar.tickets.get('tkt_nonexistent');
@@ -175,15 +336,19 @@ try {
175
336
  console.log('Ticket not found:', err.message);
176
337
  } else if (err instanceof CStarValidationError) {
177
338
  console.log('Invalid param:', err.param);
339
+ } else if (err instanceof CStarRateLimitError) {
340
+ console.log('Rate limited, retry after:', err.retryAfter, 'seconds');
341
+ } else if (err instanceof CStarAuthenticationError) {
342
+ console.log('Bad API key');
178
343
  } else if (err instanceof CStarError) {
179
344
  console.log('API error:', err.code, err.statusCode);
180
345
  }
181
346
  }
182
347
  ```
183
348
 
184
- ### Idempotency
349
+ ## Idempotency
185
350
 
186
- Safely retry create operations:
351
+ Safely retry create/update operations:
187
352
 
188
353
  ```typescript
189
354
  const { data: ticket } = await cstar.tickets.create(
@@ -0,0 +1,94 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/community/index.ts
21
+ var community_exports = {};
22
+ __export(community_exports, {
23
+ CommunityClient: () => CommunityClient
24
+ });
25
+ module.exports = __toCommonJS(community_exports);
26
+ var DEFAULT_BASE_URL = "https://www.cstar.help";
27
+ var CommunityClient = class {
28
+ constructor(config) {
29
+ this.baseUrl = (config.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
30
+ this.teamSlug = config.teamSlug;
31
+ }
32
+ /** List all public community topics. */
33
+ async topics() {
34
+ const response = await this.fetch(
35
+ `/api/community/${this.teamSlug}/topics`
36
+ );
37
+ return response.data;
38
+ }
39
+ /** List public posts, optionally filtered by topic, status, or sort order. */
40
+ async posts(params) {
41
+ const query = {};
42
+ if (params?.topicSlug) query.topicSlug = params.topicSlug;
43
+ if (params?.status) query.status = params.status;
44
+ if (params?.sort) query.sort = params.sort;
45
+ if (params?.limit) query.limit = String(params.limit);
46
+ if (params?.offset) query.offset = String(params.offset);
47
+ const response = await this.fetch(
48
+ `/api/community/${this.teamSlug}/posts`,
49
+ query
50
+ );
51
+ return { posts: response.data, count: response.count };
52
+ }
53
+ /** Get a single post by slug, including all comments. */
54
+ async post(slug) {
55
+ const response = await this.fetch(
56
+ `/api/community/${this.teamSlug}/posts/${slug}`
57
+ );
58
+ return response.data;
59
+ }
60
+ /**
61
+ * Full-text search across post titles and bodies.
62
+ * Returns matching posts with relevance ranking.
63
+ */
64
+ async search(query) {
65
+ return this.fetch(`/api/community/${this.teamSlug}/search`, {
66
+ q: query
67
+ });
68
+ }
69
+ async fetch(path, query) {
70
+ let url = `${this.baseUrl}${path}`;
71
+ if (query) {
72
+ const params = new URLSearchParams();
73
+ for (const [key, value] of Object.entries(query)) {
74
+ if (value !== void 0) params.set(key, value);
75
+ }
76
+ const qs = params.toString();
77
+ if (qs) url += `?${qs}`;
78
+ }
79
+ const response = await globalThis.fetch(url, {
80
+ method: "GET",
81
+ headers: { "Content-Type": "application/json" }
82
+ });
83
+ if (!response.ok) {
84
+ const errorBody = await response.json().catch(() => ({ error: { message: "Request failed" } }));
85
+ const message = typeof errorBody.error === "string" ? errorBody.error : errorBody.error?.message ?? `Community API error: ${response.status}`;
86
+ throw new Error(message);
87
+ }
88
+ return response.json();
89
+ }
90
+ };
91
+ // Annotate the CommonJS export names for ESM import in node:
92
+ 0 && (module.exports = {
93
+ CommunityClient
94
+ });
@@ -0,0 +1,115 @@
1
+ /** Configuration for the CommunityClient. */
2
+ interface CommunityConfig {
3
+ /** Team slug (e.g., 'acme'). Identifies the community to query. */
4
+ teamSlug: string;
5
+ /** Override the base URL (defaults to https://www.cstar.help). */
6
+ baseUrl?: string;
7
+ }
8
+ /** A discussion topic/category in the community. */
9
+ interface CommunityTopic {
10
+ id: string;
11
+ name: string;
12
+ slug: string;
13
+ description: string | null;
14
+ icon: string;
15
+ visibility: 'public' | 'members_only';
16
+ sort_order: number;
17
+ }
18
+ /** A public community post. */
19
+ interface CommunityPost {
20
+ id: string;
21
+ title: string;
22
+ slug: string;
23
+ body: string;
24
+ status: 'open' | 'answered' | 'officially_answered' | 'planned' | 'not_planned' | 'completed' | 'under_review';
25
+ visibility: 'public' | 'members_only';
26
+ voteCount: number;
27
+ commentCount: number;
28
+ isPinned: boolean;
29
+ isFeatured: boolean;
30
+ isLocked: boolean;
31
+ commentsEnabled: boolean;
32
+ topicName: string;
33
+ topicSlug: string;
34
+ authorName: string;
35
+ authorAvatar: string;
36
+ authorBio: string;
37
+ authorPostCount: number;
38
+ authorCommentCount: number;
39
+ isTeamMember: boolean;
40
+ lastActivityAt: string;
41
+ createdAt: string;
42
+ }
43
+ /** A comment on a community post. */
44
+ interface CommunityComment {
45
+ id: string;
46
+ body: string;
47
+ isOfficial: boolean;
48
+ voteScore: number;
49
+ parentCommentId: string | null;
50
+ authorName: string;
51
+ authorAvatar: string;
52
+ authorBio: string;
53
+ authorPostCount: number;
54
+ authorCommentCount: number;
55
+ isTeamMember: boolean;
56
+ createdAt: string;
57
+ }
58
+ /** Parameters for listing posts. */
59
+ interface CommunityPostListParams {
60
+ /** Filter by topic slug. */
61
+ topicSlug?: string;
62
+ /** Filter by status. */
63
+ status?: string;
64
+ /** Sort order (default: 'recent'). */
65
+ sort?: 'recent' | 'votes' | 'comments';
66
+ /** Max results per page. */
67
+ limit?: number;
68
+ /** Pagination offset. */
69
+ offset?: number;
70
+ }
71
+ /** Search results. */
72
+ interface CommunitySearchResult {
73
+ data: CommunityPost[];
74
+ count: number;
75
+ query: string;
76
+ }
77
+ /** A single post with its comments. */
78
+ interface CommunityPostDetail {
79
+ post: CommunityPost;
80
+ comments: CommunityComment[];
81
+ }
82
+
83
+ /**
84
+ * Public community client. No authentication required.
85
+ *
86
+ * ```typescript
87
+ * const community = new CommunityClient({ teamSlug: 'acme' });
88
+ * const topics = await community.topics();
89
+ * const posts = await community.posts({ topicSlug: 'feedback', sort: 'votes' });
90
+ * const post = await community.post('my-feature-request');
91
+ * const results = await community.search('dark mode');
92
+ * ```
93
+ */
94
+ declare class CommunityClient {
95
+ private readonly baseUrl;
96
+ private readonly teamSlug;
97
+ constructor(config: CommunityConfig);
98
+ /** List all public community topics. */
99
+ topics(): Promise<CommunityTopic[]>;
100
+ /** List public posts, optionally filtered by topic, status, or sort order. */
101
+ posts(params?: CommunityPostListParams): Promise<{
102
+ posts: CommunityPost[];
103
+ count: number;
104
+ }>;
105
+ /** Get a single post by slug, including all comments. */
106
+ post(slug: string): Promise<CommunityPostDetail>;
107
+ /**
108
+ * Full-text search across post titles and bodies.
109
+ * Returns matching posts with relevance ranking.
110
+ */
111
+ search(query: string): Promise<CommunitySearchResult>;
112
+ private fetch;
113
+ }
114
+
115
+ export { CommunityClient, type CommunityComment, type CommunityConfig, type CommunityPost, type CommunityPostDetail, type CommunityPostListParams, type CommunitySearchResult, type CommunityTopic };