@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.
Files changed (78) hide show
  1. package/LICENSE +177 -0
  2. package/README.md +382 -0
  3. package/dist/convex/agents/bugReportAgent.d.ts +30 -0
  4. package/dist/convex/agents/bugReportAgent.d.ts.map +1 -0
  5. package/dist/convex/agents/bugReportAgent.js +243 -0
  6. package/dist/convex/agents/bugReportAgent.js.map +1 -0
  7. package/dist/convex/agents/feedbackAgent.d.ts +29 -0
  8. package/dist/convex/agents/feedbackAgent.d.ts.map +1 -0
  9. package/dist/convex/agents/feedbackAgent.js +232 -0
  10. package/dist/convex/agents/feedbackAgent.js.map +1 -0
  11. package/dist/convex/bugReports.d.ts +49 -0
  12. package/dist/convex/bugReports.d.ts.map +1 -0
  13. package/dist/convex/bugReports.js +321 -0
  14. package/dist/convex/bugReports.js.map +1 -0
  15. package/dist/convex/convex.config.d.ts +3 -0
  16. package/dist/convex/convex.config.d.ts.map +1 -0
  17. package/dist/convex/convex.config.js +6 -0
  18. package/dist/convex/convex.config.js.map +1 -0
  19. package/dist/convex/emails/bugReportEmails.d.ts +16 -0
  20. package/dist/convex/emails/bugReportEmails.d.ts.map +1 -0
  21. package/dist/convex/emails/bugReportEmails.js +403 -0
  22. package/dist/convex/emails/bugReportEmails.js.map +1 -0
  23. package/dist/convex/emails/feedbackEmails.d.ts +16 -0
  24. package/dist/convex/emails/feedbackEmails.d.ts.map +1 -0
  25. package/dist/convex/emails/feedbackEmails.js +389 -0
  26. package/dist/convex/emails/feedbackEmails.js.map +1 -0
  27. package/dist/convex/feedback.d.ts +49 -0
  28. package/dist/convex/feedback.d.ts.map +1 -0
  29. package/dist/convex/feedback.js +327 -0
  30. package/dist/convex/feedback.js.map +1 -0
  31. package/dist/convex/index.d.ts +10 -0
  32. package/dist/convex/index.d.ts.map +1 -0
  33. package/dist/convex/index.js +12 -0
  34. package/dist/convex/index.js.map +1 -0
  35. package/dist/convex/schema.d.ts +200 -0
  36. package/dist/convex/schema.d.ts.map +1 -0
  37. package/dist/convex/schema.js +150 -0
  38. package/dist/convex/schema.js.map +1 -0
  39. package/dist/convex/supportTeams.d.ts +29 -0
  40. package/dist/convex/supportTeams.d.ts.map +1 -0
  41. package/dist/convex/supportTeams.js +159 -0
  42. package/dist/convex/supportTeams.js.map +1 -0
  43. package/dist/index.d.ts +70 -0
  44. package/dist/index.d.ts.map +1 -0
  45. package/dist/index.js +63 -0
  46. package/dist/index.js.map +1 -0
  47. package/dist/react/BugReportButton.d.ts +70 -0
  48. package/dist/react/BugReportButton.d.ts.map +1 -0
  49. package/dist/react/BugReportButton.js +371 -0
  50. package/dist/react/BugReportButton.js.map +1 -0
  51. package/dist/react/BugReportContext.d.ts +59 -0
  52. package/dist/react/BugReportContext.d.ts.map +1 -0
  53. package/dist/react/BugReportContext.js +107 -0
  54. package/dist/react/BugReportContext.js.map +1 -0
  55. package/dist/react/index.d.ts +36 -0
  56. package/dist/react/index.d.ts.map +1 -0
  57. package/dist/react/index.js +36 -0
  58. package/dist/react/index.js.map +1 -0
  59. package/dist/types.d.ts +89 -0
  60. package/dist/types.d.ts.map +1 -0
  61. package/dist/types.js +5 -0
  62. package/dist/types.js.map +1 -0
  63. package/package.json +101 -0
  64. package/src/convex/agents/bugReportAgent.ts +277 -0
  65. package/src/convex/agents/feedbackAgent.ts +264 -0
  66. package/src/convex/bugReports.ts +350 -0
  67. package/src/convex/convex.config.ts +7 -0
  68. package/src/convex/emails/bugReportEmails.ts +479 -0
  69. package/src/convex/emails/feedbackEmails.ts +465 -0
  70. package/src/convex/feedback.ts +356 -0
  71. package/src/convex/index.ts +28 -0
  72. package/src/convex/schema.ts +207 -0
  73. package/src/convex/supportTeams.ts +179 -0
  74. package/src/index.ts +77 -0
  75. package/src/react/BugReportButton.tsx +755 -0
  76. package/src/react/BugReportContext.tsx +146 -0
  77. package/src/react/index.ts +46 -0
  78. 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';