@feedhog/js 0.1.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,338 @@
1
+ /**
2
+ * Feedhog SDK Types
3
+ * These types mirror the API response types from the Feedhog server.
4
+ */
5
+ type FeedbackType = "bug" | "idea" | "question" | "other";
6
+ type FeedbackStatus = "new" | "under-review" | "planned" | "in-progress" | "completed" | "closed";
7
+ type SortBy = "newest" | "oldest" | "votes" | "comments";
8
+ /**
9
+ * SDK Configuration
10
+ */
11
+ interface FeedhogConfig {
12
+ /** Public API key (starts with fhpk_) */
13
+ apiKey: string;
14
+ /** Base URL for the API (defaults to https://feedhog.com) */
15
+ baseUrl?: string;
16
+ }
17
+ /**
18
+ * User identification data
19
+ */
20
+ interface UserIdentity {
21
+ /** Your system's unique user ID */
22
+ externalId: string;
23
+ /** User's email address */
24
+ email?: string;
25
+ /** User's display name */
26
+ name?: string;
27
+ /** URL to user's avatar image */
28
+ avatarUrl?: string;
29
+ /** Additional metadata to associate with the user */
30
+ metadata?: Record<string, unknown>;
31
+ }
32
+ /**
33
+ * Feedback submission input
34
+ */
35
+ interface SubmitFeedbackInput {
36
+ /** Feedback title (required) */
37
+ title: string;
38
+ /** Detailed description */
39
+ description?: string;
40
+ /** Type of feedback */
41
+ type?: FeedbackType;
42
+ /** Additional metadata */
43
+ metadata?: Record<string, unknown>;
44
+ }
45
+ /**
46
+ * Options for listing feedback
47
+ */
48
+ interface ListFeedbackOptions {
49
+ /** Filter by status(es) */
50
+ status?: FeedbackStatus | FeedbackStatus[];
51
+ /** Filter by type(s) */
52
+ type?: FeedbackType | FeedbackType[];
53
+ /** Search query */
54
+ search?: string;
55
+ /** Sort order */
56
+ sortBy?: SortBy;
57
+ /** Page number (1-indexed) */
58
+ page?: number;
59
+ /** Items per page (max 100) */
60
+ limit?: number;
61
+ }
62
+ /**
63
+ * Feedback author info (public)
64
+ */
65
+ interface FeedbackAuthor {
66
+ name: string | null;
67
+ avatarUrl: string | null;
68
+ }
69
+ /**
70
+ * Comment author info (public)
71
+ */
72
+ interface CommentAuthor {
73
+ name: string | null;
74
+ avatarUrl?: string | null;
75
+ isTeam?: boolean;
76
+ }
77
+ /**
78
+ * Public comment on feedback
79
+ */
80
+ interface FeedbackComment {
81
+ id: string;
82
+ content: string;
83
+ createdAt: string;
84
+ author: CommentAuthor | null;
85
+ }
86
+ /**
87
+ * Feedback item from list endpoint
88
+ */
89
+ interface FeedbackListItem {
90
+ id: string;
91
+ title: string;
92
+ description: string | null;
93
+ type: FeedbackType;
94
+ status: FeedbackStatus;
95
+ voteCount: number;
96
+ commentCount: number;
97
+ createdAt: string;
98
+ endUser: FeedbackAuthor | null;
99
+ }
100
+ /**
101
+ * Feedback item with full details
102
+ */
103
+ interface FeedbackDetail extends FeedbackListItem {
104
+ userHasVoted: boolean;
105
+ comments: FeedbackComment[];
106
+ }
107
+ /**
108
+ * Paginated response
109
+ */
110
+ interface PaginatedResponse<T> {
111
+ items: T[];
112
+ total: number;
113
+ page: number;
114
+ limit: number;
115
+ totalPages: number;
116
+ }
117
+ /**
118
+ * Vote result
119
+ */
120
+ interface VoteResult {
121
+ voted: boolean;
122
+ voteCount: number;
123
+ }
124
+ /**
125
+ * Identified user response
126
+ */
127
+ interface IdentifiedUser {
128
+ id: string;
129
+ email: string | null;
130
+ name: string | null;
131
+ avatarUrl: string | null;
132
+ createdAt: string;
133
+ }
134
+ /**
135
+ * Internal: Current user state
136
+ */
137
+ interface CurrentUser extends UserIdentity {
138
+ identified: boolean;
139
+ }
140
+
141
+ /**
142
+ * Feedhog API Client
143
+ * Handles all HTTP communication with the Feedhog API.
144
+ */
145
+
146
+ /**
147
+ * API Error with status code and optional validation details
148
+ */
149
+ declare class FeedhogApiError extends Error {
150
+ readonly status: number;
151
+ readonly details?: {
152
+ formErrors: string[];
153
+ fieldErrors: Record<string, string[]>;
154
+ } | undefined;
155
+ constructor(message: string, status: number, details?: {
156
+ formErrors: string[];
157
+ fieldErrors: Record<string, string[]>;
158
+ } | undefined);
159
+ }
160
+
161
+ /**
162
+ * Simple event emitter for SDK events
163
+ */
164
+ declare class EventEmitter<Events extends {
165
+ [key: string]: unknown;
166
+ }> {
167
+ private listeners;
168
+ on<K extends keyof Events>(event: K, callback: (data: Events[K]) => void): () => void;
169
+ emit<K extends keyof Events>(event: K, data: Events[K]): void;
170
+ off<K extends keyof Events>(event: K, callback: (data: Events[K]) => void): void;
171
+ }
172
+
173
+ /**
174
+ * Feedhog JavaScript SDK
175
+ *
176
+ * Collect user feedback from any website or application.
177
+ *
178
+ * @example
179
+ * ```typescript
180
+ * import Feedhog from '@feedhog/js';
181
+ *
182
+ * const feedhog = new Feedhog({ apiKey: 'fhpk_xxx' });
183
+ *
184
+ * // Identify the current user (optional but recommended)
185
+ * feedhog.identify({
186
+ * externalId: 'user-123',
187
+ * email: 'user@example.com',
188
+ * name: 'John Doe'
189
+ * });
190
+ *
191
+ * // Submit feedback
192
+ * await feedhog.submit({
193
+ * title: 'Add dark mode',
194
+ * description: 'Would love a dark theme option',
195
+ * type: 'idea'
196
+ * });
197
+ * ```
198
+ */
199
+
200
+ interface FeedhogEvents {
201
+ [key: string]: unknown;
202
+ identify: IdentifiedUser;
203
+ submit: FeedbackListItem;
204
+ vote: {
205
+ feedbackId: string;
206
+ result: VoteResult;
207
+ };
208
+ error: Error;
209
+ reset: void;
210
+ }
211
+ /**
212
+ * Feedhog SDK main class
213
+ */
214
+ declare class Feedhog extends EventEmitter<FeedhogEvents> {
215
+ private readonly client;
216
+ private currentUser;
217
+ constructor(config: FeedhogConfig);
218
+ /**
219
+ * Get the currently identified user
220
+ */
221
+ get user(): CurrentUser | null;
222
+ /**
223
+ * Identify the current user
224
+ *
225
+ * This associates feedback and votes with a specific user in your system.
226
+ * User data is persisted in localStorage for subsequent sessions.
227
+ *
228
+ * @param user - User identity data
229
+ * @returns Promise resolving to the identified user
230
+ *
231
+ * @example
232
+ * ```typescript
233
+ * await feedhog.identify({
234
+ * externalId: 'user-123',
235
+ * email: 'user@example.com',
236
+ * name: 'John Doe',
237
+ * metadata: { plan: 'pro' }
238
+ * });
239
+ * ```
240
+ */
241
+ identify(user: UserIdentity): Promise<IdentifiedUser>;
242
+ /**
243
+ * Submit new feedback
244
+ *
245
+ * If a user has been identified, the feedback will be associated with them.
246
+ *
247
+ * @param input - Feedback data
248
+ * @returns Promise resolving to the created feedback item
249
+ *
250
+ * @example
251
+ * ```typescript
252
+ * const feedback = await feedhog.submit({
253
+ * title: 'Add dark mode',
254
+ * description: 'Would love a dark theme option',
255
+ * type: 'idea'
256
+ * });
257
+ * console.log('Feedback submitted:', feedback.id);
258
+ * ```
259
+ */
260
+ submit(input: SubmitFeedbackInput): Promise<FeedbackListItem>;
261
+ /**
262
+ * List feedback items
263
+ *
264
+ * Returns a paginated list of feedback for the project.
265
+ *
266
+ * @param options - Filter and pagination options
267
+ * @returns Promise resolving to paginated feedback list
268
+ *
269
+ * @example
270
+ * ```typescript
271
+ * // Get all ideas in "planned" status
272
+ * const { items, total } = await feedhog.list({
273
+ * status: ['planned', 'in-progress'],
274
+ * type: 'idea',
275
+ * sortBy: 'votes',
276
+ * limit: 10
277
+ * });
278
+ * ```
279
+ */
280
+ list(options?: ListFeedbackOptions): Promise<PaginatedResponse<FeedbackListItem>>;
281
+ /**
282
+ * Get a single feedback item with full details
283
+ *
284
+ * @param feedbackId - ID of the feedback item
285
+ * @returns Promise resolving to feedback details including comments
286
+ *
287
+ * @example
288
+ * ```typescript
289
+ * const feedback = await feedhog.get('abc123');
290
+ * console.log('Comments:', feedback.comments.length);
291
+ * console.log('Has voted:', feedback.userHasVoted);
292
+ * ```
293
+ */
294
+ get(feedbackId: string): Promise<FeedbackDetail>;
295
+ /**
296
+ * Toggle vote on a feedback item
297
+ *
298
+ * If the user has already voted, this will remove their vote.
299
+ * If they haven't voted, it will add their vote.
300
+ *
301
+ * @param feedbackId - ID of the feedback item to vote on
302
+ * @returns Promise resolving to vote result
303
+ *
304
+ * @example
305
+ * ```typescript
306
+ * const { voted, voteCount } = await feedhog.vote('abc123');
307
+ * console.log(voted ? 'Vote added' : 'Vote removed');
308
+ * console.log('Total votes:', voteCount);
309
+ * ```
310
+ */
311
+ vote(feedbackId: string): Promise<VoteResult>;
312
+ /**
313
+ * Check if the current user has voted on a feedback item
314
+ *
315
+ * @param feedbackId - ID of the feedback item
316
+ * @returns Promise resolving to vote status
317
+ *
318
+ * @example
319
+ * ```typescript
320
+ * const { voted, voteCount } = await feedhog.hasVoted('abc123');
321
+ * ```
322
+ */
323
+ hasVoted(feedbackId: string): Promise<VoteResult>;
324
+ /**
325
+ * Reset the SDK state
326
+ *
327
+ * Clears the current user and removes stored data.
328
+ * Use this when a user logs out.
329
+ *
330
+ * @example
331
+ * ```typescript
332
+ * feedhog.reset();
333
+ * ```
334
+ */
335
+ reset(): void;
336
+ }
337
+
338
+ export { type CurrentUser, type FeedbackDetail, type FeedbackListItem, type FeedbackStatus, type FeedbackType, Feedhog, FeedhogApiError, type FeedhogConfig, type IdentifiedUser, type ListFeedbackOptions, type PaginatedResponse, type SortBy, type SubmitFeedbackInput, type UserIdentity, type VoteResult, Feedhog as default };
@@ -0,0 +1,338 @@
1
+ /**
2
+ * Feedhog SDK Types
3
+ * These types mirror the API response types from the Feedhog server.
4
+ */
5
+ type FeedbackType = "bug" | "idea" | "question" | "other";
6
+ type FeedbackStatus = "new" | "under-review" | "planned" | "in-progress" | "completed" | "closed";
7
+ type SortBy = "newest" | "oldest" | "votes" | "comments";
8
+ /**
9
+ * SDK Configuration
10
+ */
11
+ interface FeedhogConfig {
12
+ /** Public API key (starts with fhpk_) */
13
+ apiKey: string;
14
+ /** Base URL for the API (defaults to https://feedhog.com) */
15
+ baseUrl?: string;
16
+ }
17
+ /**
18
+ * User identification data
19
+ */
20
+ interface UserIdentity {
21
+ /** Your system's unique user ID */
22
+ externalId: string;
23
+ /** User's email address */
24
+ email?: string;
25
+ /** User's display name */
26
+ name?: string;
27
+ /** URL to user's avatar image */
28
+ avatarUrl?: string;
29
+ /** Additional metadata to associate with the user */
30
+ metadata?: Record<string, unknown>;
31
+ }
32
+ /**
33
+ * Feedback submission input
34
+ */
35
+ interface SubmitFeedbackInput {
36
+ /** Feedback title (required) */
37
+ title: string;
38
+ /** Detailed description */
39
+ description?: string;
40
+ /** Type of feedback */
41
+ type?: FeedbackType;
42
+ /** Additional metadata */
43
+ metadata?: Record<string, unknown>;
44
+ }
45
+ /**
46
+ * Options for listing feedback
47
+ */
48
+ interface ListFeedbackOptions {
49
+ /** Filter by status(es) */
50
+ status?: FeedbackStatus | FeedbackStatus[];
51
+ /** Filter by type(s) */
52
+ type?: FeedbackType | FeedbackType[];
53
+ /** Search query */
54
+ search?: string;
55
+ /** Sort order */
56
+ sortBy?: SortBy;
57
+ /** Page number (1-indexed) */
58
+ page?: number;
59
+ /** Items per page (max 100) */
60
+ limit?: number;
61
+ }
62
+ /**
63
+ * Feedback author info (public)
64
+ */
65
+ interface FeedbackAuthor {
66
+ name: string | null;
67
+ avatarUrl: string | null;
68
+ }
69
+ /**
70
+ * Comment author info (public)
71
+ */
72
+ interface CommentAuthor {
73
+ name: string | null;
74
+ avatarUrl?: string | null;
75
+ isTeam?: boolean;
76
+ }
77
+ /**
78
+ * Public comment on feedback
79
+ */
80
+ interface FeedbackComment {
81
+ id: string;
82
+ content: string;
83
+ createdAt: string;
84
+ author: CommentAuthor | null;
85
+ }
86
+ /**
87
+ * Feedback item from list endpoint
88
+ */
89
+ interface FeedbackListItem {
90
+ id: string;
91
+ title: string;
92
+ description: string | null;
93
+ type: FeedbackType;
94
+ status: FeedbackStatus;
95
+ voteCount: number;
96
+ commentCount: number;
97
+ createdAt: string;
98
+ endUser: FeedbackAuthor | null;
99
+ }
100
+ /**
101
+ * Feedback item with full details
102
+ */
103
+ interface FeedbackDetail extends FeedbackListItem {
104
+ userHasVoted: boolean;
105
+ comments: FeedbackComment[];
106
+ }
107
+ /**
108
+ * Paginated response
109
+ */
110
+ interface PaginatedResponse<T> {
111
+ items: T[];
112
+ total: number;
113
+ page: number;
114
+ limit: number;
115
+ totalPages: number;
116
+ }
117
+ /**
118
+ * Vote result
119
+ */
120
+ interface VoteResult {
121
+ voted: boolean;
122
+ voteCount: number;
123
+ }
124
+ /**
125
+ * Identified user response
126
+ */
127
+ interface IdentifiedUser {
128
+ id: string;
129
+ email: string | null;
130
+ name: string | null;
131
+ avatarUrl: string | null;
132
+ createdAt: string;
133
+ }
134
+ /**
135
+ * Internal: Current user state
136
+ */
137
+ interface CurrentUser extends UserIdentity {
138
+ identified: boolean;
139
+ }
140
+
141
+ /**
142
+ * Feedhog API Client
143
+ * Handles all HTTP communication with the Feedhog API.
144
+ */
145
+
146
+ /**
147
+ * API Error with status code and optional validation details
148
+ */
149
+ declare class FeedhogApiError extends Error {
150
+ readonly status: number;
151
+ readonly details?: {
152
+ formErrors: string[];
153
+ fieldErrors: Record<string, string[]>;
154
+ } | undefined;
155
+ constructor(message: string, status: number, details?: {
156
+ formErrors: string[];
157
+ fieldErrors: Record<string, string[]>;
158
+ } | undefined);
159
+ }
160
+
161
+ /**
162
+ * Simple event emitter for SDK events
163
+ */
164
+ declare class EventEmitter<Events extends {
165
+ [key: string]: unknown;
166
+ }> {
167
+ private listeners;
168
+ on<K extends keyof Events>(event: K, callback: (data: Events[K]) => void): () => void;
169
+ emit<K extends keyof Events>(event: K, data: Events[K]): void;
170
+ off<K extends keyof Events>(event: K, callback: (data: Events[K]) => void): void;
171
+ }
172
+
173
+ /**
174
+ * Feedhog JavaScript SDK
175
+ *
176
+ * Collect user feedback from any website or application.
177
+ *
178
+ * @example
179
+ * ```typescript
180
+ * import Feedhog from '@feedhog/js';
181
+ *
182
+ * const feedhog = new Feedhog({ apiKey: 'fhpk_xxx' });
183
+ *
184
+ * // Identify the current user (optional but recommended)
185
+ * feedhog.identify({
186
+ * externalId: 'user-123',
187
+ * email: 'user@example.com',
188
+ * name: 'John Doe'
189
+ * });
190
+ *
191
+ * // Submit feedback
192
+ * await feedhog.submit({
193
+ * title: 'Add dark mode',
194
+ * description: 'Would love a dark theme option',
195
+ * type: 'idea'
196
+ * });
197
+ * ```
198
+ */
199
+
200
+ interface FeedhogEvents {
201
+ [key: string]: unknown;
202
+ identify: IdentifiedUser;
203
+ submit: FeedbackListItem;
204
+ vote: {
205
+ feedbackId: string;
206
+ result: VoteResult;
207
+ };
208
+ error: Error;
209
+ reset: void;
210
+ }
211
+ /**
212
+ * Feedhog SDK main class
213
+ */
214
+ declare class Feedhog extends EventEmitter<FeedhogEvents> {
215
+ private readonly client;
216
+ private currentUser;
217
+ constructor(config: FeedhogConfig);
218
+ /**
219
+ * Get the currently identified user
220
+ */
221
+ get user(): CurrentUser | null;
222
+ /**
223
+ * Identify the current user
224
+ *
225
+ * This associates feedback and votes with a specific user in your system.
226
+ * User data is persisted in localStorage for subsequent sessions.
227
+ *
228
+ * @param user - User identity data
229
+ * @returns Promise resolving to the identified user
230
+ *
231
+ * @example
232
+ * ```typescript
233
+ * await feedhog.identify({
234
+ * externalId: 'user-123',
235
+ * email: 'user@example.com',
236
+ * name: 'John Doe',
237
+ * metadata: { plan: 'pro' }
238
+ * });
239
+ * ```
240
+ */
241
+ identify(user: UserIdentity): Promise<IdentifiedUser>;
242
+ /**
243
+ * Submit new feedback
244
+ *
245
+ * If a user has been identified, the feedback will be associated with them.
246
+ *
247
+ * @param input - Feedback data
248
+ * @returns Promise resolving to the created feedback item
249
+ *
250
+ * @example
251
+ * ```typescript
252
+ * const feedback = await feedhog.submit({
253
+ * title: 'Add dark mode',
254
+ * description: 'Would love a dark theme option',
255
+ * type: 'idea'
256
+ * });
257
+ * console.log('Feedback submitted:', feedback.id);
258
+ * ```
259
+ */
260
+ submit(input: SubmitFeedbackInput): Promise<FeedbackListItem>;
261
+ /**
262
+ * List feedback items
263
+ *
264
+ * Returns a paginated list of feedback for the project.
265
+ *
266
+ * @param options - Filter and pagination options
267
+ * @returns Promise resolving to paginated feedback list
268
+ *
269
+ * @example
270
+ * ```typescript
271
+ * // Get all ideas in "planned" status
272
+ * const { items, total } = await feedhog.list({
273
+ * status: ['planned', 'in-progress'],
274
+ * type: 'idea',
275
+ * sortBy: 'votes',
276
+ * limit: 10
277
+ * });
278
+ * ```
279
+ */
280
+ list(options?: ListFeedbackOptions): Promise<PaginatedResponse<FeedbackListItem>>;
281
+ /**
282
+ * Get a single feedback item with full details
283
+ *
284
+ * @param feedbackId - ID of the feedback item
285
+ * @returns Promise resolving to feedback details including comments
286
+ *
287
+ * @example
288
+ * ```typescript
289
+ * const feedback = await feedhog.get('abc123');
290
+ * console.log('Comments:', feedback.comments.length);
291
+ * console.log('Has voted:', feedback.userHasVoted);
292
+ * ```
293
+ */
294
+ get(feedbackId: string): Promise<FeedbackDetail>;
295
+ /**
296
+ * Toggle vote on a feedback item
297
+ *
298
+ * If the user has already voted, this will remove their vote.
299
+ * If they haven't voted, it will add their vote.
300
+ *
301
+ * @param feedbackId - ID of the feedback item to vote on
302
+ * @returns Promise resolving to vote result
303
+ *
304
+ * @example
305
+ * ```typescript
306
+ * const { voted, voteCount } = await feedhog.vote('abc123');
307
+ * console.log(voted ? 'Vote added' : 'Vote removed');
308
+ * console.log('Total votes:', voteCount);
309
+ * ```
310
+ */
311
+ vote(feedbackId: string): Promise<VoteResult>;
312
+ /**
313
+ * Check if the current user has voted on a feedback item
314
+ *
315
+ * @param feedbackId - ID of the feedback item
316
+ * @returns Promise resolving to vote status
317
+ *
318
+ * @example
319
+ * ```typescript
320
+ * const { voted, voteCount } = await feedhog.hasVoted('abc123');
321
+ * ```
322
+ */
323
+ hasVoted(feedbackId: string): Promise<VoteResult>;
324
+ /**
325
+ * Reset the SDK state
326
+ *
327
+ * Clears the current user and removes stored data.
328
+ * Use this when a user logs out.
329
+ *
330
+ * @example
331
+ * ```typescript
332
+ * feedhog.reset();
333
+ * ```
334
+ */
335
+ reset(): void;
336
+ }
337
+
338
+ export { type CurrentUser, type FeedbackDetail, type FeedbackListItem, type FeedbackStatus, type FeedbackType, Feedhog, FeedhogApiError, type FeedhogConfig, type IdentifiedUser, type ListFeedbackOptions, type PaginatedResponse, type SortBy, type SubmitFeedbackInput, type UserIdentity, type VoteResult, Feedhog as default };