feedbackbasket-cli 0.3.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.
Files changed (63) hide show
  1. package/README.md +215 -0
  2. package/dist/bin/feedbackbasket.d.ts +2 -0
  3. package/dist/bin/feedbackbasket.js +3 -0
  4. package/dist/src/auth/login.d.ts +6 -0
  5. package/dist/src/auth/login.js +111 -0
  6. package/dist/src/auth/manager.d.ts +11 -0
  7. package/dist/src/auth/manager.js +38 -0
  8. package/dist/src/cli.d.ts +1 -0
  9. package/dist/src/cli.js +79 -0
  10. package/dist/src/client.d.ts +105 -0
  11. package/dist/src/client.js +133 -0
  12. package/dist/src/commands/auth.d.ts +5 -0
  13. package/dist/src/commands/auth.js +313 -0
  14. package/dist/src/commands/bugs.d.ts +3 -0
  15. package/dist/src/commands/bugs.js +120 -0
  16. package/dist/src/commands/doctor.d.ts +3 -0
  17. package/dist/src/commands/doctor.js +130 -0
  18. package/dist/src/commands/feedback-bulk-update.d.ts +3 -0
  19. package/dist/src/commands/feedback-bulk-update.js +39 -0
  20. package/dist/src/commands/feedback-delete.d.ts +3 -0
  21. package/dist/src/commands/feedback-delete.js +45 -0
  22. package/dist/src/commands/feedback-export.d.ts +3 -0
  23. package/dist/src/commands/feedback-export.js +43 -0
  24. package/dist/src/commands/feedback-note.d.ts +3 -0
  25. package/dist/src/commands/feedback-note.js +41 -0
  26. package/dist/src/commands/feedback-update.d.ts +3 -0
  27. package/dist/src/commands/feedback-update.js +54 -0
  28. package/dist/src/commands/feedback.d.ts +3 -0
  29. package/dist/src/commands/feedback.js +201 -0
  30. package/dist/src/commands/projects.d.ts +3 -0
  31. package/dist/src/commands/projects.js +218 -0
  32. package/dist/src/commands/setup.d.ts +3 -0
  33. package/dist/src/commands/setup.js +90 -0
  34. package/dist/src/commands/team.d.ts +3 -0
  35. package/dist/src/commands/team.js +112 -0
  36. package/dist/src/commands/widget.d.ts +3 -0
  37. package/dist/src/commands/widget.js +153 -0
  38. package/dist/src/config/config.d.ts +10 -0
  39. package/dist/src/config/config.js +41 -0
  40. package/dist/src/config/credentials.d.ts +12 -0
  41. package/dist/src/config/credentials.js +39 -0
  42. package/dist/src/output/codes.d.ts +16 -0
  43. package/dist/src/output/codes.js +29 -0
  44. package/dist/src/output/envelope.d.ts +24 -0
  45. package/dist/src/output/envelope.js +2 -0
  46. package/dist/src/output/errors.d.ts +13 -0
  47. package/dist/src/output/errors.js +37 -0
  48. package/dist/src/output/styled.d.ts +4 -0
  49. package/dist/src/output/styled.js +78 -0
  50. package/dist/src/output/theme.d.ts +25 -0
  51. package/dist/src/output/theme.js +43 -0
  52. package/dist/src/output/writer.d.ts +23 -0
  53. package/dist/src/output/writer.js +109 -0
  54. package/dist/src/prompt.d.ts +3 -0
  55. package/dist/src/prompt.js +32 -0
  56. package/dist/src/resolve.d.ts +9 -0
  57. package/dist/src/resolve.js +70 -0
  58. package/dist/src/types.d.ts +100 -0
  59. package/dist/src/types.js +2 -0
  60. package/dist/src/version.d.ts +2 -0
  61. package/dist/src/version.js +2 -0
  62. package/package.json +49 -0
  63. package/skills/feedbackbasket/SKILL.md +132 -0
package/README.md ADDED
@@ -0,0 +1,215 @@
1
+ # FeedbackBasket CLI
2
+
3
+ Command-line interface for [FeedbackBasket](https://feedbackbasket.com) — manage feedback, bug reports, projects, and widgets from your terminal or through AI agents.
4
+
5
+ Inspired by the [Basecamp CLI](https://github.com/basecamp/basecamp-cli). Everything you can do in the dashboard, you can do from the CLI.
6
+
7
+ ## Quick Start
8
+
9
+ ```bash
10
+ # Install
11
+ npm install -g feedbackbasket-cli
12
+
13
+ # Authenticate (opens browser, full access by default)
14
+ feedbackbasket login
15
+
16
+ # Or use a token directly (for CI/headless)
17
+ feedbackbasket login --token fb_cli_your_token_here
18
+
19
+ # Start exploring
20
+ feedbackbasket projects list
21
+ feedbackbasket feedback list
22
+ feedbackbasket bugs list --severity high
23
+ ```
24
+
25
+ The first time you log in, a setup wizard walks you through selecting a default project and installing the Claude Code skill.
26
+
27
+ ## Agent Usage
28
+
29
+ Any AI agent with shell access (Claude Code, Codex, Cursor, OpenCode) can use the CLI directly:
30
+
31
+ ```bash
32
+ # Agents should use --agent flag for raw JSON output
33
+ feedbackbasket projects list --agent
34
+ feedbackbasket feedback list --category BUG --agent
35
+ feedbackbasket feedback update <id> --status PLANNED --agent
36
+ feedbackbasket widget script myproject --agent
37
+ ```
38
+
39
+ ### Install Claude Code Skill
40
+
41
+ ```bash
42
+ feedbackbasket setup claude
43
+ ```
44
+
45
+ ## Commands
46
+
47
+ ### Authentication
48
+
49
+ ```bash
50
+ feedbackbasket login # Browser OAuth flow (alias for auth login)
51
+ feedbackbasket login --token <token> # Manual token (CI/headless)
52
+ feedbackbasket logout # Clear credentials (alias for auth logout)
53
+ feedbackbasket auth status # Show auth state, scope, default project
54
+ feedbackbasket auth token # Print raw token (for scripting/piping)
55
+ ```
56
+
57
+ ### Projects
58
+
59
+ All project commands accept **name or ID** (e.g. `feedbackbasket` or `cmn3c7sgv...`).
60
+
61
+ ```bash
62
+ feedbackbasket projects list # List all projects with stats
63
+ feedbackbasket projects show <name-or-id> # Project details
64
+ feedbackbasket projects create "My App" --url https://... # Create project
65
+ feedbackbasket projects update myapp --name "New Name" # Update project
66
+ feedbackbasket projects delete myapp # Delete (with confirmation)
67
+ ```
68
+
69
+ ### Feedback
70
+
71
+ ```bash
72
+ # Read
73
+ feedbackbasket feedback list # List recent feedback
74
+ feedbackbasket feedback list --project myapp # Filter by project
75
+ feedbackbasket feedback list --category BUG # Filter by category
76
+ feedbackbasket feedback list --status OPEN # Filter by status
77
+ feedbackbasket feedback list --sentiment NEGATIVE # Filter by sentiment
78
+ feedbackbasket feedback list --search "login issue" # Text search
79
+ feedbackbasket feedback show <id> # View single item detail
80
+ feedbackbasket feedback search "crash on mobile" # Search shortcut
81
+
82
+ # Write
83
+ feedbackbasket feedback update <id> --status PLANNED # Update status
84
+ feedbackbasket feedback update <id> --category BUG # Update category
85
+ feedbackbasket feedback note <id> "Investigating this..." # Add internal note
86
+ feedbackbasket feedback delete <id> # Delete feedback
87
+ feedbackbasket feedback bulk-update --status CLOSED --ids id1,id2,id3
88
+
89
+ # Export
90
+ feedbackbasket feedback export myapp --format csv # Export to CSV
91
+ feedbackbasket feedback export myapp --format md # Export to Markdown
92
+ feedbackbasket feedback export myapp --format json # Export to JSON
93
+ ```
94
+
95
+ ### Bug Reports
96
+
97
+ ```bash
98
+ feedbackbasket bugs list # All bugs
99
+ feedbackbasket bugs list --severity high # High severity only
100
+ feedbackbasket bugs list --status OPEN # Open bugs
101
+ feedbackbasket bugs stats # Bug statistics summary
102
+ feedbackbasket bugs stats --project myapp # Per-project stats
103
+ ```
104
+
105
+ ### Widget
106
+
107
+ ```bash
108
+ # View current settings
109
+ feedbackbasket widget settings myapp
110
+
111
+ # Update widget configuration
112
+ feedbackbasket widget settings myapp --color "#22c55e" --label "Send Feedback"
113
+ feedbackbasket widget settings myapp --position bottom-left --display modal
114
+ feedbackbasket widget settings myapp --email-required --intro "How can we improve?"
115
+
116
+ # Get embed code (ready to paste into your HTML)
117
+ feedbackbasket widget script myapp
118
+ ```
119
+
120
+ ### Team
121
+
122
+ ```bash
123
+ feedbackbasket team list # List organization members
124
+ feedbackbasket team role <memberId> --role admin # Update member role
125
+ feedbackbasket team remove <memberId> # Remove member
126
+ ```
127
+
128
+ ### Utilities
129
+
130
+ ```bash
131
+ feedbackbasket doctor # Run diagnostics (auth, connectivity, integrations)
132
+ feedbackbasket setup claude # Install Claude Code skill
133
+ ```
134
+
135
+ ## Output Modes
136
+
137
+ The CLI automatically detects your environment:
138
+
139
+ | Context | Behavior |
140
+ |---------|----------|
141
+ | **Terminal (TTY)** | Styled, human-readable output with FeedbackBasket brand colors |
142
+ | **Piped** | JSON output automatically |
143
+ | `--json` | Full JSON envelope with breadcrumbs |
144
+ | `--quiet` / `--agent` | Raw JSON data only (no envelope) |
145
+ | `--md` | Markdown formatted |
146
+
147
+ ### JSON Envelope
148
+
149
+ ```json
150
+ {
151
+ "ok": true,
152
+ "data": [...],
153
+ "summary": "12 open bugs, 3 high severity",
154
+ "breadcrumbs": [
155
+ { "action": "View high severity", "cmd": "feedbackbasket bugs list --severity high" }
156
+ ]
157
+ }
158
+ ```
159
+
160
+ Breadcrumbs suggest the next logical command — useful for both humans and agents navigating without a full command catalog.
161
+
162
+ ## Configuration
163
+
164
+ Credentials stored in `~/.config/feedbackbasket/credentials.json`. Config in `~/.config/feedbackbasket/config.json`.
165
+
166
+ ### Default Project
167
+
168
+ Set during the login wizard, or manually:
169
+
170
+ ```bash
171
+ # Commands auto-scope to your default project
172
+ feedbackbasket feedback list # uses default project
173
+ feedbackbasket feedback list --project other-app # override
174
+ ```
175
+
176
+ ### Environment Variables
177
+
178
+ | Variable | Description |
179
+ |----------|-------------|
180
+ | `FEEDBACKBASKET_TOKEN` | CLI token (bypasses stored credentials) |
181
+ | `FEEDBACKBASKET_BASE_URL` | API base URL override |
182
+
183
+ ### Global Flags
184
+
185
+ | Flag | Description |
186
+ |------|-------------|
187
+ | `--json` | Full JSON envelope output |
188
+ | `--quiet` / `--agent` | Raw JSON data only |
189
+ | `--md` | Markdown output |
190
+ | `--base-url <url>` | Override API base URL |
191
+
192
+ ## Filter Options
193
+
194
+ | Type | Values |
195
+ |------|--------|
196
+ | **Categories** | `BUG`, `FEATURE_REQUEST`, `IMPROVEMENT`, `QUESTION` |
197
+ | **Statuses** | `OPEN`, `UNDER_REVIEW`, `PLANNED`, `IN_PROGRESS`, `COMPLETE`, `CLOSED` |
198
+ | **Sentiments** | `POSITIVE`, `NEGATIVE`, `NEUTRAL` |
199
+ | **Bug Severity** | `high`, `medium`, `low` |
200
+
201
+ ## Development
202
+
203
+ ```bash
204
+ git clone https://github.com/deifos/feedbackbasket-cli.git
205
+ cd feedbackbasket-cli
206
+ npm install
207
+ npm run dev -- --help # Run in development
208
+ npm run build # Build for production
209
+ npm run dev -- login # Test login flow
210
+ npm run dev -- doctor # Test diagnostics
211
+ ```
212
+
213
+ ## License
214
+
215
+ MIT
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ import { run } from '../src/cli.js';
3
+ run();
@@ -0,0 +1,6 @@
1
+ interface LoginResult {
2
+ token: string;
3
+ scope: 'read' | 'full';
4
+ }
5
+ export declare function browserLogin(baseUrl: string, scope?: 'read' | 'full'): Promise<LoginResult>;
6
+ export {};
@@ -0,0 +1,111 @@
1
+ import { createServer } from 'node:http';
2
+ import { randomUUID } from 'node:crypto';
3
+ import { URL } from 'node:url';
4
+ import open from 'open';
5
+ import { brand, logo } from '../output/theme.js';
6
+ const TIMEOUT_MS = 120_000;
7
+ const SUCCESS_HTML = `<!DOCTYPE html>
8
+ <html><head><title>FeedbackBasket CLI</title>
9
+ <style>
10
+ body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
11
+ display: flex; align-items: center; justify-content: center; min-height: 100vh;
12
+ margin: 0; background: #0a0a0a; color: #fafafa; }
13
+ .card { text-align: center; max-width: 400px; padding: 3rem; }
14
+ h1 { color: #22c55e; font-size: 1.5rem; }
15
+ p { color: #a1a1aa; line-height: 1.6; }
16
+ </style></head>
17
+ <body><div class="card">
18
+ <h1>Authenticated!</h1>
19
+ <p>You can close this window and return to your terminal.</p>
20
+ </div></body></html>`;
21
+ const ERROR_HTML = (message) => `<!DOCTYPE html>
22
+ <html><head><title>FeedbackBasket CLI</title>
23
+ <style>
24
+ body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
25
+ display: flex; align-items: center; justify-content: center; min-height: 100vh;
26
+ margin: 0; background: #0a0a0a; color: #fafafa; }
27
+ .card { text-align: center; max-width: 400px; padding: 3rem; }
28
+ h1 { color: #ef4444; font-size: 1.5rem; }
29
+ p { color: #a1a1aa; line-height: 1.6; }
30
+ </style></head>
31
+ <body><div class="card">
32
+ <h1>Authentication Failed</h1>
33
+ <p>${message}</p>
34
+ </div></body></html>`;
35
+ export async function browserLogin(baseUrl, scope = 'read') {
36
+ const state = randomUUID();
37
+ return new Promise((resolve, reject) => {
38
+ const server = createServer((req, res) => {
39
+ const url = new URL(req.url ?? '/', `http://127.0.0.1`);
40
+ if (url.pathname !== '/callback') {
41
+ res.writeHead(404);
42
+ res.end('Not found');
43
+ return;
44
+ }
45
+ const receivedState = url.searchParams.get('state');
46
+ const token = url.searchParams.get('token');
47
+ const error = url.searchParams.get('error');
48
+ // CSRF validation
49
+ if (receivedState !== state) {
50
+ res.writeHead(400, { 'Content-Type': 'text/html' });
51
+ res.end(ERROR_HTML('State mismatch — possible CSRF attack. Please try again.'));
52
+ cleanup();
53
+ reject(new Error('State mismatch during authentication'));
54
+ return;
55
+ }
56
+ // User denied
57
+ if (error) {
58
+ res.writeHead(200, { 'Content-Type': 'text/html' });
59
+ res.end(ERROR_HTML(`Authorization was denied: ${error}`));
60
+ cleanup();
61
+ reject(new Error(`Authorization denied: ${error}`));
62
+ return;
63
+ }
64
+ // Missing token
65
+ if (!token) {
66
+ res.writeHead(400, { 'Content-Type': 'text/html' });
67
+ res.end(ERROR_HTML('No token received. Please try again.'));
68
+ cleanup();
69
+ reject(new Error('No token received in callback'));
70
+ return;
71
+ }
72
+ // Success
73
+ res.writeHead(200, { 'Content-Type': 'text/html' });
74
+ res.end(SUCCESS_HTML);
75
+ cleanup();
76
+ resolve({ token, scope });
77
+ });
78
+ const timeout = setTimeout(() => {
79
+ cleanup();
80
+ reject(new Error('Authentication timed out after 2 minutes'));
81
+ }, TIMEOUT_MS);
82
+ function cleanup() {
83
+ clearTimeout(timeout);
84
+ server.close();
85
+ }
86
+ // Listen on random port on loopback
87
+ server.listen(0, '127.0.0.1', () => {
88
+ const addr = server.address();
89
+ if (!addr || typeof addr === 'string') {
90
+ cleanup();
91
+ reject(new Error('Failed to start local auth server'));
92
+ return;
93
+ }
94
+ const port = addr.port;
95
+ const authorizeUrl = `${baseUrl}/cli/authorize?callback_port=${port}&state=${state}&scope=${scope}`;
96
+ console.log();
97
+ console.log(` ${logo()} CLI`);
98
+ console.log();
99
+ console.log(` ${brand.primary('Opening browser for authentication...')}`);
100
+ console.log();
101
+ console.log(` ${brand.muted('If the browser doesn\'t open, visit:')}`);
102
+ console.log(` ${brand.primary(authorizeUrl)}`);
103
+ console.log();
104
+ console.log(` ${brand.muted('Waiting for authentication...')}`);
105
+ console.log();
106
+ open(authorizeUrl).catch(() => {
107
+ // Browser open failed — user will use the URL manually
108
+ });
109
+ });
110
+ });
111
+ }
@@ -0,0 +1,11 @@
1
+ import { type Credentials } from '../config/credentials.js';
2
+ export declare class AuthManager {
3
+ private credentials;
4
+ private loaded;
5
+ resolveToken(): string | null;
6
+ isAuthenticated(): boolean;
7
+ getCredentials(): Credentials | null;
8
+ getTokenPreview(): string | null;
9
+ getSource(): 'env' | 'file' | null;
10
+ logout(): void;
11
+ }
@@ -0,0 +1,38 @@
1
+ import { loadCredentials, clearCredentials, maskToken } from '../config/credentials.js';
2
+ export class AuthManager {
3
+ credentials = null;
4
+ loaded = false;
5
+ resolveToken() {
6
+ const creds = this.getCredentials();
7
+ return creds?.token ?? null;
8
+ }
9
+ isAuthenticated() {
10
+ return this.resolveToken() !== null;
11
+ }
12
+ getCredentials() {
13
+ if (!this.loaded) {
14
+ this.credentials = loadCredentials();
15
+ this.loaded = true;
16
+ }
17
+ return this.credentials;
18
+ }
19
+ getTokenPreview() {
20
+ const creds = this.getCredentials();
21
+ if (!creds)
22
+ return null;
23
+ return maskToken(creds.token);
24
+ }
25
+ getSource() {
26
+ if (process.env['FEEDBACKBASKET_TOKEN'])
27
+ return 'env';
28
+ const creds = this.getCredentials();
29
+ if (creds)
30
+ return 'file';
31
+ return null;
32
+ }
33
+ logout() {
34
+ clearCredentials();
35
+ this.credentials = null;
36
+ this.loaded = false;
37
+ }
38
+ }
@@ -0,0 +1 @@
1
+ export declare function run(): void;
@@ -0,0 +1,79 @@
1
+ import { Command } from 'commander';
2
+ import { VERSION } from './version.js';
3
+ import { OutputWriter, Format } from './output/writer.js';
4
+ import { CLIError } from './output/errors.js';
5
+ import { setBaseUrlOverride } from './config/config.js';
6
+ import { createAuthCommand, createLoginCommand, createLogoutCommand } from './commands/auth.js';
7
+ import { createProjectsCommand } from './commands/projects.js';
8
+ import { createFeedbackCommand } from './commands/feedback.js';
9
+ import { createBugsCommand } from './commands/bugs.js';
10
+ import { createDoctorCommand } from './commands/doctor.js';
11
+ import { createSetupCommand } from './commands/setup.js';
12
+ import { createWidgetCommand } from './commands/widget.js';
13
+ import { createTeamCommand } from './commands/team.js';
14
+ let writer;
15
+ function resolveFormat(opts) {
16
+ if (opts.agent || opts.quiet)
17
+ return Format.Quiet;
18
+ if (opts.json)
19
+ return Format.JSON;
20
+ if (opts.md)
21
+ return Format.Markdown;
22
+ return Format.Auto;
23
+ }
24
+ function getWriter() {
25
+ return writer;
26
+ }
27
+ export function run() {
28
+ const program = new Command('feedbackbasket')
29
+ .version(VERSION, '-v, --version')
30
+ .description('Command-line interface for FeedbackBasket')
31
+ .option('--json', 'Output as JSON envelope')
32
+ .option('--quiet', 'Output raw data only (no envelope)')
33
+ .option('--agent', 'Agent mode (alias for --quiet)')
34
+ .option('--md', 'Output as Markdown')
35
+ .option('--base-url <url>', 'API base URL override')
36
+ .hook('preAction', (thisCommand) => {
37
+ const opts = thisCommand.opts();
38
+ const format = resolveFormat(opts);
39
+ writer = new OutputWriter({ format });
40
+ if (opts.baseUrl) {
41
+ setBaseUrlOverride(opts.baseUrl);
42
+ }
43
+ });
44
+ // Register commands
45
+ program.addCommand(createAuthCommand(getWriter));
46
+ program.addCommand(createLoginCommand(getWriter)); // alias: feedbackbasket login
47
+ program.addCommand(createLogoutCommand(getWriter)); // alias: feedbackbasket logout
48
+ program.addCommand(createProjectsCommand(getWriter));
49
+ program.addCommand(createFeedbackCommand(getWriter));
50
+ program.addCommand(createBugsCommand(getWriter));
51
+ program.addCommand(createWidgetCommand(getWriter));
52
+ program.addCommand(createTeamCommand(getWriter));
53
+ program.addCommand(createDoctorCommand(getWriter));
54
+ program.addCommand(createSetupCommand(getWriter));
55
+ // Global error handler
56
+ program.exitOverride();
57
+ (async () => {
58
+ try {
59
+ await program.parseAsync(process.argv);
60
+ }
61
+ catch (error) {
62
+ if (error instanceof CLIError) {
63
+ if (!writer) {
64
+ writer = new OutputWriter({ format: Format.Auto });
65
+ }
66
+ writer.err(error);
67
+ process.exit(error.exitCode);
68
+ }
69
+ // Commander's own errors (help, version, etc.)
70
+ if (error instanceof Error && 'exitCode' in error) {
71
+ const exitCode = error.exitCode;
72
+ process.exit(exitCode);
73
+ }
74
+ // Unknown errors
75
+ console.error(error instanceof Error ? error.message : String(error));
76
+ process.exit(1);
77
+ }
78
+ })();
79
+ }
@@ -0,0 +1,105 @@
1
+ import type { ProjectsResponse, FeedbackResponse, BugReportsResponse, FeedbackParams, BugReportParams, UserProfile, Project, Feedback } from './types.js';
2
+ export declare class FeedbackBasketClient {
3
+ private http;
4
+ constructor(token: string, baseUrl: string);
5
+ me(): Promise<UserProfile>;
6
+ listProjects(): Promise<ProjectsResponse>;
7
+ getProject(id: string): Promise<Project>;
8
+ createProject(data: {
9
+ name: string;
10
+ url: string;
11
+ description?: string;
12
+ }): Promise<{
13
+ project: Project;
14
+ }>;
15
+ updateProject(id: string, data: {
16
+ name?: string;
17
+ url?: string;
18
+ description?: string;
19
+ }): Promise<Project>;
20
+ deleteProject(id: string): Promise<{
21
+ deleted: boolean;
22
+ id: string;
23
+ name: string;
24
+ }>;
25
+ getFeedback(params?: FeedbackParams): Promise<FeedbackResponse>;
26
+ getFeedbackById(id: string): Promise<Feedback>;
27
+ getBugReports(params?: BugReportParams): Promise<BugReportsResponse>;
28
+ getBugStats(params?: {
29
+ projectId?: string;
30
+ }): Promise<BugReportsResponse['stats']>;
31
+ searchFeedback(query: string, opts?: {
32
+ projectId?: string;
33
+ category?: string;
34
+ limit?: number;
35
+ }): Promise<FeedbackResponse>;
36
+ getWidgetSettings(projectId: string): Promise<{
37
+ projectId: string;
38
+ projectName: string;
39
+ settings: Record<string, unknown>;
40
+ }>;
41
+ updateWidgetSettings(projectId: string, settings: Record<string, unknown>): Promise<{
42
+ projectId: string;
43
+ projectName: string;
44
+ settings: Record<string, unknown>;
45
+ }>;
46
+ getWidgetScript(projectId: string): Promise<{
47
+ projectId: string;
48
+ projectName: string;
49
+ embedCode: string;
50
+ scriptUrl: string;
51
+ }>;
52
+ updateFeedback(id: string, data: {
53
+ status?: string;
54
+ category?: string;
55
+ sentiment?: string;
56
+ }): Promise<Feedback>;
57
+ createNote(feedbackId: string, content: string): Promise<{
58
+ id: string;
59
+ content: string;
60
+ createdAt: string;
61
+ }>;
62
+ deleteFeedback(id: string): Promise<{
63
+ deleted: boolean;
64
+ id: string;
65
+ }>;
66
+ bulkUpdateStatus(ids: string[], status: string): Promise<{
67
+ updated: number;
68
+ status: string;
69
+ }>;
70
+ updateNote(feedbackId: string, noteId: string, content: string): Promise<{
71
+ id: string;
72
+ content: string;
73
+ createdAt: string;
74
+ }>;
75
+ deleteNote(feedbackId: string, noteId: string): Promise<{
76
+ deleted: boolean;
77
+ id: string;
78
+ }>;
79
+ exportFeedback(projectId: string, format?: 'csv' | 'md' | 'json'): Promise<string>;
80
+ listTeam(): Promise<{
81
+ members: Array<{
82
+ memberId: string;
83
+ userId: string;
84
+ name: string;
85
+ email: string;
86
+ role: string;
87
+ joinedAt: string;
88
+ }>;
89
+ totalMembers: number;
90
+ }>;
91
+ updateMemberRole(memberId: string, role: string): Promise<{
92
+ memberId: string;
93
+ name: string;
94
+ email: string;
95
+ role: string;
96
+ }>;
97
+ removeMember(memberId: string): Promise<{
98
+ removed: boolean;
99
+ memberId: string;
100
+ name: string;
101
+ email: string;
102
+ }>;
103
+ private request;
104
+ private handleError;
105
+ }