@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.
@@ -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
+ };