@fatagnus/convex-feedback 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.
- package/LICENSE +177 -0
- package/README.md +382 -0
- package/dist/convex/agents/bugReportAgent.d.ts +30 -0
- package/dist/convex/agents/bugReportAgent.d.ts.map +1 -0
- package/dist/convex/agents/bugReportAgent.js +243 -0
- package/dist/convex/agents/bugReportAgent.js.map +1 -0
- package/dist/convex/agents/feedbackAgent.d.ts +29 -0
- package/dist/convex/agents/feedbackAgent.d.ts.map +1 -0
- package/dist/convex/agents/feedbackAgent.js +232 -0
- package/dist/convex/agents/feedbackAgent.js.map +1 -0
- package/dist/convex/bugReports.d.ts +49 -0
- package/dist/convex/bugReports.d.ts.map +1 -0
- package/dist/convex/bugReports.js +321 -0
- package/dist/convex/bugReports.js.map +1 -0
- package/dist/convex/convex.config.d.ts +3 -0
- package/dist/convex/convex.config.d.ts.map +1 -0
- package/dist/convex/convex.config.js +6 -0
- package/dist/convex/convex.config.js.map +1 -0
- package/dist/convex/emails/bugReportEmails.d.ts +16 -0
- package/dist/convex/emails/bugReportEmails.d.ts.map +1 -0
- package/dist/convex/emails/bugReportEmails.js +403 -0
- package/dist/convex/emails/bugReportEmails.js.map +1 -0
- package/dist/convex/emails/feedbackEmails.d.ts +16 -0
- package/dist/convex/emails/feedbackEmails.d.ts.map +1 -0
- package/dist/convex/emails/feedbackEmails.js +389 -0
- package/dist/convex/emails/feedbackEmails.js.map +1 -0
- package/dist/convex/feedback.d.ts +49 -0
- package/dist/convex/feedback.d.ts.map +1 -0
- package/dist/convex/feedback.js +327 -0
- package/dist/convex/feedback.js.map +1 -0
- package/dist/convex/index.d.ts +10 -0
- package/dist/convex/index.d.ts.map +1 -0
- package/dist/convex/index.js +12 -0
- package/dist/convex/index.js.map +1 -0
- package/dist/convex/schema.d.ts +200 -0
- package/dist/convex/schema.d.ts.map +1 -0
- package/dist/convex/schema.js +150 -0
- package/dist/convex/schema.js.map +1 -0
- package/dist/convex/supportTeams.d.ts +29 -0
- package/dist/convex/supportTeams.d.ts.map +1 -0
- package/dist/convex/supportTeams.js +159 -0
- package/dist/convex/supportTeams.js.map +1 -0
- package/dist/index.d.ts +70 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +63 -0
- package/dist/index.js.map +1 -0
- package/dist/react/BugReportButton.d.ts +70 -0
- package/dist/react/BugReportButton.d.ts.map +1 -0
- package/dist/react/BugReportButton.js +371 -0
- package/dist/react/BugReportButton.js.map +1 -0
- package/dist/react/BugReportContext.d.ts +59 -0
- package/dist/react/BugReportContext.d.ts.map +1 -0
- package/dist/react/BugReportContext.js +107 -0
- package/dist/react/BugReportContext.js.map +1 -0
- package/dist/react/index.d.ts +36 -0
- package/dist/react/index.d.ts.map +1 -0
- package/dist/react/index.js +36 -0
- package/dist/react/index.js.map +1 -0
- package/dist/types.d.ts +89 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/package.json +101 -0
- package/src/convex/agents/bugReportAgent.ts +277 -0
- package/src/convex/agents/feedbackAgent.ts +264 -0
- package/src/convex/bugReports.ts +350 -0
- package/src/convex/convex.config.ts +7 -0
- package/src/convex/emails/bugReportEmails.ts +479 -0
- package/src/convex/emails/feedbackEmails.ts +465 -0
- package/src/convex/feedback.ts +356 -0
- package/src/convex/index.ts +28 -0
- package/src/convex/schema.ts +207 -0
- package/src/convex/supportTeams.ts +179 -0
- package/src/index.ts +77 -0
- package/src/react/BugReportButton.tsx +755 -0
- package/src/react/BugReportContext.tsx +146 -0
- package/src/react/index.ts +46 -0
- package/src/types.ts +93 -0
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import { v } from "convex/values";
|
|
2
|
+
import { mutation, query, internalQuery } from "./_generated/server";
|
|
3
|
+
import {
|
|
4
|
+
feedbackTypeValidator,
|
|
5
|
+
bugSeverityValidator,
|
|
6
|
+
} from "./schema";
|
|
7
|
+
|
|
8
|
+
// Return type for support team records
|
|
9
|
+
const supportTeamReturnValidator = v.object({
|
|
10
|
+
_id: v.id("supportTeams"),
|
|
11
|
+
_creationTime: v.number(),
|
|
12
|
+
teamName: v.string(),
|
|
13
|
+
memberEmails: v.array(v.string()),
|
|
14
|
+
feedbackTypes: v.array(feedbackTypeValidator),
|
|
15
|
+
bugReportSeverities: v.array(bugSeverityValidator),
|
|
16
|
+
isActive: v.boolean(),
|
|
17
|
+
createdAt: v.number(),
|
|
18
|
+
updatedAt: v.number(),
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* List all support teams.
|
|
23
|
+
*/
|
|
24
|
+
export const list = query({
|
|
25
|
+
args: {
|
|
26
|
+
activeOnly: v.optional(v.boolean()),
|
|
27
|
+
},
|
|
28
|
+
returns: v.array(supportTeamReturnValidator),
|
|
29
|
+
handler: async (ctx, args) => {
|
|
30
|
+
if (args.activeOnly) {
|
|
31
|
+
return await ctx.db
|
|
32
|
+
.query("supportTeams")
|
|
33
|
+
.withIndex("by_active", (q) => q.eq("isActive", true))
|
|
34
|
+
.collect();
|
|
35
|
+
}
|
|
36
|
+
return await ctx.db.query("supportTeams").collect();
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Get a support team by ID.
|
|
42
|
+
*/
|
|
43
|
+
export const get = query({
|
|
44
|
+
args: {
|
|
45
|
+
teamId: v.id("supportTeams"),
|
|
46
|
+
},
|
|
47
|
+
returns: v.union(supportTeamReturnValidator, v.null()),
|
|
48
|
+
handler: async (ctx, args) => {
|
|
49
|
+
return await ctx.db.get(args.teamId);
|
|
50
|
+
},
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Internal query to find all active teams that handle a given feedback type.
|
|
55
|
+
*/
|
|
56
|
+
export const getTeamsForFeedbackType = internalQuery({
|
|
57
|
+
args: {
|
|
58
|
+
feedbackType: feedbackTypeValidator,
|
|
59
|
+
},
|
|
60
|
+
returns: v.array(supportTeamReturnValidator),
|
|
61
|
+
handler: async (ctx, args) => {
|
|
62
|
+
const allTeams = await ctx.db
|
|
63
|
+
.query("supportTeams")
|
|
64
|
+
.withIndex("by_active", (q) => q.eq("isActive", true))
|
|
65
|
+
.collect();
|
|
66
|
+
|
|
67
|
+
return allTeams.filter((team) =>
|
|
68
|
+
team.feedbackTypes.includes(args.feedbackType)
|
|
69
|
+
);
|
|
70
|
+
},
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Internal query to find all active teams that handle a given bug report severity.
|
|
75
|
+
*/
|
|
76
|
+
export const getTeamsForBugReportSeverity = internalQuery({
|
|
77
|
+
args: {
|
|
78
|
+
severity: bugSeverityValidator,
|
|
79
|
+
},
|
|
80
|
+
returns: v.array(supportTeamReturnValidator),
|
|
81
|
+
handler: async (ctx, args) => {
|
|
82
|
+
const allTeams = await ctx.db
|
|
83
|
+
.query("supportTeams")
|
|
84
|
+
.withIndex("by_active", (q) => q.eq("isActive", true))
|
|
85
|
+
.collect();
|
|
86
|
+
|
|
87
|
+
return allTeams.filter((team) =>
|
|
88
|
+
team.bugReportSeverities.includes(args.severity)
|
|
89
|
+
);
|
|
90
|
+
},
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Create a new support team.
|
|
95
|
+
*/
|
|
96
|
+
export const create = mutation({
|
|
97
|
+
args: {
|
|
98
|
+
teamName: v.string(),
|
|
99
|
+
memberEmails: v.array(v.string()),
|
|
100
|
+
feedbackTypes: v.array(feedbackTypeValidator),
|
|
101
|
+
bugReportSeverities: v.array(bugSeverityValidator),
|
|
102
|
+
},
|
|
103
|
+
returns: v.id("supportTeams"),
|
|
104
|
+
handler: async (ctx, args) => {
|
|
105
|
+
const now = Date.now();
|
|
106
|
+
return await ctx.db.insert("supportTeams", {
|
|
107
|
+
teamName: args.teamName,
|
|
108
|
+
memberEmails: args.memberEmails,
|
|
109
|
+
feedbackTypes: args.feedbackTypes,
|
|
110
|
+
bugReportSeverities: args.bugReportSeverities,
|
|
111
|
+
isActive: true,
|
|
112
|
+
createdAt: now,
|
|
113
|
+
updatedAt: now,
|
|
114
|
+
});
|
|
115
|
+
},
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Update a support team.
|
|
120
|
+
*/
|
|
121
|
+
export const update = mutation({
|
|
122
|
+
args: {
|
|
123
|
+
teamId: v.id("supportTeams"),
|
|
124
|
+
teamName: v.optional(v.string()),
|
|
125
|
+
memberEmails: v.optional(v.array(v.string())),
|
|
126
|
+
feedbackTypes: v.optional(v.array(feedbackTypeValidator)),
|
|
127
|
+
bugReportSeverities: v.optional(v.array(bugSeverityValidator)),
|
|
128
|
+
isActive: v.optional(v.boolean()),
|
|
129
|
+
},
|
|
130
|
+
returns: v.null(),
|
|
131
|
+
handler: async (ctx, args) => {
|
|
132
|
+
const team = await ctx.db.get(args.teamId);
|
|
133
|
+
if (!team) {
|
|
134
|
+
throw new Error("Support team not found");
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const updates: Record<string, unknown> = {
|
|
138
|
+
updatedAt: Date.now(),
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
if (args.teamName !== undefined) {
|
|
142
|
+
updates.teamName = args.teamName;
|
|
143
|
+
}
|
|
144
|
+
if (args.memberEmails !== undefined) {
|
|
145
|
+
updates.memberEmails = args.memberEmails;
|
|
146
|
+
}
|
|
147
|
+
if (args.feedbackTypes !== undefined) {
|
|
148
|
+
updates.feedbackTypes = args.feedbackTypes;
|
|
149
|
+
}
|
|
150
|
+
if (args.bugReportSeverities !== undefined) {
|
|
151
|
+
updates.bugReportSeverities = args.bugReportSeverities;
|
|
152
|
+
}
|
|
153
|
+
if (args.isActive !== undefined) {
|
|
154
|
+
updates.isActive = args.isActive;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
await ctx.db.patch(args.teamId, updates);
|
|
158
|
+
return null;
|
|
159
|
+
},
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Delete a support team.
|
|
164
|
+
*/
|
|
165
|
+
export const remove = mutation({
|
|
166
|
+
args: {
|
|
167
|
+
teamId: v.id("supportTeams"),
|
|
168
|
+
},
|
|
169
|
+
returns: v.null(),
|
|
170
|
+
handler: async (ctx, args) => {
|
|
171
|
+
const team = await ctx.db.get(args.teamId);
|
|
172
|
+
if (!team) {
|
|
173
|
+
throw new Error("Support team not found");
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
await ctx.db.delete(args.teamId);
|
|
177
|
+
return null;
|
|
178
|
+
},
|
|
179
|
+
});
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @convex-dev/feedback
|
|
3
|
+
*
|
|
4
|
+
* Bug reports and feedback collection component for Convex applications.
|
|
5
|
+
*
|
|
6
|
+
* ## Installation
|
|
7
|
+
*
|
|
8
|
+
* ```bash
|
|
9
|
+
* npm install @convex-dev/feedback
|
|
10
|
+
* ```
|
|
11
|
+
*
|
|
12
|
+
* ## Setup
|
|
13
|
+
*
|
|
14
|
+
* 1. Add the component to your `convex/convex.config.ts`:
|
|
15
|
+
*
|
|
16
|
+
* ```typescript
|
|
17
|
+
* import { defineApp } from "convex/server";
|
|
18
|
+
* import feedback from "@convex-dev/feedback/convex.config";
|
|
19
|
+
*
|
|
20
|
+
* const app = defineApp();
|
|
21
|
+
* app.use(feedback);
|
|
22
|
+
* export default app;
|
|
23
|
+
* ```
|
|
24
|
+
*
|
|
25
|
+
* 2. Set required environment variables in your Convex dashboard:
|
|
26
|
+
* - `OPENROUTER_API_KEY` - For AI analysis (optional)
|
|
27
|
+
* - `RESEND_API_KEY` - For email notifications (optional)
|
|
28
|
+
* - `RESEND_FROM_EMAIL` - From address for emails (optional)
|
|
29
|
+
*
|
|
30
|
+
* ## Usage
|
|
31
|
+
*
|
|
32
|
+
* ### Convex Functions
|
|
33
|
+
*
|
|
34
|
+
* The component exposes these functions through `api.feedback`:
|
|
35
|
+
*
|
|
36
|
+
* - `api.feedback.bugReports.create` - Create a bug report
|
|
37
|
+
* - `api.feedback.bugReports.list` - List bug reports
|
|
38
|
+
* - `api.feedback.bugReports.get` - Get a bug report by ID
|
|
39
|
+
* - `api.feedback.bugReports.updateStatus` - Update bug report status
|
|
40
|
+
* - `api.feedback.bugReports.archive` - Archive a bug report
|
|
41
|
+
* - `api.feedback.bugReports.unarchive` - Unarchive a bug report
|
|
42
|
+
*
|
|
43
|
+
* - `api.feedback.feedback.create` - Create feedback
|
|
44
|
+
* - `api.feedback.feedback.list` - List feedback
|
|
45
|
+
* - `api.feedback.feedback.get` - Get feedback by ID
|
|
46
|
+
* - `api.feedback.feedback.updateStatus` - Update feedback status
|
|
47
|
+
*
|
|
48
|
+
* - `api.feedback.supportTeams.list` - List support teams
|
|
49
|
+
* - `api.feedback.supportTeams.create` - Create a support team
|
|
50
|
+
* - `api.feedback.supportTeams.update` - Update a support team
|
|
51
|
+
*
|
|
52
|
+
* ### React Components
|
|
53
|
+
*
|
|
54
|
+
* Import from `@convex-dev/feedback/react`:
|
|
55
|
+
*
|
|
56
|
+
* ```tsx
|
|
57
|
+
* import { BugReportProvider, BugReportButton } from '@convex-dev/feedback/react';
|
|
58
|
+
* ```
|
|
59
|
+
*
|
|
60
|
+
* @module
|
|
61
|
+
*/
|
|
62
|
+
|
|
63
|
+
// Type definitions
|
|
64
|
+
export type BugSeverity = 'low' | 'medium' | 'high' | 'critical';
|
|
65
|
+
export type BugStatus = 'open' | 'in-progress' | 'resolved' | 'closed';
|
|
66
|
+
export type FeedbackType = 'feature_request' | 'change_request' | 'general';
|
|
67
|
+
export type FeedbackPriority = 'nice_to_have' | 'important' | 'critical';
|
|
68
|
+
export type FeedbackStatus = 'open' | 'under_review' | 'planned' | 'in_progress' | 'completed' | 'declined';
|
|
69
|
+
export type ReporterType = 'staff' | 'customer';
|
|
70
|
+
export type Effort = 'low' | 'medium' | 'high';
|
|
71
|
+
|
|
72
|
+
// Export document types
|
|
73
|
+
export type {
|
|
74
|
+
BugReport,
|
|
75
|
+
Feedback,
|
|
76
|
+
SupportTeam,
|
|
77
|
+
} from './types';
|