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 (86) hide show
  1. package/README.md +183 -0
  2. package/dist/.tsbuildinfo +1 -0
  3. package/dist/client/api.d.ts +72 -0
  4. package/dist/client/api.d.ts.map +1 -0
  5. package/dist/client/api.js +2 -0
  6. package/dist/client/api.js.map +1 -0
  7. package/dist/client/config.d.ts +37 -0
  8. package/dist/client/config.d.ts.map +1 -0
  9. package/dist/client/config.js +36 -0
  10. package/dist/client/config.js.map +1 -0
  11. package/dist/client/index.d.ts +186 -0
  12. package/dist/client/index.d.ts.map +1 -0
  13. package/dist/client/index.js +248 -0
  14. package/dist/client/index.js.map +1 -0
  15. package/dist/component/_generated/api.d.ts +42 -0
  16. package/dist/component/_generated/api.d.ts.map +1 -0
  17. package/dist/component/_generated/api.js +31 -0
  18. package/dist/component/_generated/api.js.map +1 -0
  19. package/dist/component/_generated/component.d.ts +233 -0
  20. package/dist/component/_generated/component.d.ts.map +1 -0
  21. package/dist/component/_generated/component.js +11 -0
  22. package/dist/component/_generated/component.js.map +1 -0
  23. package/dist/component/_generated/dataModel.d.ts +46 -0
  24. package/dist/component/_generated/dataModel.d.ts.map +1 -0
  25. package/dist/component/_generated/dataModel.js +11 -0
  26. package/dist/component/_generated/dataModel.js.map +1 -0
  27. package/dist/component/_generated/server.d.ts +133 -0
  28. package/dist/component/_generated/server.d.ts.map +1 -0
  29. package/dist/component/_generated/server.js +80 -0
  30. package/dist/component/_generated/server.js.map +1 -0
  31. package/dist/component/comments.d.ts +68 -0
  32. package/dist/component/comments.d.ts.map +1 -0
  33. package/dist/component/comments.js +206 -0
  34. package/dist/component/comments.js.map +1 -0
  35. package/dist/component/convex.config.d.ts +3 -0
  36. package/dist/component/convex.config.d.ts.map +1 -0
  37. package/dist/component/convex.config.js +3 -0
  38. package/dist/component/convex.config.js.map +1 -0
  39. package/dist/component/entries.d.ts +140 -0
  40. package/dist/component/entries.d.ts.map +1 -0
  41. package/dist/component/entries.js +302 -0
  42. package/dist/component/entries.js.map +1 -0
  43. package/dist/component/helpers.d.ts +10 -0
  44. package/dist/component/helpers.d.ts.map +1 -0
  45. package/dist/component/helpers.js +74 -0
  46. package/dist/component/helpers.js.map +1 -0
  47. package/dist/component/model.d.ts +176 -0
  48. package/dist/component/model.d.ts.map +1 -0
  49. package/dist/component/model.js +41 -0
  50. package/dist/component/model.js.map +1 -0
  51. package/dist/component/schema.d.ts +78 -0
  52. package/dist/component/schema.d.ts.map +1 -0
  53. package/dist/component/schema.js +56 -0
  54. package/dist/component/schema.js.map +1 -0
  55. package/dist/component/types.d.ts +5 -0
  56. package/dist/component/types.d.ts.map +1 -0
  57. package/dist/component/types.js +2 -0
  58. package/dist/component/types.js.map +1 -0
  59. package/dist/react/index.d.ts +169 -0
  60. package/dist/react/index.d.ts.map +1 -0
  61. package/dist/react/index.js +68 -0
  62. package/dist/react/index.js.map +1 -0
  63. package/dist/test.d.ts +88 -0
  64. package/dist/test.d.ts.map +1 -0
  65. package/dist/test.js +9 -0
  66. package/dist/test.js.map +1 -0
  67. package/package.json +63 -0
  68. package/src/client/README.md +11 -0
  69. package/src/client/api.ts +126 -0
  70. package/src/client/config.ts +80 -0
  71. package/src/client/index.ts +338 -0
  72. package/src/component/README.md +13 -0
  73. package/src/component/_generated/api.ts +58 -0
  74. package/src/component/_generated/component.ts +339 -0
  75. package/src/component/_generated/dataModel.ts +60 -0
  76. package/src/component/_generated/server.ts +169 -0
  77. package/src/component/comments.ts +258 -0
  78. package/src/component/convex.config.ts +3 -0
  79. package/src/component/entries.ts +385 -0
  80. package/src/component/helpers.ts +105 -0
  81. package/src/component/model.ts +76 -0
  82. package/src/component/schema.ts +60 -0
  83. package/src/component/types.ts +6 -0
  84. package/src/react/README.md +7 -0
  85. package/src/react/index.ts +140 -0
  86. package/src/test.ts +18 -0
@@ -0,0 +1,11 @@
1
+ # Host client layer
2
+
3
+ This layer is the supported server-side integration boundary between a host Convex app and the component.
4
+
5
+ - Construct the client with `createFeedback(...)` and the generated component reference.
6
+ - Resolve authentication and moderation in the host app. Components do not own host authentication.
7
+ - Keep `actor.id` stable. It is the identity used for authorship, entry upvotes, and comment likes.
8
+ - Configuration is static code configuration; there is no configuration table.
9
+ - Call the returned methods from host queries/mutations instead of exposing component internals directly.
10
+
11
+ Do not add user/profile persistence here. Display profiles belong to the host application.
@@ -0,0 +1,126 @@
1
+ import type {
2
+ FunctionReference,
3
+ PaginationOptions,
4
+ PaginationResult,
5
+ } from "convex/server";
6
+
7
+ import type {
8
+ CommentSort,
9
+ EntryKind,
10
+ EntrySort,
11
+ EntryStatus,
12
+ FeedbackComment,
13
+ FeedbackEntry,
14
+ SimilarEntriesResult,
15
+ } from "../component/model.js";
16
+
17
+ export interface FeedbackPublicApi<
18
+ Name extends string | undefined = string | undefined,
19
+ > {
20
+ listEntries: FunctionReference<
21
+ "query",
22
+ "public",
23
+ {
24
+ paginationOpts: PaginationOptions;
25
+ kind?: EntryKind;
26
+ status?: EntryStatus;
27
+ sort?: EntrySort;
28
+ },
29
+ PaginationResult<FeedbackEntry>,
30
+ Name
31
+ >;
32
+ getEntry: FunctionReference<
33
+ "query",
34
+ "public",
35
+ { entryId: string },
36
+ FeedbackEntry | null,
37
+ Name
38
+ >;
39
+ searchEntries: FunctionReference<
40
+ "query",
41
+ "public",
42
+ {
43
+ searchQuery: string;
44
+ kind?: EntryKind;
45
+ status?: EntryStatus;
46
+ limit?: number;
47
+ },
48
+ FeedbackEntry[],
49
+ Name
50
+ >;
51
+ findSimilarEntries: FunctionReference<
52
+ "query",
53
+ "public",
54
+ { title: string; body: string; kind?: EntryKind; limit?: number },
55
+ SimilarEntriesResult,
56
+ Name
57
+ >;
58
+ createEntry: FunctionReference<
59
+ "mutation",
60
+ "public",
61
+ { kind: EntryKind; title: string; body: string },
62
+ string,
63
+ Name
64
+ >;
65
+ updateEntry: FunctionReference<
66
+ "mutation",
67
+ "public",
68
+ { entryId: string; title: string; body: string },
69
+ null,
70
+ Name
71
+ >;
72
+ setEntryStatus: FunctionReference<
73
+ "mutation",
74
+ "public",
75
+ { entryId: string; status: EntryStatus },
76
+ null,
77
+ Name
78
+ >;
79
+ setEntryUpvote: FunctionReference<
80
+ "mutation",
81
+ "public",
82
+ { entryId: string; desiredState: boolean },
83
+ { active: boolean; upvoteCount: number },
84
+ Name
85
+ >;
86
+ listComments: FunctionReference<
87
+ "query",
88
+ "public",
89
+ {
90
+ paginationOpts: PaginationOptions;
91
+ entryId: string;
92
+ parentCommentId?: string;
93
+ sort?: CommentSort;
94
+ },
95
+ PaginationResult<FeedbackComment>,
96
+ Name
97
+ >;
98
+ createComment: FunctionReference<
99
+ "mutation",
100
+ "public",
101
+ { entryId: string; parentCommentId?: string; body: string },
102
+ string,
103
+ Name
104
+ >;
105
+ updateComment: FunctionReference<
106
+ "mutation",
107
+ "public",
108
+ { commentId: string; body: string },
109
+ null,
110
+ Name
111
+ >;
112
+ deleteComment: FunctionReference<
113
+ "mutation",
114
+ "public",
115
+ { commentId: string },
116
+ null,
117
+ Name
118
+ >;
119
+ setCommentLike: FunctionReference<
120
+ "mutation",
121
+ "public",
122
+ { commentId: string; desiredState: boolean },
123
+ { active: boolean; likeCount: number },
124
+ Name
125
+ >;
126
+ }
@@ -0,0 +1,80 @@
1
+ import type {
2
+ CommentSort,
3
+ EntryKind,
4
+ EntrySort,
5
+ EntryStatus,
6
+ } from "../component/model.js";
7
+
8
+ export interface FeedbackConfig {
9
+ entries: {
10
+ enabledKinds: readonly EntryKind[];
11
+ defaultStatus: EntryStatus;
12
+ defaultSort: EntrySort;
13
+ maxPageSize: number;
14
+ editableByAuthor: boolean;
15
+ };
16
+ comments: {
17
+ maxDepth: number;
18
+ maxPageSize: number;
19
+ defaultSort: CommentSort;
20
+ editableByAuthor: boolean;
21
+ deletableByAuthor: boolean;
22
+ };
23
+ search: {
24
+ duplicateSuggestions: boolean;
25
+ duplicateSuggestionLimit: number;
26
+ defaultLimit: number;
27
+ maxLimit: number;
28
+ };
29
+ limits: {
30
+ titleLength: number;
31
+ bodyLength: number;
32
+ commentLength: number;
33
+ };
34
+ }
35
+
36
+ export interface FeedbackConfigOverrides {
37
+ entries?: Partial<FeedbackConfig["entries"]>;
38
+ comments?: Partial<FeedbackConfig["comments"]>;
39
+ search?: Partial<FeedbackConfig["search"]>;
40
+ limits?: Partial<FeedbackConfig["limits"]>;
41
+ }
42
+
43
+ export const defaultFeedbackConfig: FeedbackConfig = {
44
+ entries: {
45
+ enabledKinds: ["feedback", "feature_request", "bug_report"],
46
+ defaultStatus: "open",
47
+ defaultSort: "top",
48
+ maxPageSize: 50,
49
+ editableByAuthor: true,
50
+ },
51
+ comments: {
52
+ maxDepth: 5,
53
+ maxPageSize: 50,
54
+ defaultSort: "top",
55
+ editableByAuthor: true,
56
+ deletableByAuthor: true,
57
+ },
58
+ search: {
59
+ duplicateSuggestions: true,
60
+ duplicateSuggestionLimit: 5,
61
+ defaultLimit: 20,
62
+ maxLimit: 50,
63
+ },
64
+ limits: {
65
+ titleLength: 160,
66
+ bodyLength: 10_000,
67
+ commentLength: 5_000,
68
+ },
69
+ };
70
+
71
+ export function createFeedbackConfig(
72
+ overrides: FeedbackConfigOverrides = {},
73
+ ): FeedbackConfig {
74
+ return {
75
+ entries: { ...defaultFeedbackConfig.entries, ...overrides.entries },
76
+ comments: { ...defaultFeedbackConfig.comments, ...overrides.comments },
77
+ search: { ...defaultFeedbackConfig.search, ...overrides.search },
78
+ limits: { ...defaultFeedbackConfig.limits, ...overrides.limits },
79
+ };
80
+ }
@@ -0,0 +1,338 @@
1
+ import {
2
+ mutationGeneric,
3
+ paginationOptsValidator,
4
+ paginationResultValidator,
5
+ queryGeneric,
6
+ type Auth,
7
+ type PaginationOptions,
8
+ } from "convex/server";
9
+ import { ConvexError, v } from "convex/values";
10
+
11
+ import type { ComponentApi } from "../component/_generated/component.js";
12
+ import {
13
+ commentSortValidator,
14
+ entryKindValidator,
15
+ entrySortValidator,
16
+ entryStatusValidator,
17
+ publicCommentValidator,
18
+ publicEntryValidator,
19
+ similarEntriesValidator,
20
+ type FeedbackActor,
21
+ } from "../component/model.js";
22
+ import type { FeedbackPublicApi } from "./api.js";
23
+ import {
24
+ createFeedbackConfig,
25
+ type FeedbackConfigOverrides,
26
+ } from "./config.js";
27
+
28
+ export type {
29
+ CommentSort,
30
+ EntryKind,
31
+ EntrySort,
32
+ EntryStatus,
33
+ FeedbackActor,
34
+ FeedbackComment,
35
+ FeedbackEntry,
36
+ SimilarEntriesResult,
37
+ } from "../component/model.js";
38
+ export type { FeedbackPublicApi } from "./api.js";
39
+ export {
40
+ createFeedbackConfig,
41
+ defaultFeedbackConfig,
42
+ type FeedbackConfig,
43
+ type FeedbackConfigOverrides,
44
+ } from "./config.js";
45
+
46
+ export interface FeedbackAuthContext {
47
+ auth: Auth;
48
+ }
49
+
50
+ export interface ExposeFeedbackOptions {
51
+ actor: (ctx: FeedbackAuthContext) => Promise<FeedbackActor | null>;
52
+ config?: FeedbackConfigOverrides;
53
+ }
54
+
55
+ function requireActor(actor: FeedbackActor | null): FeedbackActor {
56
+ if (actor === null) {
57
+ throw new ConvexError("Authentication is required.");
58
+ }
59
+ return actor;
60
+ }
61
+
62
+ function clampPositive(
63
+ value: number | undefined,
64
+ fallback: number,
65
+ maximum: number,
66
+ ): number {
67
+ const candidate = value ?? fallback;
68
+ if (!Number.isFinite(candidate)) return fallback;
69
+ return Math.max(1, Math.min(Math.floor(candidate), maximum));
70
+ }
71
+
72
+ function clampPagination(
73
+ paginationOpts: PaginationOptions,
74
+ maximum: number,
75
+ ): PaginationOptions {
76
+ return {
77
+ ...paginationOpts,
78
+ numItems: clampPositive(paginationOpts.numItems, maximum, maximum),
79
+ };
80
+ }
81
+
82
+ function actorIdFields(actor: FeedbackActor | null): {
83
+ viewerActorId?: string;
84
+ } {
85
+ return actor === null ? {} : { viewerActorId: actor.id };
86
+ }
87
+
88
+ export function exposeFeedbackApi<Name extends string | undefined>(
89
+ component: ComponentApi<Name>,
90
+ options: ExposeFeedbackOptions,
91
+ ) {
92
+ const config = createFeedbackConfig(options.config);
93
+
94
+ return {
95
+ listEntries: queryGeneric({
96
+ args: {
97
+ paginationOpts: paginationOptsValidator,
98
+ kind: v.optional(entryKindValidator),
99
+ status: v.optional(entryStatusValidator),
100
+ sort: v.optional(entrySortValidator),
101
+ },
102
+ returns: paginationResultValidator(publicEntryValidator),
103
+ handler: async (ctx, args) => {
104
+ const actor = await options.actor(ctx);
105
+ return await ctx.runQuery(component.entries.list, {
106
+ paginationOpts: clampPagination(
107
+ args.paginationOpts,
108
+ config.entries.maxPageSize,
109
+ ),
110
+ ...(args.kind === undefined ? {} : { kind: args.kind }),
111
+ ...(args.status === undefined ? {} : { status: args.status }),
112
+ sort: args.sort ?? config.entries.defaultSort,
113
+ ...actorIdFields(actor),
114
+ });
115
+ },
116
+ }),
117
+
118
+ getEntry: queryGeneric({
119
+ args: { entryId: v.string() },
120
+ returns: v.union(publicEntryValidator, v.null()),
121
+ handler: async (ctx, args) => {
122
+ const actor = await options.actor(ctx);
123
+ return await ctx.runQuery(component.entries.get, {
124
+ entryId: args.entryId,
125
+ ...actorIdFields(actor),
126
+ });
127
+ },
128
+ }),
129
+
130
+ searchEntries: queryGeneric({
131
+ args: {
132
+ searchQuery: v.string(),
133
+ kind: v.optional(entryKindValidator),
134
+ status: v.optional(entryStatusValidator),
135
+ limit: v.optional(v.number()),
136
+ },
137
+ returns: v.array(publicEntryValidator),
138
+ handler: async (ctx, args) => {
139
+ const actor = await options.actor(ctx);
140
+ return await ctx.runQuery(component.entries.search, {
141
+ searchQuery: args.searchQuery,
142
+ ...(args.kind === undefined ? {} : { kind: args.kind }),
143
+ ...(args.status === undefined ? {} : { status: args.status }),
144
+ limit: clampPositive(
145
+ args.limit,
146
+ config.search.defaultLimit,
147
+ config.search.maxLimit,
148
+ ),
149
+ ...actorIdFields(actor),
150
+ });
151
+ },
152
+ }),
153
+
154
+ findSimilarEntries: queryGeneric({
155
+ args: {
156
+ title: v.string(),
157
+ body: v.string(),
158
+ kind: v.optional(entryKindValidator),
159
+ limit: v.optional(v.number()),
160
+ },
161
+ returns: similarEntriesValidator,
162
+ handler: async (ctx, args) => {
163
+ if (!config.search.duplicateSuggestions) {
164
+ return { exact: [], similar: [] };
165
+ }
166
+ const actor = await options.actor(ctx);
167
+ return await ctx.runQuery(component.entries.similar, {
168
+ title: args.title,
169
+ body: args.body,
170
+ ...(args.kind === undefined ? {} : { kind: args.kind }),
171
+ limit: clampPositive(
172
+ args.limit,
173
+ config.search.duplicateSuggestionLimit,
174
+ config.search.maxLimit,
175
+ ),
176
+ ...actorIdFields(actor),
177
+ });
178
+ },
179
+ }),
180
+
181
+ createEntry: mutationGeneric({
182
+ args: {
183
+ kind: entryKindValidator,
184
+ title: v.string(),
185
+ body: v.string(),
186
+ },
187
+ returns: v.string(),
188
+ handler: async (ctx, args) => {
189
+ const actor = requireActor(await options.actor(ctx));
190
+ return await ctx.runMutation(component.entries.create, {
191
+ actorId: actor.id,
192
+ kind: args.kind,
193
+ title: args.title,
194
+ body: args.body,
195
+ defaultStatus: config.entries.defaultStatus,
196
+ enabledKinds: [...config.entries.enabledKinds],
197
+ maxTitleLength: config.limits.titleLength,
198
+ maxBodyLength: config.limits.bodyLength,
199
+ });
200
+ },
201
+ }),
202
+
203
+ updateEntry: mutationGeneric({
204
+ args: {
205
+ entryId: v.string(),
206
+ title: v.string(),
207
+ body: v.string(),
208
+ },
209
+ returns: v.null(),
210
+ handler: async (ctx, args) => {
211
+ const actor = requireActor(await options.actor(ctx));
212
+ return await ctx.runMutation(component.entries.update, {
213
+ actor,
214
+ entryId: args.entryId,
215
+ title: args.title,
216
+ body: args.body,
217
+ editableByAuthor: config.entries.editableByAuthor,
218
+ maxTitleLength: config.limits.titleLength,
219
+ maxBodyLength: config.limits.bodyLength,
220
+ });
221
+ },
222
+ }),
223
+
224
+ setEntryStatus: mutationGeneric({
225
+ args: { entryId: v.string(), status: entryStatusValidator },
226
+ returns: v.null(),
227
+ handler: async (ctx, args) => {
228
+ const actor = requireActor(await options.actor(ctx));
229
+ return await ctx.runMutation(component.entries.setStatus, {
230
+ actor,
231
+ entryId: args.entryId,
232
+ status: args.status,
233
+ });
234
+ },
235
+ }),
236
+
237
+ setEntryUpvote: mutationGeneric({
238
+ args: { entryId: v.string(), desiredState: v.boolean() },
239
+ returns: v.object({ active: v.boolean(), upvoteCount: v.number() }),
240
+ handler: async (ctx, args) => {
241
+ const actor = requireActor(await options.actor(ctx));
242
+ return await ctx.runMutation(component.entries.setUpvote, {
243
+ actorId: actor.id,
244
+ entryId: args.entryId,
245
+ desiredState: args.desiredState,
246
+ });
247
+ },
248
+ }),
249
+
250
+ listComments: queryGeneric({
251
+ args: {
252
+ paginationOpts: paginationOptsValidator,
253
+ entryId: v.string(),
254
+ parentCommentId: v.optional(v.string()),
255
+ sort: v.optional(commentSortValidator),
256
+ },
257
+ returns: paginationResultValidator(publicCommentValidator),
258
+ handler: async (ctx, args) => {
259
+ const actor = await options.actor(ctx);
260
+ return await ctx.runQuery(component.comments.list, {
261
+ paginationOpts: clampPagination(
262
+ args.paginationOpts,
263
+ config.comments.maxPageSize,
264
+ ),
265
+ entryId: args.entryId,
266
+ ...(args.parentCommentId === undefined
267
+ ? {}
268
+ : { parentCommentId: args.parentCommentId }),
269
+ sort: args.sort ?? config.comments.defaultSort,
270
+ ...actorIdFields(actor),
271
+ });
272
+ },
273
+ }),
274
+
275
+ createComment: mutationGeneric({
276
+ args: {
277
+ entryId: v.string(),
278
+ parentCommentId: v.optional(v.string()),
279
+ body: v.string(),
280
+ },
281
+ returns: v.string(),
282
+ handler: async (ctx, args) => {
283
+ const actor = requireActor(await options.actor(ctx));
284
+ return await ctx.runMutation(component.comments.create, {
285
+ actorId: actor.id,
286
+ entryId: args.entryId,
287
+ ...(args.parentCommentId === undefined
288
+ ? {}
289
+ : { parentCommentId: args.parentCommentId }),
290
+ body: args.body,
291
+ maxDepth: config.comments.maxDepth,
292
+ maxCommentLength: config.limits.commentLength,
293
+ });
294
+ },
295
+ }),
296
+
297
+ updateComment: mutationGeneric({
298
+ args: { commentId: v.string(), body: v.string() },
299
+ returns: v.null(),
300
+ handler: async (ctx, args) => {
301
+ const actor = requireActor(await options.actor(ctx));
302
+ return await ctx.runMutation(component.comments.update, {
303
+ actor,
304
+ commentId: args.commentId,
305
+ body: args.body,
306
+ editableByAuthor: config.comments.editableByAuthor,
307
+ maxCommentLength: config.limits.commentLength,
308
+ });
309
+ },
310
+ }),
311
+
312
+ deleteComment: mutationGeneric({
313
+ args: { commentId: v.string() },
314
+ returns: v.null(),
315
+ handler: async (ctx, args) => {
316
+ const actor = requireActor(await options.actor(ctx));
317
+ return await ctx.runMutation(component.comments.remove, {
318
+ actor,
319
+ commentId: args.commentId,
320
+ deletableByAuthor: config.comments.deletableByAuthor,
321
+ });
322
+ },
323
+ }),
324
+
325
+ setCommentLike: mutationGeneric({
326
+ args: { commentId: v.string(), desiredState: v.boolean() },
327
+ returns: v.object({ active: v.boolean(), likeCount: v.number() }),
328
+ handler: async (ctx, args) => {
329
+ const actor = requireActor(await options.actor(ctx));
330
+ return await ctx.runMutation(component.comments.setLike, {
331
+ actorId: actor.id,
332
+ commentId: args.commentId,
333
+ desiredState: args.desiredState,
334
+ });
335
+ },
336
+ }),
337
+ } satisfies Record<keyof FeedbackPublicApi, unknown>;
338
+ }
@@ -0,0 +1,13 @@
1
+ # Component implementation
2
+
3
+ This directory is the isolated Convex component backend.
4
+
5
+ - `schema.ts`: three tables and query-driven indexes.
6
+ - `entries.ts`: entry CRUD, full-text search, duplicate suggestions, entry voting, indexed pagination.
7
+ - `comments.ts`: direct-child pagination, recursive write validation, soft deletion, comment likes.
8
+ - `model.ts`: reusable validators and public model types.
9
+ - `helpers.ts`: normalization, validation, and serializers.
10
+ - `convex.config.ts`: packaged component definition.
11
+ - `_generated/`: generated component API/server/data-model types. Regenerate after backend changes.
12
+
13
+ Important: component public functions become internal references when installed by a host app. The host must wrap them before exposing them to clients. Component IDs become strings at that boundary.
@@ -0,0 +1,58 @@
1
+ /* eslint-disable */
2
+ /**
3
+ * Generated `api` utility.
4
+ *
5
+ * THIS CODE IS AUTOMATICALLY GENERATED.
6
+ *
7
+ * To regenerate, run `npx convex dev`.
8
+ * @module
9
+ */
10
+
11
+ import type * as comments from "../comments.js";
12
+ import type * as entries from "../entries.js";
13
+ import type * as helpers from "../helpers.js";
14
+ import type * as model from "../model.js";
15
+ import type * as types from "../types.js";
16
+
17
+ import type {
18
+ ApiFromModules,
19
+ FilterApi,
20
+ FunctionReference,
21
+ } from "convex/server";
22
+ import { anyApi, componentsGeneric } from "convex/server";
23
+
24
+ const fullApi: ApiFromModules<{
25
+ comments: typeof comments;
26
+ entries: typeof entries;
27
+ helpers: typeof helpers;
28
+ model: typeof model;
29
+ types: typeof types;
30
+ }> = anyApi as any;
31
+
32
+ /**
33
+ * A utility for referencing Convex functions in your app's public API.
34
+ *
35
+ * Usage:
36
+ * ```js
37
+ * const myFunctionReference = api.myModule.myFunction;
38
+ * ```
39
+ */
40
+ export const api: FilterApi<
41
+ typeof fullApi,
42
+ FunctionReference<any, "public">
43
+ > = anyApi as any;
44
+
45
+ /**
46
+ * A utility for referencing Convex functions in your app's internal API.
47
+ *
48
+ * Usage:
49
+ * ```js
50
+ * const myFunctionReference = internal.myModule.myFunction;
51
+ * ```
52
+ */
53
+ export const internal: FilterApi<
54
+ typeof fullApi,
55
+ FunctionReference<any, "internal">
56
+ > = anyApi as any;
57
+
58
+ export const components = componentsGeneric() as unknown as {};