@cstar.help/js 0.1.1 → 0.2.1

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
@@ -140,7 +140,7 @@ const event = await constructEventAsync(rawBody, signature, secret);
140
140
  const cstar = new CStarClient({
141
141
  apiKey: 'sk_live_...', // Required — secret or publishable key
142
142
  teamId: 'tm_...', // Required — your team ID
143
- baseUrl: 'https://...', // Optional — defaults to https://app.cstar.help
143
+ baseUrl: 'https://...', // Optional — defaults to https://www.cstar.help
144
144
  version: '2026-03-01', // Optional — API version header
145
145
  maxRetries: 3, // Optional — retry attempts for 5xx/429
146
146
  timeout: 30000 // Optional — request timeout in ms
@@ -0,0 +1,127 @@
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/auth/index.ts
21
+ var auth_exports = {};
22
+ __export(auth_exports, {
23
+ AuthClient: () => AuthClient
24
+ });
25
+ module.exports = __toCommonJS(auth_exports);
26
+ var DEFAULT_BASE_URL = "https://app.cstar.help";
27
+ var AuthClient = class {
28
+ constructor(config) {
29
+ this.session = null;
30
+ this.baseUrl = (config.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
31
+ this.teamSlug = config.teamSlug;
32
+ }
33
+ /**
34
+ * Create a new customer account.
35
+ *
36
+ * If the team requires email confirmation, returns a `SignupConfirmationResult`
37
+ * instead of tokens. Check for `requiresConfirmation` in the response.
38
+ *
39
+ * @throws Error on validation failure, duplicate email, or server error
40
+ */
41
+ async signup(params) {
42
+ const response = await this.fetch(
43
+ "/widget/api/auth/signup",
44
+ {
45
+ method: "POST",
46
+ body: {
47
+ team_id: this.teamSlug,
48
+ email: params.email,
49
+ password: params.password,
50
+ name: params.name
51
+ }
52
+ }
53
+ );
54
+ if ("access_token" in response && response.access_token && response.customer) {
55
+ this.session = {
56
+ customer: response.customer,
57
+ accessToken: response.access_token,
58
+ refreshToken: response.refresh_token
59
+ };
60
+ }
61
+ return response;
62
+ }
63
+ /**
64
+ * Log in an existing customer with email and password.
65
+ *
66
+ * On success, stores the session internally so subsequent
67
+ * ChatClient requests can use `auth.getSession()` for tokens.
68
+ *
69
+ * @throws Error on invalid credentials, unconfirmed email, or server error
70
+ */
71
+ async login(params) {
72
+ const response = await this.fetch("/widget/api/auth/login", {
73
+ method: "POST",
74
+ body: {
75
+ team_id: this.teamSlug,
76
+ email: params.email,
77
+ password: params.password
78
+ }
79
+ });
80
+ if (response.access_token && response.customer) {
81
+ this.session = {
82
+ customer: response.customer,
83
+ accessToken: response.access_token,
84
+ refreshToken: response.refresh_token
85
+ };
86
+ }
87
+ return response;
88
+ }
89
+ /** Clear the stored session. */
90
+ logout() {
91
+ this.session = null;
92
+ }
93
+ /** Get the current session, or null if not authenticated. */
94
+ getSession() {
95
+ return this.session;
96
+ }
97
+ /** Get the authenticated customer, or null if not logged in. */
98
+ getCustomer() {
99
+ return this.session?.customer ?? null;
100
+ }
101
+ /** Whether a customer is currently authenticated. */
102
+ get isAuthenticated() {
103
+ return this.session !== null;
104
+ }
105
+ /** Get the current access token, or null. Useful for passing to ChatClient. */
106
+ get accessToken() {
107
+ return this.session?.accessToken ?? null;
108
+ }
109
+ async fetch(path, options) {
110
+ const url = `${this.baseUrl}${path}`;
111
+ const response = await globalThis.fetch(url, {
112
+ method: options.method,
113
+ headers: { "Content-Type": "application/json" },
114
+ body: options.body ? JSON.stringify(options.body) : void 0
115
+ });
116
+ if (!response.ok) {
117
+ const errorBody = await response.json().catch(() => ({ error: "Request failed" }));
118
+ const message = errorBody.error ?? errorBody.message ?? `Auth API error: ${response.status}`;
119
+ throw new Error(message);
120
+ }
121
+ return response.json();
122
+ }
123
+ };
124
+ // Annotate the CommonJS export names for ESM import in node:
125
+ 0 && (module.exports = {
126
+ AuthClient
127
+ });
@@ -0,0 +1,123 @@
1
+ /** Configuration for the AuthClient. */
2
+ interface AuthConfig {
3
+ /** Team slug (e.g., 'acme'). Identifies which team's customers to authenticate. */
4
+ teamSlug: string;
5
+ /** Override the base URL (defaults to https://app.cstar.help). */
6
+ baseUrl?: string;
7
+ }
8
+ /** A customer identity returned from auth endpoints. */
9
+ interface AuthCustomer {
10
+ id: string;
11
+ email: string;
12
+ name: string;
13
+ }
14
+ /** Parameters for signing up a new customer. */
15
+ interface SignupParams {
16
+ /** Customer email address. */
17
+ email: string;
18
+ /** Password (minimum 6 characters). */
19
+ password: string;
20
+ /** Customer display name. */
21
+ name?: string;
22
+ }
23
+ /** Response from a successful signup. */
24
+ interface SignupResult {
25
+ customer: AuthCustomer;
26
+ /** Access token for authenticated requests. Null if email confirmation is required. */
27
+ access_token: string | null;
28
+ /** Refresh token for renewing the session. Null if email confirmation is required. */
29
+ refresh_token: string | null;
30
+ }
31
+ /** Response when email confirmation is required after signup. */
32
+ interface SignupConfirmationResult {
33
+ success: true;
34
+ message: string;
35
+ requiresConfirmation: true;
36
+ }
37
+ /** Parameters for logging in an existing customer. */
38
+ interface LoginParams {
39
+ /** Customer email address. */
40
+ email: string;
41
+ /** Customer password. */
42
+ password: string;
43
+ }
44
+ /** Response from a successful login. */
45
+ interface LoginResult {
46
+ customer: AuthCustomer;
47
+ /** Access token for authenticated requests. */
48
+ access_token: string | null;
49
+ /** Refresh token for renewing the session. */
50
+ refresh_token: string | null;
51
+ }
52
+ /** Stored session with tokens and customer identity. */
53
+ interface AuthSession {
54
+ customer: AuthCustomer;
55
+ accessToken: string;
56
+ refreshToken: string;
57
+ }
58
+
59
+ /**
60
+ * Customer authentication client for the cStar widget API.
61
+ *
62
+ * Provides signup, login, and session management for end-customers
63
+ * interacting with your support widget or custom integration.
64
+ *
65
+ * ```typescript
66
+ * import { AuthClient } from '@cstar.help/js/auth';
67
+ *
68
+ * const auth = new AuthClient({ teamSlug: 'acme' });
69
+ *
70
+ * // Sign up a new customer
71
+ * const result = await auth.signup({
72
+ * email: 'jane@example.com',
73
+ * password: 'securepass123',
74
+ * name: 'Jane Doe',
75
+ * });
76
+ *
77
+ * // Log in an existing customer
78
+ * const session = await auth.login({
79
+ * email: 'jane@example.com',
80
+ * password: 'securepass123',
81
+ * });
82
+ *
83
+ * // Check current session
84
+ * const current = auth.getSession();
85
+ * ```
86
+ */
87
+ declare class AuthClient {
88
+ private readonly baseUrl;
89
+ private readonly teamSlug;
90
+ private session;
91
+ constructor(config: AuthConfig);
92
+ /**
93
+ * Create a new customer account.
94
+ *
95
+ * If the team requires email confirmation, returns a `SignupConfirmationResult`
96
+ * instead of tokens. Check for `requiresConfirmation` in the response.
97
+ *
98
+ * @throws Error on validation failure, duplicate email, or server error
99
+ */
100
+ signup(params: SignupParams): Promise<SignupResult | SignupConfirmationResult>;
101
+ /**
102
+ * Log in an existing customer with email and password.
103
+ *
104
+ * On success, stores the session internally so subsequent
105
+ * ChatClient requests can use `auth.getSession()` for tokens.
106
+ *
107
+ * @throws Error on invalid credentials, unconfirmed email, or server error
108
+ */
109
+ login(params: LoginParams): Promise<LoginResult>;
110
+ /** Clear the stored session. */
111
+ logout(): void;
112
+ /** Get the current session, or null if not authenticated. */
113
+ getSession(): AuthSession | null;
114
+ /** Get the authenticated customer, or null if not logged in. */
115
+ getCustomer(): AuthCustomer | null;
116
+ /** Whether a customer is currently authenticated. */
117
+ get isAuthenticated(): boolean;
118
+ /** Get the current access token, or null. Useful for passing to ChatClient. */
119
+ get accessToken(): string | null;
120
+ private fetch;
121
+ }
122
+
123
+ export { AuthClient, type AuthConfig, type AuthCustomer, type AuthSession, type LoginParams, type LoginResult, type SignupConfirmationResult, type SignupParams, type SignupResult };
@@ -0,0 +1,123 @@
1
+ /** Configuration for the AuthClient. */
2
+ interface AuthConfig {
3
+ /** Team slug (e.g., 'acme'). Identifies which team's customers to authenticate. */
4
+ teamSlug: string;
5
+ /** Override the base URL (defaults to https://app.cstar.help). */
6
+ baseUrl?: string;
7
+ }
8
+ /** A customer identity returned from auth endpoints. */
9
+ interface AuthCustomer {
10
+ id: string;
11
+ email: string;
12
+ name: string;
13
+ }
14
+ /** Parameters for signing up a new customer. */
15
+ interface SignupParams {
16
+ /** Customer email address. */
17
+ email: string;
18
+ /** Password (minimum 6 characters). */
19
+ password: string;
20
+ /** Customer display name. */
21
+ name?: string;
22
+ }
23
+ /** Response from a successful signup. */
24
+ interface SignupResult {
25
+ customer: AuthCustomer;
26
+ /** Access token for authenticated requests. Null if email confirmation is required. */
27
+ access_token: string | null;
28
+ /** Refresh token for renewing the session. Null if email confirmation is required. */
29
+ refresh_token: string | null;
30
+ }
31
+ /** Response when email confirmation is required after signup. */
32
+ interface SignupConfirmationResult {
33
+ success: true;
34
+ message: string;
35
+ requiresConfirmation: true;
36
+ }
37
+ /** Parameters for logging in an existing customer. */
38
+ interface LoginParams {
39
+ /** Customer email address. */
40
+ email: string;
41
+ /** Customer password. */
42
+ password: string;
43
+ }
44
+ /** Response from a successful login. */
45
+ interface LoginResult {
46
+ customer: AuthCustomer;
47
+ /** Access token for authenticated requests. */
48
+ access_token: string | null;
49
+ /** Refresh token for renewing the session. */
50
+ refresh_token: string | null;
51
+ }
52
+ /** Stored session with tokens and customer identity. */
53
+ interface AuthSession {
54
+ customer: AuthCustomer;
55
+ accessToken: string;
56
+ refreshToken: string;
57
+ }
58
+
59
+ /**
60
+ * Customer authentication client for the cStar widget API.
61
+ *
62
+ * Provides signup, login, and session management for end-customers
63
+ * interacting with your support widget or custom integration.
64
+ *
65
+ * ```typescript
66
+ * import { AuthClient } from '@cstar.help/js/auth';
67
+ *
68
+ * const auth = new AuthClient({ teamSlug: 'acme' });
69
+ *
70
+ * // Sign up a new customer
71
+ * const result = await auth.signup({
72
+ * email: 'jane@example.com',
73
+ * password: 'securepass123',
74
+ * name: 'Jane Doe',
75
+ * });
76
+ *
77
+ * // Log in an existing customer
78
+ * const session = await auth.login({
79
+ * email: 'jane@example.com',
80
+ * password: 'securepass123',
81
+ * });
82
+ *
83
+ * // Check current session
84
+ * const current = auth.getSession();
85
+ * ```
86
+ */
87
+ declare class AuthClient {
88
+ private readonly baseUrl;
89
+ private readonly teamSlug;
90
+ private session;
91
+ constructor(config: AuthConfig);
92
+ /**
93
+ * Create a new customer account.
94
+ *
95
+ * If the team requires email confirmation, returns a `SignupConfirmationResult`
96
+ * instead of tokens. Check for `requiresConfirmation` in the response.
97
+ *
98
+ * @throws Error on validation failure, duplicate email, or server error
99
+ */
100
+ signup(params: SignupParams): Promise<SignupResult | SignupConfirmationResult>;
101
+ /**
102
+ * Log in an existing customer with email and password.
103
+ *
104
+ * On success, stores the session internally so subsequent
105
+ * ChatClient requests can use `auth.getSession()` for tokens.
106
+ *
107
+ * @throws Error on invalid credentials, unconfirmed email, or server error
108
+ */
109
+ login(params: LoginParams): Promise<LoginResult>;
110
+ /** Clear the stored session. */
111
+ logout(): void;
112
+ /** Get the current session, or null if not authenticated. */
113
+ getSession(): AuthSession | null;
114
+ /** Get the authenticated customer, or null if not logged in. */
115
+ getCustomer(): AuthCustomer | null;
116
+ /** Whether a customer is currently authenticated. */
117
+ get isAuthenticated(): boolean;
118
+ /** Get the current access token, or null. Useful for passing to ChatClient. */
119
+ get accessToken(): string | null;
120
+ private fetch;
121
+ }
122
+
123
+ export { AuthClient, type AuthConfig, type AuthCustomer, type AuthSession, type LoginParams, type LoginResult, type SignupConfirmationResult, type SignupParams, type SignupResult };
@@ -0,0 +1,102 @@
1
+ // src/auth/index.ts
2
+ var DEFAULT_BASE_URL = "https://app.cstar.help";
3
+ var AuthClient = class {
4
+ constructor(config) {
5
+ this.session = null;
6
+ this.baseUrl = (config.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
7
+ this.teamSlug = config.teamSlug;
8
+ }
9
+ /**
10
+ * Create a new customer account.
11
+ *
12
+ * If the team requires email confirmation, returns a `SignupConfirmationResult`
13
+ * instead of tokens. Check for `requiresConfirmation` in the response.
14
+ *
15
+ * @throws Error on validation failure, duplicate email, or server error
16
+ */
17
+ async signup(params) {
18
+ const response = await this.fetch(
19
+ "/widget/api/auth/signup",
20
+ {
21
+ method: "POST",
22
+ body: {
23
+ team_id: this.teamSlug,
24
+ email: params.email,
25
+ password: params.password,
26
+ name: params.name
27
+ }
28
+ }
29
+ );
30
+ if ("access_token" in response && response.access_token && response.customer) {
31
+ this.session = {
32
+ customer: response.customer,
33
+ accessToken: response.access_token,
34
+ refreshToken: response.refresh_token
35
+ };
36
+ }
37
+ return response;
38
+ }
39
+ /**
40
+ * Log in an existing customer with email and password.
41
+ *
42
+ * On success, stores the session internally so subsequent
43
+ * ChatClient requests can use `auth.getSession()` for tokens.
44
+ *
45
+ * @throws Error on invalid credentials, unconfirmed email, or server error
46
+ */
47
+ async login(params) {
48
+ const response = await this.fetch("/widget/api/auth/login", {
49
+ method: "POST",
50
+ body: {
51
+ team_id: this.teamSlug,
52
+ email: params.email,
53
+ password: params.password
54
+ }
55
+ });
56
+ if (response.access_token && response.customer) {
57
+ this.session = {
58
+ customer: response.customer,
59
+ accessToken: response.access_token,
60
+ refreshToken: response.refresh_token
61
+ };
62
+ }
63
+ return response;
64
+ }
65
+ /** Clear the stored session. */
66
+ logout() {
67
+ this.session = null;
68
+ }
69
+ /** Get the current session, or null if not authenticated. */
70
+ getSession() {
71
+ return this.session;
72
+ }
73
+ /** Get the authenticated customer, or null if not logged in. */
74
+ getCustomer() {
75
+ return this.session?.customer ?? null;
76
+ }
77
+ /** Whether a customer is currently authenticated. */
78
+ get isAuthenticated() {
79
+ return this.session !== null;
80
+ }
81
+ /** Get the current access token, or null. Useful for passing to ChatClient. */
82
+ get accessToken() {
83
+ return this.session?.accessToken ?? null;
84
+ }
85
+ async fetch(path, options) {
86
+ const url = `${this.baseUrl}${path}`;
87
+ const response = await globalThis.fetch(url, {
88
+ method: options.method,
89
+ headers: { "Content-Type": "application/json" },
90
+ body: options.body ? JSON.stringify(options.body) : void 0
91
+ });
92
+ if (!response.ok) {
93
+ const errorBody = await response.json().catch(() => ({ error: "Request failed" }));
94
+ const message = errorBody.error ?? errorBody.message ?? `Auth API error: ${response.status}`;
95
+ throw new Error(message);
96
+ }
97
+ return response.json();
98
+ }
99
+ };
100
+ export {
101
+ AuthClient
102
+ };
@@ -512,17 +512,14 @@ var ConversationsApi = class {
512
512
  /** Create a new conversation (ticket). */
513
513
  async create(params) {
514
514
  const teamId = this.chat.getTeamId();
515
- const response = await this.chat.fetch(
516
- "/api/widget/tickets",
517
- {
518
- method: "POST",
519
- body: {
520
- teamId,
521
- subject: params.subject,
522
- message: params.message
523
- }
515
+ const response = await this.chat.fetch("/api/widget/tickets", {
516
+ method: "POST",
517
+ body: {
518
+ teamId,
519
+ subject: params.subject,
520
+ message: params.message
524
521
  }
525
- );
522
+ });
526
523
  return {
527
524
  id: response.data.id,
528
525
  ticketNumber: "",
@@ -476,17 +476,14 @@ var ConversationsApi = class {
476
476
  /** Create a new conversation (ticket). */
477
477
  async create(params) {
478
478
  const teamId = this.chat.getTeamId();
479
- const response = await this.chat.fetch(
480
- "/api/widget/tickets",
481
- {
482
- method: "POST",
483
- body: {
484
- teamId,
485
- subject: params.subject,
486
- message: params.message
487
- }
479
+ const response = await this.chat.fetch("/api/widget/tickets", {
480
+ method: "POST",
481
+ body: {
482
+ teamId,
483
+ subject: params.subject,
484
+ message: params.message
488
485
  }
489
- );
486
+ });
490
487
  return {
491
488
  id: response.data.id,
492
489
  ticketNumber: "",
package/dist/index.cjs CHANGED
@@ -97,7 +97,7 @@ function parseError(statusCode, body, retryAfter) {
97
97
  }
98
98
 
99
99
  // src/client.ts
100
- var SDK_VERSION = "0.1.0";
100
+ var SDK_VERSION = "0.2.0";
101
101
  var DEFAULT_BASE_URL = "https://app.cstar.help";
102
102
  var DEFAULT_API_VERSION = "2026-03-01";
103
103
  var DEFAULT_MAX_RETRIES = 3;
@@ -179,7 +179,7 @@ var HttpClient = class {
179
179
  }
180
180
  buildHeaders(idempotencyKey) {
181
181
  const headers = {
182
- "Authorization": `Bearer ${this.config.apiKey}`,
182
+ Authorization: `Bearer ${this.config.apiKey}`,
183
183
  "Content-Type": "application/json",
184
184
  "CStar-Version": this.config.version,
185
185
  "User-Agent": `@cstar.help/js/${SDK_VERSION}`
@@ -235,10 +235,7 @@ var BaseResource = class {
235
235
  }
236
236
  /** Delete a resource by ID. */
237
237
  async del(id) {
238
- return this.client.request(
239
- "DELETE",
240
- `${this.basePath}/${id}`
241
- );
238
+ return this.client.request("DELETE", `${this.basePath}/${id}`);
242
239
  }
243
240
  /**
244
241
  * Auto-paginating async iterator that yields every item across all pages.
@@ -285,21 +282,14 @@ var TicketMessagesResource = class {
285
282
  }
286
283
  /** List all messages on a ticket. */
287
284
  async list(ticketId) {
288
- return this.client.request(
289
- "GET",
290
- `/tickets/${ticketId}/messages`
291
- );
285
+ return this.client.request("GET", `/tickets/${ticketId}/messages`);
292
286
  }
293
287
  /** Add a message to a ticket. */
294
288
  async create(ticketId, params, options) {
295
- return this.client.request(
296
- "POST",
297
- `/tickets/${ticketId}/messages`,
298
- {
299
- body: params,
300
- idempotencyKey: options?.idempotencyKey
301
- }
302
- );
289
+ return this.client.request("POST", `/tickets/${ticketId}/messages`, {
290
+ body: params,
291
+ idempotencyKey: options?.idempotencyKey
292
+ });
303
293
  }
304
294
  };
305
295
  var TicketsResource = class extends BaseResource {
package/dist/index.js CHANGED
@@ -65,7 +65,7 @@ function parseError(statusCode, body, retryAfter) {
65
65
  }
66
66
 
67
67
  // src/client.ts
68
- var SDK_VERSION = "0.1.0";
68
+ var SDK_VERSION = "0.2.0";
69
69
  var DEFAULT_BASE_URL = "https://app.cstar.help";
70
70
  var DEFAULT_API_VERSION = "2026-03-01";
71
71
  var DEFAULT_MAX_RETRIES = 3;
@@ -147,7 +147,7 @@ var HttpClient = class {
147
147
  }
148
148
  buildHeaders(idempotencyKey) {
149
149
  const headers = {
150
- "Authorization": `Bearer ${this.config.apiKey}`,
150
+ Authorization: `Bearer ${this.config.apiKey}`,
151
151
  "Content-Type": "application/json",
152
152
  "CStar-Version": this.config.version,
153
153
  "User-Agent": `@cstar.help/js/${SDK_VERSION}`
@@ -203,10 +203,7 @@ var BaseResource = class {
203
203
  }
204
204
  /** Delete a resource by ID. */
205
205
  async del(id) {
206
- return this.client.request(
207
- "DELETE",
208
- `${this.basePath}/${id}`
209
- );
206
+ return this.client.request("DELETE", `${this.basePath}/${id}`);
210
207
  }
211
208
  /**
212
209
  * Auto-paginating async iterator that yields every item across all pages.
@@ -253,21 +250,14 @@ var TicketMessagesResource = class {
253
250
  }
254
251
  /** List all messages on a ticket. */
255
252
  async list(ticketId) {
256
- return this.client.request(
257
- "GET",
258
- `/tickets/${ticketId}/messages`
259
- );
253
+ return this.client.request("GET", `/tickets/${ticketId}/messages`);
260
254
  }
261
255
  /** Add a message to a ticket. */
262
256
  async create(ticketId, params, options) {
263
- return this.client.request(
264
- "POST",
265
- `/tickets/${ticketId}/messages`,
266
- {
267
- body: params,
268
- idempotencyKey: options?.idempotencyKey
269
- }
270
- );
257
+ return this.client.request("POST", `/tickets/${ticketId}/messages`, {
258
+ body: params,
259
+ idempotencyKey: options?.idempotencyKey
260
+ });
271
261
  }
272
262
  };
273
263
  var TicketsResource = class extends BaseResource {
@@ -65,10 +65,24 @@ var LibraryClient = class {
65
65
  q: query
66
66
  };
67
67
  if (params?.limit) queryParams.limit = String(params.limit);
68
- return this.fetch(
69
- `/api/library/${this.teamSlug}/search`,
70
- queryParams
71
- );
68
+ return this.fetch(`/api/library/${this.teamSlug}/search`, queryParams);
69
+ }
70
+ /** Get the most viewed articles, sorted by view count descending. */
71
+ async popularArticles(limit = 5) {
72
+ const articles = await this.articles({ limit: 50 });
73
+ return articles.sort((a, b) => (b.view_count ?? 0) - (a.view_count ?? 0)).slice(0, limit);
74
+ }
75
+ /** Get aggregate stats for this knowledge base (article count, category count, total views). */
76
+ async stats() {
77
+ const [categories, articles] = await Promise.all([
78
+ this.categories(),
79
+ this.articles({ limit: 1e3 })
80
+ ]);
81
+ return {
82
+ totalArticles: articles.length,
83
+ totalCategories: categories.length,
84
+ totalViews: articles.reduce((sum, a) => sum + (a.view_count ?? 0), 0)
85
+ };
72
86
  }
73
87
  async fetch(path, query) {
74
88
  let url = `${this.baseUrl}${path}`;
@@ -50,6 +50,12 @@ interface LibrarySearchResult {
50
50
  count: number;
51
51
  query: string;
52
52
  }
53
+ /** Aggregate stats for a public knowledge base. */
54
+ interface LibraryStats {
55
+ totalArticles: number;
56
+ totalCategories: number;
57
+ totalViews: number;
58
+ }
53
59
 
54
60
  /**
55
61
  * Public knowledge base client. No authentication required.
@@ -76,7 +82,11 @@ declare class LibraryClient {
76
82
  * Returns matching articles with relevance ranking.
77
83
  */
78
84
  search(query: string, params?: LibrarySearchParams): Promise<LibrarySearchResult>;
85
+ /** Get the most viewed articles, sorted by view count descending. */
86
+ popularArticles(limit?: number): Promise<LibraryArticle[]>;
87
+ /** Get aggregate stats for this knowledge base (article count, category count, total views). */
88
+ stats(): Promise<LibraryStats>;
79
89
  private fetch;
80
90
  }
81
91
 
82
- export { type Category, type LibraryArticle, type LibraryArticleListParams, LibraryClient, type LibraryConfig, type LibrarySearchParams, type LibrarySearchResult };
92
+ export { type Category, type LibraryArticle, type LibraryArticleListParams, LibraryClient, type LibraryConfig, type LibrarySearchParams, type LibrarySearchResult, type LibraryStats };
@@ -50,6 +50,12 @@ interface LibrarySearchResult {
50
50
  count: number;
51
51
  query: string;
52
52
  }
53
+ /** Aggregate stats for a public knowledge base. */
54
+ interface LibraryStats {
55
+ totalArticles: number;
56
+ totalCategories: number;
57
+ totalViews: number;
58
+ }
53
59
 
54
60
  /**
55
61
  * Public knowledge base client. No authentication required.
@@ -76,7 +82,11 @@ declare class LibraryClient {
76
82
  * Returns matching articles with relevance ranking.
77
83
  */
78
84
  search(query: string, params?: LibrarySearchParams): Promise<LibrarySearchResult>;
85
+ /** Get the most viewed articles, sorted by view count descending. */
86
+ popularArticles(limit?: number): Promise<LibraryArticle[]>;
87
+ /** Get aggregate stats for this knowledge base (article count, category count, total views). */
88
+ stats(): Promise<LibraryStats>;
79
89
  private fetch;
80
90
  }
81
91
 
82
- export { type Category, type LibraryArticle, type LibraryArticleListParams, LibraryClient, type LibraryConfig, type LibrarySearchParams, type LibrarySearchResult };
92
+ export { type Category, type LibraryArticle, type LibraryArticleListParams, LibraryClient, type LibraryConfig, type LibrarySearchParams, type LibrarySearchResult, type LibraryStats };
@@ -41,10 +41,24 @@ var LibraryClient = class {
41
41
  q: query
42
42
  };
43
43
  if (params?.limit) queryParams.limit = String(params.limit);
44
- return this.fetch(
45
- `/api/library/${this.teamSlug}/search`,
46
- queryParams
47
- );
44
+ return this.fetch(`/api/library/${this.teamSlug}/search`, queryParams);
45
+ }
46
+ /** Get the most viewed articles, sorted by view count descending. */
47
+ async popularArticles(limit = 5) {
48
+ const articles = await this.articles({ limit: 50 });
49
+ return articles.sort((a, b) => (b.view_count ?? 0) - (a.view_count ?? 0)).slice(0, limit);
50
+ }
51
+ /** Get aggregate stats for this knowledge base (article count, category count, total views). */
52
+ async stats() {
53
+ const [categories, articles] = await Promise.all([
54
+ this.categories(),
55
+ this.articles({ limit: 1e3 })
56
+ ]);
57
+ return {
58
+ totalArticles: articles.length,
59
+ totalCategories: categories.length,
60
+ totalViews: articles.reduce((sum, a) => sum + (a.view_count ?? 0), 0)
61
+ };
48
62
  }
49
63
  async fetch(path, query) {
50
64
  let url = `${this.baseUrl}${path}`;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cstar.help/js",
3
- "version": "0.1.1",
3
+ "version": "0.2.1",
4
4
  "description": "Official TypeScript SDK for the cStar customer support platform",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -46,6 +46,16 @@
46
46
  "types": "./dist/webhook/index.d.cts",
47
47
  "default": "./dist/webhook/index.cjs"
48
48
  }
49
+ },
50
+ "./auth": {
51
+ "import": {
52
+ "types": "./dist/auth/index.d.ts",
53
+ "default": "./dist/auth/index.js"
54
+ },
55
+ "require": {
56
+ "types": "./dist/auth/index.d.cts",
57
+ "default": "./dist/auth/index.cjs"
58
+ }
49
59
  }
50
60
  },
51
61
  "files": [