@cstar.help/js 0.3.4 → 0.4.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
+ - **Five entry points** — tree-shake what you don't need
8
8
  - **ESM + CJS** — works everywhere
9
9
 
10
10
  ## Install
@@ -94,6 +94,61 @@ const results = await library.search('reset password');
94
94
  const article = await library.article('how-to-reset-password');
95
95
  ```
96
96
 
97
+ ### Public Community
98
+
99
+ Browse and search your public community forum — no authentication required.
100
+
101
+ ```typescript
102
+ import { CommunityClient } from '@cstar.help/js/community';
103
+
104
+ const community = new CommunityClient({ teamSlug: 'acme' });
105
+
106
+ // List discussion topics
107
+ const topics = await community.topics();
108
+
109
+ // List posts (with filters)
110
+ const { posts, count } = await community.posts({
111
+ topicSlug: 'feature-requests',
112
+ sort: 'votes'
113
+ });
114
+
115
+ // Get a single post with all comments
116
+ const { post, comments } = await community.post('dark-mode-support');
117
+
118
+ // Search posts
119
+ const results = await community.search('billing');
120
+ ```
121
+
122
+ ### Server-side Community (Admin)
123
+
124
+ Manage community posts with your secret API key via `CStarClient`:
125
+
126
+ ```typescript
127
+ const cstar = new CStarClient({ apiKey: 'sk_live_...', teamId: 'tm_...' });
128
+
129
+ // List all posts (including hidden/unapproved)
130
+ const { data: posts } = await cstar.community.posts.list({ status: 'open' });
131
+
132
+ // Create a post
133
+ const { data: post } = await cstar.community.posts.create({
134
+ title: 'New Feature: Dark Mode',
135
+ body: 'We just shipped dark mode!',
136
+ topicId: 'topic_abc123'
137
+ });
138
+
139
+ // Toggle vote on a post
140
+ const { voted, voteCount } = await cstar.community.posts.vote('post_id');
141
+
142
+ // Add a comment
143
+ const comment = await cstar.community.posts.createComment('post_id', {
144
+ body: 'Great idea!',
145
+ isOfficial: true
146
+ });
147
+
148
+ // List topics
149
+ const { data: topics } = await cstar.community.topics.list();
150
+ ```
151
+
97
152
  ### Webhook Verification
98
153
 
99
154
  Verify incoming webhook signatures on your server.
@@ -126,13 +181,15 @@ const event = await constructEventAsync(rawBody, signature, secret);
126
181
 
127
182
  ### CStarClient
128
183
 
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)` |
184
+ | Resource | Methods |
185
+ | ------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------- |
186
+ | `cstar.tickets` | `.list()` `.get(id)` `.create(params)` `.update(id, params)` `.del(id)` `.listAutoPaginating()` |
187
+ | `cstar.tickets.messages` | `.list(ticketId)` `.create(ticketId, params)` |
188
+ | `cstar.customers` | `.list()` `.get(id)` `.create(params)` `.update(id, params)` `.del(id)` `.listAutoPaginating()` |
189
+ | `cstar.articles` | `.list()` `.get(id)` `.create(params)` `.update(id, params)` `.del(id)` `.listAutoPaginating()` |
190
+ | `cstar.webhooks` | `.list()` `.get(id)` `.create(params)` `.update(id, params)` `.del(id)` `.test(id)` |
191
+ | `cstar.community.posts` | `.list()` `.get(id)` `.create(params)` `.update(id, params)` `.del(id)` `.vote(id)` `.follow(id)` `.listComments(id)` `.createComment(id, params)` |
192
+ | `cstar.community.topics` | `.list()` `.get(id)` |
136
193
 
137
194
  ### Configuration
138
195
 
@@ -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 };
@@ -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 };
@@ -0,0 +1,69 @@
1
+ // src/community/index.ts
2
+ var DEFAULT_BASE_URL = "https://www.cstar.help";
3
+ var CommunityClient = class {
4
+ constructor(config) {
5
+ this.baseUrl = (config.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
6
+ this.teamSlug = config.teamSlug;
7
+ }
8
+ /** List all public community topics. */
9
+ async topics() {
10
+ const response = await this.fetch(
11
+ `/api/community/${this.teamSlug}/topics`
12
+ );
13
+ return response.data;
14
+ }
15
+ /** List public posts, optionally filtered by topic, status, or sort order. */
16
+ async posts(params) {
17
+ const query = {};
18
+ if (params?.topicSlug) query.topicSlug = params.topicSlug;
19
+ if (params?.status) query.status = params.status;
20
+ if (params?.sort) query.sort = params.sort;
21
+ if (params?.limit) query.limit = String(params.limit);
22
+ if (params?.offset) query.offset = String(params.offset);
23
+ const response = await this.fetch(
24
+ `/api/community/${this.teamSlug}/posts`,
25
+ query
26
+ );
27
+ return { posts: response.data, count: response.count };
28
+ }
29
+ /** Get a single post by slug, including all comments. */
30
+ async post(slug) {
31
+ const response = await this.fetch(
32
+ `/api/community/${this.teamSlug}/posts/${slug}`
33
+ );
34
+ return response.data;
35
+ }
36
+ /**
37
+ * Full-text search across post titles and bodies.
38
+ * Returns matching posts with relevance ranking.
39
+ */
40
+ async search(query) {
41
+ return this.fetch(`/api/community/${this.teamSlug}/search`, {
42
+ q: query
43
+ });
44
+ }
45
+ async fetch(path, query) {
46
+ let url = `${this.baseUrl}${path}`;
47
+ if (query) {
48
+ const params = new URLSearchParams();
49
+ for (const [key, value] of Object.entries(query)) {
50
+ if (value !== void 0) params.set(key, value);
51
+ }
52
+ const qs = params.toString();
53
+ if (qs) url += `?${qs}`;
54
+ }
55
+ const response = await globalThis.fetch(url, {
56
+ method: "GET",
57
+ headers: { "Content-Type": "application/json" }
58
+ });
59
+ if (!response.ok) {
60
+ const errorBody = await response.json().catch(() => ({ error: { message: "Request failed" } }));
61
+ const message = typeof errorBody.error === "string" ? errorBody.error : errorBody.error?.message ?? `Community API error: ${response.status}`;
62
+ throw new Error(message);
63
+ }
64
+ return response.json();
65
+ }
66
+ };
67
+ export {
68
+ CommunityClient
69
+ };
package/dist/index.cjs CHANGED
@@ -341,6 +341,49 @@ var CategoriesResource = class extends BaseResource {
341
341
  }
342
342
  };
343
343
 
344
+ // src/resources/communityPosts.ts
345
+ var CommunityPostsResource = class extends BaseResource {
346
+ constructor(client) {
347
+ super(client, "/community/posts");
348
+ }
349
+ /** Toggle vote on a post. Returns new vote state and count. */
350
+ async vote(postId) {
351
+ return this.client.request(
352
+ "POST",
353
+ `${this.basePath}/${postId}/vote`
354
+ );
355
+ }
356
+ /** Toggle follow on a post. Returns new follow state. */
357
+ async follow(postId) {
358
+ return this.client.request(
359
+ "POST",
360
+ `${this.basePath}/${postId}/follow`
361
+ );
362
+ }
363
+ /** List all comments on a post. */
364
+ async listComments(postId) {
365
+ return this.client.request(
366
+ "GET",
367
+ `${this.basePath}/${postId}/comments`
368
+ );
369
+ }
370
+ /** Add a comment to a post. */
371
+ async createComment(postId, params) {
372
+ return this.client.request(
373
+ "POST",
374
+ `${this.basePath}/${postId}/comments`,
375
+ { body: params }
376
+ );
377
+ }
378
+ };
379
+
380
+ // src/resources/communityTopics.ts
381
+ var CommunityTopicsResource = class extends BaseResource {
382
+ constructor(client) {
383
+ super(client, "/community/topics");
384
+ }
385
+ };
386
+
344
387
  // src/index.ts
345
388
  var CStarClient = class {
346
389
  constructor(config) {
@@ -350,6 +393,10 @@ var CStarClient = class {
350
393
  this.articles = new ArticlesResource(this.client);
351
394
  this.webhooks = new WebhooksResource(this.client);
352
395
  this.categories = new CategoriesResource(this.client);
396
+ this.community = {
397
+ posts: new CommunityPostsResource(this.client),
398
+ topics: new CommunityTopicsResource(this.client)
399
+ };
353
400
  }
354
401
  /** Whether this client is using test mode keys (sk_test_* or pk_test_*). */
355
402
  get isTestMode() {
package/dist/index.d.cts CHANGED
@@ -471,6 +471,107 @@ declare class CategoriesResource extends BaseResource<Category, CategoryListPara
471
471
  constructor(client: HttpClient);
472
472
  }
473
473
 
474
+ /** A community discussion topic (category/board). */
475
+ interface CommunityTopic {
476
+ id: string;
477
+ name: string;
478
+ slug: string;
479
+ description: string | null;
480
+ icon: string;
481
+ visibility: 'public' | 'members_only';
482
+ sortOrder: number;
483
+ postCount: number;
484
+ createdAt: string;
485
+ }
486
+ /** A community discussion post. */
487
+ interface CommunityPost {
488
+ id: string;
489
+ topicId: string;
490
+ topicName: string;
491
+ title: string;
492
+ slug: string;
493
+ body: string | null;
494
+ status: 'open' | 'answered' | 'officially_answered' | 'planned' | 'not_planned' | 'completed' | 'under_review';
495
+ visibility: 'public' | 'members_only';
496
+ voteCount: number;
497
+ commentCount: number;
498
+ isPinned: boolean;
499
+ isFeatured: boolean;
500
+ isLocked: boolean;
501
+ commentsEnabled: boolean;
502
+ authorName: string;
503
+ lastActivityAt: string;
504
+ createdAt: string;
505
+ updatedAt: string;
506
+ }
507
+ /** A comment on a community post. */
508
+ interface CommunityComment {
509
+ id: string;
510
+ postId: string;
511
+ body: string;
512
+ isOfficial: boolean;
513
+ voteScore: number;
514
+ authorName: string;
515
+ parentCommentId: string | null;
516
+ createdAt: string;
517
+ }
518
+ /** Query parameters for listing community posts. */
519
+ interface CommunityPostListParams {
520
+ topicId?: string;
521
+ status?: string;
522
+ sort?: 'recent' | 'votes' | 'comments';
523
+ page?: number;
524
+ pageSize?: number;
525
+ }
526
+ /** Parameters for creating a community post. */
527
+ interface CommunityPostCreateParams {
528
+ title: string;
529
+ body?: string;
530
+ topicId: string;
531
+ visibility?: 'public' | 'members_only';
532
+ }
533
+ /** Parameters for updating a community post. */
534
+ interface CommunityPostUpdateParams {
535
+ title?: string;
536
+ body?: string;
537
+ topicId?: string;
538
+ status?: string;
539
+ visibility?: string;
540
+ isPinned?: boolean;
541
+ isLocked?: boolean;
542
+ isHidden?: boolean;
543
+ commentsEnabled?: boolean;
544
+ }
545
+ /** Parameters for creating a comment on a community post. */
546
+ interface CommunityCommentCreateParams {
547
+ body: string;
548
+ parentCommentId?: string;
549
+ isOfficial?: boolean;
550
+ }
551
+
552
+ /** Manage community discussion posts. */
553
+ declare class CommunityPostsResource extends BaseResource<CommunityPost, CommunityPostListParams, CommunityPostCreateParams, CommunityPostUpdateParams> {
554
+ constructor(client: HttpClient);
555
+ /** Toggle vote on a post. Returns new vote state and count. */
556
+ vote(postId: string): Promise<ApiResponse<{
557
+ voted: boolean;
558
+ voteCount: number;
559
+ }>>;
560
+ /** Toggle follow on a post. Returns new follow state. */
561
+ follow(postId: string): Promise<ApiResponse<{
562
+ following: boolean;
563
+ }>>;
564
+ /** List all comments on a post. */
565
+ listComments(postId: string): Promise<ApiResponse<CommunityComment[]>>;
566
+ /** Add a comment to a post. */
567
+ createComment(postId: string, params: CommunityCommentCreateParams): Promise<ApiResponse<CommunityComment>>;
568
+ }
569
+
570
+ /** Manage community discussion topics. */
571
+ declare class CommunityTopicsResource extends BaseResource<CommunityTopic, Record<string, never>, never, never> {
572
+ constructor(client: HttpClient);
573
+ }
574
+
474
575
  /** Error type constants matching the cStar API. */
475
576
  declare const ErrorType: {
476
577
  readonly AUTHENTICATION_ERROR: "authentication_error";
@@ -554,10 +655,15 @@ declare class CStarClient {
554
655
  readonly webhooks: WebhooksResource;
555
656
  /** Manage article categories. */
556
657
  readonly categories: CategoriesResource;
658
+ /** Manage community posts and topics. */
659
+ readonly community: {
660
+ readonly posts: CommunityPostsResource;
661
+ readonly topics: CommunityTopicsResource;
662
+ };
557
663
  private readonly client;
558
664
  constructor(config: CStarClientConfig);
559
665
  /** Whether this client is using test mode keys (sk_test_* or pk_test_*). */
560
666
  get isTestMode(): boolean;
561
667
  }
562
668
 
563
- export { type ApiErrorBody, type ApiResponse, type Article, type ArticleCreateParams, type ArticleListParams, type ArticleUpdateParams, CStarAuthenticationError, CStarClient, type CStarClientConfig, CStarError, CStarNotFoundError, CStarRateLimitError, CStarValidationError, type Category, type CategoryCreateParams, type CategoryListParams, type CategoryUpdateParams, type Customer, type CustomerCreateParams, type CustomerListParams, type CustomerUpdateParams, type DeleteResponse, ErrorType, type ListResponse, type Message, type MessageCreateParams, type Metadata, type PaginationInfo, type PaginationParams, type RequestOptions, type Ticket, type TicketCreateParams, type TicketCustomerSummary, type TicketListParams, type TicketUpdateParams, type Webhook, type WebhookCreateParams, type WebhookEvent, type WebhookEventData, type WebhookEventType, type WebhookListParams, type WebhookTestResult, type WebhookUpdateParams };
669
+ export { type ApiErrorBody, type ApiResponse, type Article, type ArticleCreateParams, type ArticleListParams, type ArticleUpdateParams, CStarAuthenticationError, CStarClient, type CStarClientConfig, CStarError, CStarNotFoundError, CStarRateLimitError, CStarValidationError, type Category, type CategoryCreateParams, type CategoryListParams, type CategoryUpdateParams, type CommunityComment, type CommunityCommentCreateParams, type CommunityPost, type CommunityPostCreateParams, type CommunityPostListParams, type CommunityPostUpdateParams, type CommunityTopic, type Customer, type CustomerCreateParams, type CustomerListParams, type CustomerUpdateParams, type DeleteResponse, ErrorType, type ListResponse, type Message, type MessageCreateParams, type Metadata, type PaginationInfo, type PaginationParams, type RequestOptions, type Ticket, type TicketCreateParams, type TicketCustomerSummary, type TicketListParams, type TicketUpdateParams, type Webhook, type WebhookCreateParams, type WebhookEvent, type WebhookEventData, type WebhookEventType, type WebhookListParams, type WebhookTestResult, type WebhookUpdateParams };
package/dist/index.d.ts CHANGED
@@ -471,6 +471,107 @@ declare class CategoriesResource extends BaseResource<Category, CategoryListPara
471
471
  constructor(client: HttpClient);
472
472
  }
473
473
 
474
+ /** A community discussion topic (category/board). */
475
+ interface CommunityTopic {
476
+ id: string;
477
+ name: string;
478
+ slug: string;
479
+ description: string | null;
480
+ icon: string;
481
+ visibility: 'public' | 'members_only';
482
+ sortOrder: number;
483
+ postCount: number;
484
+ createdAt: string;
485
+ }
486
+ /** A community discussion post. */
487
+ interface CommunityPost {
488
+ id: string;
489
+ topicId: string;
490
+ topicName: string;
491
+ title: string;
492
+ slug: string;
493
+ body: string | null;
494
+ status: 'open' | 'answered' | 'officially_answered' | 'planned' | 'not_planned' | 'completed' | 'under_review';
495
+ visibility: 'public' | 'members_only';
496
+ voteCount: number;
497
+ commentCount: number;
498
+ isPinned: boolean;
499
+ isFeatured: boolean;
500
+ isLocked: boolean;
501
+ commentsEnabled: boolean;
502
+ authorName: string;
503
+ lastActivityAt: string;
504
+ createdAt: string;
505
+ updatedAt: string;
506
+ }
507
+ /** A comment on a community post. */
508
+ interface CommunityComment {
509
+ id: string;
510
+ postId: string;
511
+ body: string;
512
+ isOfficial: boolean;
513
+ voteScore: number;
514
+ authorName: string;
515
+ parentCommentId: string | null;
516
+ createdAt: string;
517
+ }
518
+ /** Query parameters for listing community posts. */
519
+ interface CommunityPostListParams {
520
+ topicId?: string;
521
+ status?: string;
522
+ sort?: 'recent' | 'votes' | 'comments';
523
+ page?: number;
524
+ pageSize?: number;
525
+ }
526
+ /** Parameters for creating a community post. */
527
+ interface CommunityPostCreateParams {
528
+ title: string;
529
+ body?: string;
530
+ topicId: string;
531
+ visibility?: 'public' | 'members_only';
532
+ }
533
+ /** Parameters for updating a community post. */
534
+ interface CommunityPostUpdateParams {
535
+ title?: string;
536
+ body?: string;
537
+ topicId?: string;
538
+ status?: string;
539
+ visibility?: string;
540
+ isPinned?: boolean;
541
+ isLocked?: boolean;
542
+ isHidden?: boolean;
543
+ commentsEnabled?: boolean;
544
+ }
545
+ /** Parameters for creating a comment on a community post. */
546
+ interface CommunityCommentCreateParams {
547
+ body: string;
548
+ parentCommentId?: string;
549
+ isOfficial?: boolean;
550
+ }
551
+
552
+ /** Manage community discussion posts. */
553
+ declare class CommunityPostsResource extends BaseResource<CommunityPost, CommunityPostListParams, CommunityPostCreateParams, CommunityPostUpdateParams> {
554
+ constructor(client: HttpClient);
555
+ /** Toggle vote on a post. Returns new vote state and count. */
556
+ vote(postId: string): Promise<ApiResponse<{
557
+ voted: boolean;
558
+ voteCount: number;
559
+ }>>;
560
+ /** Toggle follow on a post. Returns new follow state. */
561
+ follow(postId: string): Promise<ApiResponse<{
562
+ following: boolean;
563
+ }>>;
564
+ /** List all comments on a post. */
565
+ listComments(postId: string): Promise<ApiResponse<CommunityComment[]>>;
566
+ /** Add a comment to a post. */
567
+ createComment(postId: string, params: CommunityCommentCreateParams): Promise<ApiResponse<CommunityComment>>;
568
+ }
569
+
570
+ /** Manage community discussion topics. */
571
+ declare class CommunityTopicsResource extends BaseResource<CommunityTopic, Record<string, never>, never, never> {
572
+ constructor(client: HttpClient);
573
+ }
574
+
474
575
  /** Error type constants matching the cStar API. */
475
576
  declare const ErrorType: {
476
577
  readonly AUTHENTICATION_ERROR: "authentication_error";
@@ -554,10 +655,15 @@ declare class CStarClient {
554
655
  readonly webhooks: WebhooksResource;
555
656
  /** Manage article categories. */
556
657
  readonly categories: CategoriesResource;
658
+ /** Manage community posts and topics. */
659
+ readonly community: {
660
+ readonly posts: CommunityPostsResource;
661
+ readonly topics: CommunityTopicsResource;
662
+ };
557
663
  private readonly client;
558
664
  constructor(config: CStarClientConfig);
559
665
  /** Whether this client is using test mode keys (sk_test_* or pk_test_*). */
560
666
  get isTestMode(): boolean;
561
667
  }
562
668
 
563
- export { type ApiErrorBody, type ApiResponse, type Article, type ArticleCreateParams, type ArticleListParams, type ArticleUpdateParams, CStarAuthenticationError, CStarClient, type CStarClientConfig, CStarError, CStarNotFoundError, CStarRateLimitError, CStarValidationError, type Category, type CategoryCreateParams, type CategoryListParams, type CategoryUpdateParams, type Customer, type CustomerCreateParams, type CustomerListParams, type CustomerUpdateParams, type DeleteResponse, ErrorType, type ListResponse, type Message, type MessageCreateParams, type Metadata, type PaginationInfo, type PaginationParams, type RequestOptions, type Ticket, type TicketCreateParams, type TicketCustomerSummary, type TicketListParams, type TicketUpdateParams, type Webhook, type WebhookCreateParams, type WebhookEvent, type WebhookEventData, type WebhookEventType, type WebhookListParams, type WebhookTestResult, type WebhookUpdateParams };
669
+ export { type ApiErrorBody, type ApiResponse, type Article, type ArticleCreateParams, type ArticleListParams, type ArticleUpdateParams, CStarAuthenticationError, CStarClient, type CStarClientConfig, CStarError, CStarNotFoundError, CStarRateLimitError, CStarValidationError, type Category, type CategoryCreateParams, type CategoryListParams, type CategoryUpdateParams, type CommunityComment, type CommunityCommentCreateParams, type CommunityPost, type CommunityPostCreateParams, type CommunityPostListParams, type CommunityPostUpdateParams, type CommunityTopic, type Customer, type CustomerCreateParams, type CustomerListParams, type CustomerUpdateParams, type DeleteResponse, ErrorType, type ListResponse, type Message, type MessageCreateParams, type Metadata, type PaginationInfo, type PaginationParams, type RequestOptions, type Ticket, type TicketCreateParams, type TicketCustomerSummary, type TicketListParams, type TicketUpdateParams, type Webhook, type WebhookCreateParams, type WebhookEvent, type WebhookEventData, type WebhookEventType, type WebhookListParams, type WebhookTestResult, type WebhookUpdateParams };
package/dist/index.js CHANGED
@@ -309,6 +309,49 @@ var CategoriesResource = class extends BaseResource {
309
309
  }
310
310
  };
311
311
 
312
+ // src/resources/communityPosts.ts
313
+ var CommunityPostsResource = class extends BaseResource {
314
+ constructor(client) {
315
+ super(client, "/community/posts");
316
+ }
317
+ /** Toggle vote on a post. Returns new vote state and count. */
318
+ async vote(postId) {
319
+ return this.client.request(
320
+ "POST",
321
+ `${this.basePath}/${postId}/vote`
322
+ );
323
+ }
324
+ /** Toggle follow on a post. Returns new follow state. */
325
+ async follow(postId) {
326
+ return this.client.request(
327
+ "POST",
328
+ `${this.basePath}/${postId}/follow`
329
+ );
330
+ }
331
+ /** List all comments on a post. */
332
+ async listComments(postId) {
333
+ return this.client.request(
334
+ "GET",
335
+ `${this.basePath}/${postId}/comments`
336
+ );
337
+ }
338
+ /** Add a comment to a post. */
339
+ async createComment(postId, params) {
340
+ return this.client.request(
341
+ "POST",
342
+ `${this.basePath}/${postId}/comments`,
343
+ { body: params }
344
+ );
345
+ }
346
+ };
347
+
348
+ // src/resources/communityTopics.ts
349
+ var CommunityTopicsResource = class extends BaseResource {
350
+ constructor(client) {
351
+ super(client, "/community/topics");
352
+ }
353
+ };
354
+
312
355
  // src/index.ts
313
356
  var CStarClient = class {
314
357
  constructor(config) {
@@ -318,6 +361,10 @@ var CStarClient = class {
318
361
  this.articles = new ArticlesResource(this.client);
319
362
  this.webhooks = new WebhooksResource(this.client);
320
363
  this.categories = new CategoriesResource(this.client);
364
+ this.community = {
365
+ posts: new CommunityPostsResource(this.client),
366
+ topics: new CommunityTopicsResource(this.client)
367
+ };
321
368
  }
322
369
  /** Whether this client is using test mode keys (sk_test_* or pk_test_*). */
323
370
  get isTestMode() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cstar.help/js",
3
- "version": "0.3.4",
3
+ "version": "0.4.0",
4
4
  "description": "Official TypeScript SDK for the cStar customer support platform",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -47,6 +47,16 @@
47
47
  "default": "./dist/webhook/index.cjs"
48
48
  }
49
49
  },
50
+ "./community": {
51
+ "import": {
52
+ "types": "./dist/community/index.d.ts",
53
+ "default": "./dist/community/index.js"
54
+ },
55
+ "require": {
56
+ "types": "./dist/community/index.d.cts",
57
+ "default": "./dist/community/index.cjs"
58
+ }
59
+ },
50
60
  "./auth": {
51
61
  "import": {
52
62
  "types": "./dist/auth/index.d.ts",