convex-feedback 0.1.3 → 0.1.5

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 (61) hide show
  1. package/README.md +33 -0
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/client/api.d.ts +7 -1
  4. package/dist/client/api.d.ts.map +1 -1
  5. package/dist/client/index.d.ts +1 -1
  6. package/dist/client/index.d.ts.map +1 -1
  7. package/dist/client/index.js +12 -1
  8. package/dist/client/index.js.map +1 -1
  9. package/dist/component/_generated/api.d.ts +4 -0
  10. package/dist/component/_generated/api.d.ts.map +1 -1
  11. package/dist/component/_generated/api.js.map +1 -1
  12. package/dist/component/_generated/component.d.ts +27 -0
  13. package/dist/component/_generated/component.d.ts.map +1 -1
  14. package/dist/component/comments.d.ts +8 -8
  15. package/dist/component/comments.d.ts.map +1 -1
  16. package/dist/component/comments.js +2 -1
  17. package/dist/component/comments.js.map +1 -1
  18. package/dist/component/crons.d.ts +3 -0
  19. package/dist/component/crons.d.ts.map +1 -0
  20. package/dist/component/crons.js +8 -0
  21. package/dist/component/crons.js.map +1 -0
  22. package/dist/component/entries.d.ts +53 -26
  23. package/dist/component/entries.d.ts.map +1 -1
  24. package/dist/component/entries.js +116 -9
  25. package/dist/component/entries.js.map +1 -1
  26. package/dist/component/helpers.d.ts +2 -1
  27. package/dist/component/helpers.d.ts.map +1 -1
  28. package/dist/component/helpers.js +46 -1
  29. package/dist/component/helpers.js.map +1 -1
  30. package/dist/component/migrations.d.ts +11 -0
  31. package/dist/component/migrations.d.ts.map +1 -0
  32. package/dist/component/migrations.js +35 -0
  33. package/dist/component/migrations.js.map +1 -0
  34. package/dist/component/model.d.ts +74 -3
  35. package/dist/component/model.d.ts.map +1 -1
  36. package/dist/component/model.js +11 -0
  37. package/dist/component/model.js.map +1 -1
  38. package/dist/component/schema.d.ts +19 -2
  39. package/dist/component/schema.d.ts.map +1 -1
  40. package/dist/component/schema.js +12 -2
  41. package/dist/component/schema.js.map +1 -1
  42. package/dist/react/index.d.ts +27 -3
  43. package/dist/react/index.d.ts.map +1 -1
  44. package/dist/react/index.js +6 -0
  45. package/dist/react/index.js.map +1 -1
  46. package/dist/test.d.ts +19 -2
  47. package/dist/test.d.ts.map +1 -1
  48. package/package.json +6 -2
  49. package/src/client/api.ts +11 -0
  50. package/src/client/index.ts +16 -0
  51. package/src/component/README.md +2 -0
  52. package/src/component/_generated/api.ts +4 -0
  53. package/src/component/_generated/component.ts +31 -1
  54. package/src/component/comments.ts +2 -0
  55. package/src/component/crons.ts +16 -0
  56. package/src/component/entries.ts +158 -7
  57. package/src/component/helpers.ts +70 -0
  58. package/src/component/migrations.ts +44 -0
  59. package/src/component/model.ts +44 -0
  60. package/src/component/schema.ts +17 -2
  61. package/src/react/index.ts +13 -0
@@ -16,6 +16,11 @@ export const entryStatusValidator = v.union(
16
16
  v.literal("closed"),
17
17
  );
18
18
 
19
+ export const entryStatusFilterValidator = v.union(
20
+ v.literal("open"),
21
+ v.literal("closed"),
22
+ );
23
+
19
24
  export const entrySortValidator = v.union(
20
25
  v.literal("top"),
21
26
  v.literal("newest"),
@@ -32,6 +37,22 @@ export const actorValidator = v.object({
32
37
  isModerator: v.boolean(),
33
38
  });
34
39
 
40
+ export const feedbackMetadataValueValidator = v.union(
41
+ v.string(),
42
+ v.number(),
43
+ v.boolean(),
44
+ );
45
+
46
+ export const feedbackMetadataRecordValidator = v.record(
47
+ v.string(),
48
+ feedbackMetadataValueValidator,
49
+ );
50
+
51
+ export const feedbackMetadataValidator = v.object({
52
+ standard: v.optional(feedbackMetadataRecordValidator),
53
+ additional: v.optional(feedbackMetadataRecordValidator),
54
+ });
55
+
35
56
  export const publicEntryValidator = v.object({
36
57
  id: v.string(),
37
58
  creationTime: v.number(),
@@ -44,6 +65,7 @@ export const publicEntryValidator = v.object({
44
65
  commentCount: v.number(),
45
66
  updatedAt: v.optional(v.number()),
46
67
  viewerHasUpvoted: v.boolean(),
68
+ metadata: v.optional(feedbackMetadataValidator),
47
69
  });
48
70
 
49
71
  export const publicCommentValidator = v.object({
@@ -83,6 +105,15 @@ export type EntryKind = Infer<typeof entryKindValidator>;
83
105
  */
84
106
  export type EntryStatus = Infer<typeof entryStatusValidator>;
85
107
 
108
+ /** Coarse status bucket used by the indexed board and search filters. */
109
+ export type EntryStatusFilter = Infer<typeof entryStatusFilterValidator>;
110
+
111
+ export function entryStatusFilterForStatus(
112
+ status: EntryStatus,
113
+ ): EntryStatusFilter {
114
+ return status === "closed" ? "closed" : "open";
115
+ }
116
+
86
117
  /**
87
118
  * Server-side ordering strategy for feedback entries.
88
119
  *
@@ -119,6 +150,14 @@ export type CommentSort = Infer<typeof commentSortValidator>;
119
150
  */
120
151
  export type FeedbackActor = Infer<typeof actorValidator>;
121
152
 
153
+ /** Scalar value accepted in entry diagnostic metadata. */
154
+ export type FeedbackMetadataValue = Infer<
155
+ typeof feedbackMetadataValueValidator
156
+ >;
157
+
158
+ /** Flat metadata values grouped by their source. */
159
+ export type FeedbackMetadata = Infer<typeof feedbackMetadataValidator>;
160
+
122
161
  /**
123
162
  * Public representation of a feedback, feature-request, or bug-report entry.
124
163
  *
@@ -157,6 +196,11 @@ export type FeedbackActor = Infer<typeof actorValidator>;
157
196
  * @property viewerHasUpvoted
158
197
  * Whether the actor associated with the current query has upvoted the entry.
159
198
  * `false` when no viewer actor is available.
199
+ *
200
+ * @property metadata
201
+ * Creation-time diagnostic metadata. Present only when `getEntry` is queried
202
+ * by a moderator. Ordinary entry lists, searches, and non-moderator reads omit
203
+ * this property.
160
204
  */
161
205
  export type FeedbackEntry = Infer<typeof publicEntryValidator>;
162
206
 
@@ -1,13 +1,19 @@
1
1
  import { defineSchema, defineTable } from "convex/server";
2
2
  import { v } from "convex/values";
3
3
 
4
- import { entryKindValidator, entryStatusValidator } from "./model.js";
4
+ import {
5
+ entryKindValidator,
6
+ entryStatusFilterValidator,
7
+ entryStatusValidator,
8
+ feedbackMetadataValidator,
9
+ } from "./model.js";
5
10
 
6
11
  const schema = defineSchema({
7
12
  entries: defineTable({
8
13
  actorId: v.string(),
9
14
  kind: entryKindValidator,
10
15
  status: entryStatusValidator,
16
+ statusFilter: v.optional(entryStatusFilterValidator),
11
17
  title: v.string(),
12
18
  body: v.string(),
13
19
  normalizedTitle: v.string(),
@@ -15,19 +21,28 @@ const schema = defineSchema({
15
21
  upvoteCount: v.number(),
16
22
  commentCount: v.number(),
17
23
  updatedAt: v.optional(v.number()),
24
+ metadata: v.optional(feedbackMetadataValidator),
18
25
  })
19
26
  .index("by_kind", ["kind"])
20
27
  .index("by_status", ["status"])
21
28
  .index("by_kind_status", ["kind", "status"])
29
+ .index("by_status_filter", ["statusFilter"])
30
+ .index("by_kind_status_filter", ["kind", "statusFilter"])
22
31
  .index("by_upvotes", ["upvoteCount"])
23
32
  .index("by_kind_upvotes", ["kind", "upvoteCount"])
24
33
  .index("by_status_upvotes", ["status", "upvoteCount"])
25
34
  .index("by_kind_status_upvotes", ["kind", "status", "upvoteCount"])
35
+ .index("by_status_filter_upvotes", ["statusFilter", "upvoteCount"])
36
+ .index("by_kind_status_filter_upvotes", [
37
+ "kind",
38
+ "statusFilter",
39
+ "upvoteCount",
40
+ ])
26
41
  .index("by_normalized_title", ["normalizedTitle"])
27
42
  .index("by_kind_normalized_title", ["kind", "normalizedTitle"])
28
43
  .searchIndex("search", {
29
44
  searchField: "searchText",
30
- filterFields: ["kind", "status"],
45
+ filterFields: ["kind", "status", "statusFilter"],
31
46
  }),
32
47
 
33
48
  comments: defineTable({
@@ -9,6 +9,7 @@ import type {
9
9
  EntryKind,
10
10
  EntrySort,
11
11
  EntryStatus,
12
+ EntryStatusFilter,
12
13
  SimilarEntriesResult,
13
14
  } from "../component/model.js";
14
15
 
@@ -61,6 +62,9 @@ export interface UseEntriesArgs {
61
62
  /** Optional workflow-status filter. */
62
63
  status?: EntryStatus;
63
64
 
65
+ /** Optional indexed open or closed board bucket. */
66
+ statusFilter?: EntryStatusFilter;
67
+
64
68
  /**
65
69
  * Server-side entry ordering.
66
70
  *
@@ -120,6 +124,9 @@ export interface SearchEntriesArgs {
120
124
  /** Optional workflow-status filter. */
121
125
  status?: EntryStatus;
122
126
 
127
+ /** Optional indexed open or closed board bucket. */
128
+ statusFilter?: EntryStatusFilter;
129
+
123
130
  /**
124
131
  * Maximum number of results requested.
125
132
  *
@@ -212,6 +219,9 @@ function createFeedbackHooksImplementation<RateLimitResult>(
212
219
  const queryArgs = {
213
220
  ...(args.kinds === undefined ? {} : { kinds: [...args.kinds] }),
214
221
  ...(args.status === undefined ? {} : { status: args.status }),
222
+ ...(args.statusFilter === undefined
223
+ ? {}
224
+ : { statusFilter: args.statusFilter }),
215
225
  ...(args.sort === undefined ? {} : { sort: args.sort }),
216
226
  };
217
227
 
@@ -244,6 +254,9 @@ function createFeedbackHooksImplementation<RateLimitResult>(
244
254
  searchQuery,
245
255
  ...(args.kinds === undefined ? {} : { kinds: [...args.kinds] }),
246
256
  ...(args.status === undefined ? {} : { status: args.status }),
257
+ ...(args.statusFilter === undefined
258
+ ? {}
259
+ : { statusFilter: args.statusFilter }),
247
260
  ...(args.limit === undefined ? {} : { limit: args.limit }),
248
261
  };
249
262