@devvit/reddit 0.12.6-next-2025-12-09-22-01-39-77cc3d62a.0 → 0.12.6-next-2025-12-10-21-30-51-8567b4083.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.
@@ -0,0 +1,10 @@
1
+ import type { GraphQL, Metadata, QueryResponse } from '@devvit/protos';
2
+ import type { PersistedQueryRequest, QueryRequest } from '@devvit/protos/types/devvit/plugin/redditapi/graphql/graphql_msg.js';
3
+ import type { LinksAndCommentsMock } from './LinksAndCommentsMock.js';
4
+ export declare class GraphQLMock implements GraphQL {
5
+ private readonly _linksAndCommentsMock;
6
+ constructor(linksAndCommentsMock: LinksAndCommentsMock);
7
+ PersistedQuery(request: PersistedQueryRequest, _metadata?: Metadata): Promise<QueryResponse>;
8
+ Query(_request: QueryRequest, _metadata?: Metadata): Promise<QueryResponse>;
9
+ }
10
+ //# sourceMappingURL=GraphQLMock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GraphQLMock.d.ts","sourceRoot":"","sources":["../../src/mocks/GraphQLMock.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACvE,OAAO,KAAK,EACV,qBAAqB,EACrB,YAAY,EACb,MAAM,qEAAqE,CAAC;AAE7E,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAatE,qBAAa,WAAY,YAAW,OAAO;IACzC,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAuB;gBAEjD,oBAAoB,EAAE,oBAAoB;IAIhD,cAAc,CAClB,OAAO,EAAE,qBAAqB,EAC9B,SAAS,CAAC,EAAE,QAAQ,GACnB,OAAO,CAAC,aAAa,CAAC;IA+BnB,KAAK,CAAC,QAAQ,EAAE,YAAY,EAAE,SAAS,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,aAAa,CAAC;CAMlF"}
@@ -0,0 +1,43 @@
1
+ const methodMap = {
2
+ GetUserSocialLinks: 'User.getSocialLinks',
3
+ GetSnoovatarUrlByName: 'User.getSnoovatarUrl',
4
+ GetVaultContactByAddress: 'getVaultByAddress',
5
+ GetVaultContactByUserId: 'getVaultByUserId',
6
+ CreateModmailConversation: 'ModMailService.create*Conversation',
7
+ GetSubredditInfoByName: 'getSubredditInfoByName',
8
+ GetSubredditInfoById: 'getSubredditInfoById',
9
+ CreateShareUrl: 'createShareUrl',
10
+ };
11
+ export class GraphQLMock {
12
+ constructor(linksAndCommentsMock) {
13
+ this._linksAndCommentsMock = linksAndCommentsMock;
14
+ }
15
+ async PersistedQuery(request, _metadata) {
16
+ const { operationName, variables } = request;
17
+ if (operationName === 'GetDevvitPostData') {
18
+ const id = variables?.id;
19
+ if (!id) {
20
+ throw new Error('GetDevvitPostData requires an id');
21
+ }
22
+ const postData = this._linksAndCommentsMock.getPostData(id);
23
+ return {
24
+ data: {
25
+ postInfoById: {
26
+ devvit: {
27
+ postData: postData ? JSON.stringify({ developerData: postData }) : undefined,
28
+ },
29
+ },
30
+ },
31
+ errors: [],
32
+ };
33
+ }
34
+ const friendlyName = methodMap[operationName];
35
+ const nameToReport = friendlyName ?? 'unknown';
36
+ throw new Error(`Reddit API method ${nameToReport} is not implemented in the test harness.\n` +
37
+ `For more information, visit https://developers.reddit.com/docs/guides/tools/devvit_test`);
38
+ }
39
+ async Query(_request, _metadata) {
40
+ throw new Error(`Reddit API method GraphQL.Query is not implemented in the test harness.\n` +
41
+ `For more information, visit https://developers.reddit.com/docs/guides/tools/devvit_test`);
42
+ }
43
+ }
@@ -0,0 +1,41 @@
1
+ import type { Empty, LinksAndComments, Metadata } from '@devvit/protos';
2
+ import { type JsonRedditObjects, type JsonStatus, type Listing, RedditObject } from '@devvit/protos/types/devvit/plugin/redditapi/common/common_msg.js';
3
+ import type { BasicIdRequest, CommentRequest, EditCustomPostRequest, FollowPostRequest, InfoRequest, JsonWrappedComment, MoreChildrenRequest, ReportAwardRequest, ReportRequest, SaveRequest, SendRepliesRequest, SetContestModeRequest, SetCustomPostPreviewRequest, SetSubredditStickyRequest, SetSuggestedSortRequest, SubmitRequest, SubmitResponse, VoteRequest } from '@devvit/protos/types/devvit/plugin/redditapi/linksandcomments/linksandcomments_msg.js';
4
+ import { type JsonObject, T3 } from '@devvit/shared';
5
+ export declare class LinksAndCommentsMock implements LinksAndComments {
6
+ private _posts;
7
+ private _postData;
8
+ Comment(_request: CommentRequest, _metadata?: Metadata): Promise<JsonWrappedComment>;
9
+ Del(request: BasicIdRequest, _metadata?: Metadata): Promise<Empty>;
10
+ EditCustomPost(request: EditCustomPostRequest, _metadata?: Metadata): Promise<JsonRedditObjects>;
11
+ EditUserText(request: CommentRequest, _metadata?: Metadata): Promise<JsonWrappedComment>;
12
+ FollowPost(_request: FollowPostRequest, _metadata?: Metadata): Promise<Empty>;
13
+ Hide(_request: BasicIdRequest, _metadata?: Metadata): Promise<Empty>;
14
+ Info(request: InfoRequest, _metadata?: Metadata): Promise<Listing>;
15
+ Lock(_request: BasicIdRequest, _metadata?: Metadata): Promise<Empty>;
16
+ MarkNSFW(_request: BasicIdRequest, _metadata?: Metadata): Promise<Empty>;
17
+ MoreChildren(_request: MoreChildrenRequest, _metadata?: Metadata): Promise<JsonWrappedComment>;
18
+ Report(_request: ReportRequest, _metadata?: Metadata): Promise<JsonStatus>;
19
+ ReportAward(_request: ReportAwardRequest, _metadata?: Metadata): Promise<Empty>;
20
+ Save(_request: SaveRequest, _metadata?: Metadata): Promise<Empty>;
21
+ SendReplies(_request: SendRepliesRequest, _metadata?: Metadata): Promise<Empty>;
22
+ SetContestMode(_request: SetContestModeRequest, _metadata?: Metadata): Promise<JsonStatus>;
23
+ SetCustomPostPreview(_request: SetCustomPostPreviewRequest, _metadata?: Metadata): Promise<Empty>;
24
+ SetSubredditSticky(_request: SetSubredditStickyRequest, _metadata?: Metadata): Promise<JsonStatus>;
25
+ SetSuggestedSort(_request: SetSuggestedSortRequest, _metadata?: Metadata): Promise<JsonStatus>;
26
+ Spoiler(_request: BasicIdRequest, _metadata?: Metadata): Promise<Empty>;
27
+ Submit(request: SubmitRequest, _metadata?: Metadata): Promise<SubmitResponse>;
28
+ SubmitCustomPost(request: SubmitRequest, _metadata?: Metadata): Promise<SubmitResponse>;
29
+ Unhide(_request: BasicIdRequest, _metadata?: Metadata): Promise<Empty>;
30
+ Unlock(_request: BasicIdRequest, _metadata?: Metadata): Promise<Empty>;
31
+ UnmarkNSFW(_request: BasicIdRequest, _metadata?: Metadata): Promise<Empty>;
32
+ Unsave(_request: BasicIdRequest, _metadata?: Metadata): Promise<Empty>;
33
+ Unspoiler(_request: BasicIdRequest, _metadata?: Metadata): Promise<Empty>;
34
+ Vote(_request: VoteRequest, _metadata?: Metadata): Promise<Empty>;
35
+ getPostData(postId: string): JsonObject | undefined;
36
+ addPost(post: Omit<Partial<RedditObject>, 'id'> & {
37
+ id: T3;
38
+ title: string;
39
+ }): RedditObject;
40
+ }
41
+ //# sourceMappingURL=LinksAndCommentsMock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LinksAndCommentsMock.d.ts","sourceRoot":"","sources":["../../src/mocks/LinksAndCommentsMock.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AACxE,OAAO,EACL,KAAK,iBAAiB,EACtB,KAAK,UAAU,EACf,KAAK,OAAO,EACZ,YAAY,EACb,MAAM,mEAAmE,CAAC;AAC3E,OAAO,KAAK,EACV,cAAc,EACd,cAAc,EACd,qBAAqB,EACrB,iBAAiB,EACjB,WAAW,EACX,kBAAkB,EAClB,mBAAmB,EACnB,kBAAkB,EAClB,aAAa,EACb,WAAW,EACX,kBAAkB,EAClB,qBAAqB,EACrB,2BAA2B,EAC3B,yBAAyB,EACzB,uBAAuB,EACvB,aAAa,EACb,cAAc,EACd,WAAW,EACZ,MAAM,uFAAuF,CAAC;AAE/F,OAAO,EAAE,KAAK,UAAU,EAAE,EAAE,EAAE,MAAM,gBAAgB,CAAC;AAuMrD,qBAAa,oBAAqB,YAAW,gBAAgB;IAC3D,OAAO,CAAC,MAAM,CAAmC;IACjD,OAAO,CAAC,SAAS,CAA2C;IAEtD,OAAO,CAAC,QAAQ,EAAE,cAAc,EAAE,SAAS,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAOpF,GAAG,CAAC,OAAO,EAAE,cAAc,EAAE,SAAS,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC;IAKlE,cAAc,CAClB,OAAO,EAAE,qBAAqB,EAC9B,SAAS,CAAC,EAAE,QAAQ,GACnB,OAAO,CAAC,iBAAiB,CAAC;IAOvB,YAAY,CAAC,OAAO,EAAE,cAAc,EAAE,SAAS,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAgCxF,UAAU,CAAC,QAAQ,EAAE,iBAAiB,EAAE,SAAS,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC;IAO7E,IAAI,CAAC,QAAQ,EAAE,cAAc,EAAE,SAAS,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC;IAOpE,IAAI,CAAC,OAAO,EAAE,WAAW,EAAE,SAAS,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC;IAoBlE,IAAI,CAAC,QAAQ,EAAE,cAAc,EAAE,SAAS,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC;IAOpE,QAAQ,CAAC,QAAQ,EAAE,cAAc,EAAE,SAAS,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC;IAOxE,YAAY,CAChB,QAAQ,EAAE,mBAAmB,EAC7B,SAAS,CAAC,EAAE,QAAQ,GACnB,OAAO,CAAC,kBAAkB,CAAC;IAOxB,MAAM,CAAC,QAAQ,EAAE,aAAa,EAAE,SAAS,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC;IAO1E,WAAW,CAAC,QAAQ,EAAE,kBAAkB,EAAE,SAAS,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC;IAO/E,IAAI,CAAC,QAAQ,EAAE,WAAW,EAAE,SAAS,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC;IAOjE,WAAW,CAAC,QAAQ,EAAE,kBAAkB,EAAE,SAAS,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC;IAO/E,cAAc,CAAC,QAAQ,EAAE,qBAAqB,EAAE,SAAS,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC;IAO1F,oBAAoB,CACxB,QAAQ,EAAE,2BAA2B,EACrC,SAAS,CAAC,EAAE,QAAQ,GACnB,OAAO,CAAC,KAAK,CAAC;IAOX,kBAAkB,CACtB,QAAQ,EAAE,yBAAyB,EACnC,SAAS,CAAC,EAAE,QAAQ,GACnB,OAAO,CAAC,UAAU,CAAC;IAOhB,gBAAgB,CACpB,QAAQ,EAAE,uBAAuB,EACjC,SAAS,CAAC,EAAE,QAAQ,GACnB,OAAO,CAAC,UAAU,CAAC;IAOhB,OAAO,CAAC,QAAQ,EAAE,cAAc,EAAE,SAAS,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC;IAOvE,MAAM,CAAC,OAAO,EAAE,aAAa,EAAE,SAAS,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,cAAc,CAAC;IAiC7E,gBAAgB,CAAC,OAAO,EAAE,aAAa,EAAE,SAAS,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,cAAc,CAAC;IAqCvF,MAAM,CAAC,QAAQ,EAAE,cAAc,EAAE,SAAS,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC;IAOtE,MAAM,CAAC,QAAQ,EAAE,cAAc,EAAE,SAAS,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC;IAOtE,UAAU,CAAC,QAAQ,EAAE,cAAc,EAAE,SAAS,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC;IAO1E,MAAM,CAAC,QAAQ,EAAE,cAAc,EAAE,SAAS,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC;IAOtE,SAAS,CAAC,QAAQ,EAAE,cAAc,EAAE,SAAS,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC;IAOzE,IAAI,CAAC,QAAQ,EAAE,WAAW,EAAE,SAAS,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC;IAOvE,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS;IAInD,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,IAAI,CAAC,GAAG;QAAE,EAAE,EAAE,EAAE,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,YAAY;CAuB3F"}
@@ -0,0 +1,428 @@
1
+ import { RedditObject, } from '@devvit/protos/types/devvit/plugin/redditapi/common/common_msg.js';
2
+ import { T3 } from '@devvit/shared';
3
+ const DEFAULT_REDDIT_OBJECT = {
4
+ allAwardings: [],
5
+ approved: false,
6
+ approvedAtUtc: 0,
7
+ approvedBy: '',
8
+ archived: false,
9
+ associatedAward: '',
10
+ author: '',
11
+ authorFlairBackgroundColor: '',
12
+ authorFlairCssClass: '',
13
+ authorFlairRichtext: [],
14
+ authorFlairTemplateId: '',
15
+ authorFlairText: '',
16
+ authorFlairTextColor: '',
17
+ authorFlairType: '',
18
+ authorFullname: '',
19
+ authorIsBlocked: false,
20
+ authorPatreonFlair: false,
21
+ authorPremium: false,
22
+ awarders: [],
23
+ bannedAtUtc: 0,
24
+ bannedBy: '',
25
+ body: '',
26
+ bodyHtml: '',
27
+ canGild: false,
28
+ canModPost: false,
29
+ children: [],
30
+ collapsed: false,
31
+ collapsedBecauseCrowdControl: false,
32
+ collapsedReason: '',
33
+ collapsedReasonCode: '',
34
+ commentType: '',
35
+ controversiality: 0,
36
+ count: 0,
37
+ created: 0,
38
+ createdUtc: 0,
39
+ depth: 0,
40
+ displayName: '',
41
+ distinguished: '',
42
+ downs: 0,
43
+ edited: false,
44
+ gallery: [],
45
+ gilded: 0,
46
+ gildings: undefined,
47
+ hidden: false,
48
+ id: '',
49
+ ignoreReports: false,
50
+ isSubmitter: false,
51
+ likes: false,
52
+ linkAuthor: '',
53
+ linkFlairBackgroundColor: '',
54
+ linkFlairCssClass: '',
55
+ linkFlairRichtext: [],
56
+ linkFlairTemplateId: '',
57
+ linkFlairText: '',
58
+ linkFlairTextColor: '',
59
+ linkFlairType: '',
60
+ linkId: '',
61
+ linkPermalink: '',
62
+ linkTitle: '',
63
+ linkUrl: '',
64
+ locked: false,
65
+ modNote: '',
66
+ modPermissions: [],
67
+ modReasonBy: '',
68
+ modReasonTitle: '',
69
+ modReports: [],
70
+ name: '',
71
+ noFollow: false,
72
+ numComments: 0,
73
+ numReports: 0,
74
+ over18: false,
75
+ parentId: '',
76
+ permalink: '',
77
+ quarantine: false,
78
+ removalReason: '',
79
+ removed: false,
80
+ removedBy: '',
81
+ removedByCategory: '',
82
+ replies: '',
83
+ replyList: undefined,
84
+ reportReasons: [],
85
+ rteMode: '',
86
+ saved: false,
87
+ score: 0,
88
+ scoreHidden: false,
89
+ secureMedia: undefined,
90
+ selftext: '',
91
+ selftextHtml: '',
92
+ sendReplies: false,
93
+ spam: false,
94
+ spoiler: false,
95
+ stickied: false,
96
+ subreddit: '',
97
+ subredditId: '',
98
+ subredditNamePrefixed: '',
99
+ subredditType: '',
100
+ thumbnail: '',
101
+ thumbnailHeight: 0,
102
+ thumbnailWidth: 0,
103
+ title: '',
104
+ topAwardedType: '',
105
+ totalAwardsReceived: 0,
106
+ treatmentTags: [],
107
+ unrepliableReason: '',
108
+ ups: 0,
109
+ url: '',
110
+ userReports: [],
111
+ };
112
+ const DEFAULT_COMMENT = {
113
+ allAwardings: [],
114
+ approved: false,
115
+ approvedAtUtc: 0,
116
+ approvedBy: '',
117
+ archived: false,
118
+ associatedAward: '',
119
+ author: '',
120
+ authorFlairBackgroundColor: '',
121
+ authorFlairCssClass: '',
122
+ authorFlairRichtext: [],
123
+ authorFlairTemplateId: '',
124
+ authorFlairText: '',
125
+ authorFlairTextColor: '',
126
+ authorFlairType: '',
127
+ authorFullname: '',
128
+ authorIsBlocked: false,
129
+ authorPatreonFlair: false,
130
+ authorPremium: false,
131
+ awarders: [],
132
+ banInfo: undefined,
133
+ bannedAtUtc: 0,
134
+ bannedBy: '',
135
+ body: '',
136
+ bodyHtml: '',
137
+ canGild: false,
138
+ canModPost: false,
139
+ children: [],
140
+ collapsed: false,
141
+ collapsedBecauseCrowdControl: false,
142
+ collapsedReason: '',
143
+ collapsedReasonCode: '',
144
+ commentType: '',
145
+ controversiality: 0,
146
+ count: 0,
147
+ created: 0,
148
+ createdUtc: 0,
149
+ depth: 0,
150
+ distinguished: '',
151
+ downs: 0,
152
+ edited: false,
153
+ gilded: 0,
154
+ gildings: undefined,
155
+ id: '',
156
+ ignoreReports: false,
157
+ isSubmitter: false,
158
+ likes: false,
159
+ linkId: '',
160
+ locked: false,
161
+ markedSpam: false,
162
+ modNote: '',
163
+ modReasonBy: '',
164
+ modReasonTitle: '',
165
+ modReports: [],
166
+ name: '',
167
+ noFollow: false,
168
+ numReports: 0,
169
+ parentId: '',
170
+ permalink: '',
171
+ removalReason: '',
172
+ removed: false,
173
+ replies: '',
174
+ reportReasons: [],
175
+ rteMode: '',
176
+ saved: false,
177
+ score: 0,
178
+ scoreHidden: false,
179
+ sendReplies: false,
180
+ spam: false,
181
+ stickied: false,
182
+ subreddit: '',
183
+ subredditId: '',
184
+ subredditNamePrefixed: '',
185
+ subredditType: '',
186
+ topAwardedType: '',
187
+ totalAwardsReceived: 0,
188
+ treatmentTags: [],
189
+ unrepliableReason: '',
190
+ ups: 0,
191
+ userReports: [],
192
+ verdict: '',
193
+ };
194
+ function fakeId() {
195
+ return `t3_${Math.random().toString(36).substring(7)}`;
196
+ }
197
+ export class LinksAndCommentsMock {
198
+ constructor() {
199
+ this._posts = new Map();
200
+ this._postData = new Map();
201
+ }
202
+ async Comment(_request, _metadata) {
203
+ throw new Error(`Reddit API method Users.Friend is not implemented in the test harness.\n` +
204
+ `For more information, visit https://developers.reddit.com/docs/guides/tools/devvit_test`);
205
+ }
206
+ async Del(request, _metadata) {
207
+ this._posts.delete(request.id);
208
+ return {};
209
+ }
210
+ async EditCustomPost(request, _metadata) {
211
+ if (request.postData?.developerData) {
212
+ this._postData.set(request.thingId, request.postData.developerData);
213
+ }
214
+ return { json: { errors: [], data: { things: [] } } };
215
+ }
216
+ async EditUserText(request, _metadata) {
217
+ const post = this._posts.get(request.thingId);
218
+ if (!post) {
219
+ throw new Error('Post not found');
220
+ }
221
+ post.selftext = request.text;
222
+ post.edited = true;
223
+ return {
224
+ json: {
225
+ errors: [],
226
+ data: {
227
+ things: [
228
+ {
229
+ kind: 't3',
230
+ data: {
231
+ ...DEFAULT_COMMENT,
232
+ ...post,
233
+ body: request.text,
234
+ allAwardings: [], // Mismatch fix: RedditObject has Any[], Comment has Awarding[]
235
+ gildings: undefined, // Mismatch fix: RedditObject has Any, Comment has Gildings
236
+ reportReasons: [], // Mismatch fix: RedditObject has ListValue[], Comment has string[]
237
+ treatmentTags: [], // Mismatch fix: RedditObject has Any[], Comment has string[]
238
+ children: [], // Mismatch fix: RedditObject has ListValue, Comment has string[]
239
+ },
240
+ },
241
+ ],
242
+ },
243
+ },
244
+ };
245
+ }
246
+ async FollowPost(_request, _metadata) {
247
+ throw new Error(`Reddit API method LinksAndComments.FollowPost is not implemented in the test harness.\n` +
248
+ `For more information, visit https://developers.reddit.com/docs/guides/tools/devvit_test`);
249
+ }
250
+ async Hide(_request, _metadata) {
251
+ throw new Error(`Reddit API method LinksAndComments.Hide is not implemented in the test harness.\n` +
252
+ `For more information, visit https://developers.reddit.com/docs/guides/tools/devvit_test`);
253
+ }
254
+ async Info(request, _metadata) {
255
+ const children = [];
256
+ for (const id of request.thingIds) {
257
+ const post = this._posts.get(id);
258
+ if (post) {
259
+ children.push({
260
+ kind: 't3',
261
+ data: post,
262
+ });
263
+ }
264
+ }
265
+ return {
266
+ kind: 'Listing',
267
+ data: {
268
+ children,
269
+ },
270
+ };
271
+ }
272
+ async Lock(_request, _metadata) {
273
+ throw new Error(`Reddit API method LinksAndComments.Lock is not implemented in the test harness.\n` +
274
+ `For more information, visit https://developers.reddit.com/docs/guides/tools/devvit_test`);
275
+ }
276
+ async MarkNSFW(_request, _metadata) {
277
+ throw new Error(`Reddit API method LinksAndComments.MarkNSFW is not implemented in the test harness.\n` +
278
+ `For more information, visit https://developers.reddit.com/docs/guides/tools/devvit_test`);
279
+ }
280
+ async MoreChildren(_request, _metadata) {
281
+ throw new Error(`Reddit API method LinksAndComments.MoreChildren is not implemented in the test harness.\n` +
282
+ `For more information, visit https://developers.reddit.com/docs/guides/tools/devvit_test`);
283
+ }
284
+ async Report(_request, _metadata) {
285
+ throw new Error(`Reddit API method LinksAndComments.Report is not implemented in the test harness.\n` +
286
+ `For more information, visit https://developers.reddit.com/docs/guides/tools/devvit_test`);
287
+ }
288
+ async ReportAward(_request, _metadata) {
289
+ throw new Error(`Reddit API method LinksAndComments.ReportAward is not implemented in the test harness.\n` +
290
+ `For more information, visit https://developers.reddit.com/docs/guides/tools/devvit_test`);
291
+ }
292
+ async Save(_request, _metadata) {
293
+ throw new Error(`Reddit API method LinksAndComments.Save is not implemented in the test harness.\n` +
294
+ `For more information, visit https://developers.reddit.com/docs/guides/tools/devvit_test`);
295
+ }
296
+ async SendReplies(_request, _metadata) {
297
+ throw new Error(`Reddit API method LinksAndComments.SendReplies is not implemented in the test harness.\n` +
298
+ `For more information, visit https://developers.reddit.com/docs/guides/tools/devvit_test`);
299
+ }
300
+ async SetContestMode(_request, _metadata) {
301
+ throw new Error(`Reddit API method LinksAndComments.SetContestMode is not implemented in the test harness.\n` +
302
+ `For more information, visit https://developers.reddit.com/docs/guides/tools/devvit_test`);
303
+ }
304
+ async SetCustomPostPreview(_request, _metadata) {
305
+ throw new Error(`Reddit API method LinksAndComments.SetCustomPostPreview is not implemented in the test harness.\n` +
306
+ `For more information, visit https://developers.reddit.com/docs/guides/tools/devvit_test`);
307
+ }
308
+ async SetSubredditSticky(_request, _metadata) {
309
+ throw new Error(`Reddit API method LinksAndComments.SetSubredditSticky is not implemented in the test harness.\n` +
310
+ `For more information, visit https://developers.reddit.com/docs/guides/tools/devvit_test`);
311
+ }
312
+ async SetSuggestedSort(_request, _metadata) {
313
+ throw new Error(`Reddit API method LinksAndComments.SetSuggestedSort is not implemented in the test harness.\n` +
314
+ `For more information, visit https://developers.reddit.com/docs/guides/tools/devvit_test`);
315
+ }
316
+ async Spoiler(_request, _metadata) {
317
+ throw new Error(`Reddit API method LinksAndComments.Spoiler is not implemented in the test harness.\n` +
318
+ `For more information, visit https://developers.reddit.com/docs/guides/tools/devvit_test`);
319
+ }
320
+ async Submit(request, _metadata) {
321
+ const id = fakeId();
322
+ const shortId = id.substring(3);
323
+ const post = {
324
+ ...DEFAULT_REDDIT_OBJECT,
325
+ id: shortId,
326
+ name: id,
327
+ title: request.title,
328
+ createdUtc: Math.floor(Date.now() / 1000),
329
+ author: 'testuser',
330
+ subreddit: request.sr,
331
+ subredditId: 't5_test', // Mock subreddit ID
332
+ url: request.url || `https://www.reddit.com/r/${request.sr}/comments/${shortId}/`,
333
+ permalink: `/r/${request.sr}/comments/${shortId}/`,
334
+ selftext: request.text,
335
+ authorFullname: 't2_testuser',
336
+ };
337
+ this._posts.set(id, post);
338
+ return {
339
+ json: {
340
+ data: {
341
+ id: shortId,
342
+ url: post.url,
343
+ name: id,
344
+ },
345
+ errors: [],
346
+ },
347
+ };
348
+ }
349
+ async SubmitCustomPost(request, _metadata) {
350
+ const id = fakeId();
351
+ const shortId = id.substring(3);
352
+ const post = {
353
+ ...DEFAULT_REDDIT_OBJECT,
354
+ id: shortId,
355
+ name: id,
356
+ title: request.title,
357
+ createdUtc: Math.floor(Date.now() / 1000),
358
+ author: 'testuser',
359
+ subreddit: request.sr,
360
+ subredditId: 't5_test',
361
+ url: `https://www.reddit.com/r/${request.sr}/comments/${shortId}/`,
362
+ permalink: `/r/${request.sr}/comments/${shortId}/`,
363
+ selftext: '',
364
+ authorFullname: 't2_testuser',
365
+ };
366
+ this._posts.set(id, post);
367
+ if (request.postData?.developerData) {
368
+ this._postData.set(id, request.postData.developerData);
369
+ }
370
+ return {
371
+ json: {
372
+ data: {
373
+ id: shortId,
374
+ url: post.url,
375
+ name: id,
376
+ },
377
+ errors: [],
378
+ },
379
+ };
380
+ }
381
+ async Unhide(_request, _metadata) {
382
+ throw new Error(`Reddit API method LinksAndComments.Unhide is not implemented in the test harness.\n` +
383
+ `For more information, visit https://developers.reddit.com/docs/guides/tools/devvit_test`);
384
+ }
385
+ async Unlock(_request, _metadata) {
386
+ throw new Error(`Reddit API method LinksAndComments.Unlock is not implemented in the test harness.\n` +
387
+ `For more information, visit https://developers.reddit.com/docs/guides/tools/devvit_test`);
388
+ }
389
+ async UnmarkNSFW(_request, _metadata) {
390
+ throw new Error(`Reddit API method LinksAndComments.UnmarkNSFW is not implemented in the test harness.\n` +
391
+ `For more information, visit https://developers.reddit.com/docs/guides/tools/devvit_test`);
392
+ }
393
+ async Unsave(_request, _metadata) {
394
+ throw new Error(`Reddit API method LinksAndComments.Unsave is not implemented in the test harness.\n` +
395
+ `For more information, visit https://developers.reddit.com/docs/guides/tools/devvit_test`);
396
+ }
397
+ async Unspoiler(_request, _metadata) {
398
+ throw new Error(`Reddit API method LinksAndComments.Unspoiler is not implemented in the test harness.\n` +
399
+ `For more information, visit https://developers.reddit.com/docs/guides/tools/devvit_test`);
400
+ }
401
+ async Vote(_request, _metadata) {
402
+ throw new Error(`Reddit API method LinksAndComments.Vote is not implemented in the test harness.\n` +
403
+ `For more information, visit https://developers.reddit.com/docs/guides/tools/devvit_test`);
404
+ }
405
+ getPostData(postId) {
406
+ return this._postData.get(postId);
407
+ }
408
+ addPost(post) {
409
+ const fullId = post.id;
410
+ const shortId = fullId.replace(/^t3_/, '');
411
+ const newPost = {
412
+ ...DEFAULT_REDDIT_OBJECT,
413
+ createdUtc: Math.floor(Date.now() / 1000),
414
+ author: 'testuser',
415
+ subreddit: 'testsub',
416
+ subredditId: 't5_test',
417
+ url: `https://www.reddit.com/r/testsub/comments/${shortId}/`,
418
+ permalink: `/r/testsub/comments/${shortId}/`,
419
+ score: 0,
420
+ numComments: 0,
421
+ ...post,
422
+ id: shortId,
423
+ name: post.title,
424
+ };
425
+ this._posts.set(fullId, newPost);
426
+ return newPost;
427
+ }
428
+ }
@@ -0,0 +1,83 @@
1
+ import type { RedditObject } from '@devvit/protos/types/devvit/plugin/redditapi/common/common_msg.js';
2
+ import type { SubredditAboutResponse_AboutData } from '@devvit/protos/types/devvit/plugin/redditapi/subreddits/subreddits_msg.js';
3
+ import type { User } from '@devvit/protos/types/devvit/reddit/user.js';
4
+ import { T3, type T5 } from '@devvit/shared';
5
+ import { T2 } from '@devvit/shared-types/tid.js';
6
+ import { GraphQLMock } from './GraphQLMock.js';
7
+ import { LinksAndCommentsMock } from './LinksAndCommentsMock.js';
8
+ import { SubredditMock } from './SubredditMock.js';
9
+ import { UserMock } from './UserMock.js';
10
+ /**
11
+ * RedditPluginMock serves as the registry for all Reddit backend plugin mocks.
12
+ *
13
+ * It acts as the "Server" side of the mock infrastructure. When the `RedditClient` (client-side)
14
+ * makes an RPC call (e.g. `reddit.getPostById()`), it eventually routes to a plugin method on the backend.
15
+ *
16
+ * This class intercepts those plugin requests.
17
+ *
18
+ * - If a mock implementation exists (e.g. `Users`), it routes the request to that mock.
19
+ * - If no implementation exists (e.g. `Subreddits`), it returns a proxy that throws a helpful error
20
+ * when any method is called, informing the user that the specific plugin is not yet mocked.
21
+ *
22
+ * This "partial implementation" strategy allows us to incrementally add support for more Reddit APIs
23
+ * without breaking the entire harness or requiring a full implementation of every Reddit service upfront.
24
+ */
25
+ export declare class RedditPluginMock {
26
+ readonly users: UserMock;
27
+ readonly linksAndComments: LinksAndCommentsMock;
28
+ readonly subreddits: SubredditMock;
29
+ readonly graphQL: GraphQLMock;
30
+ readonly flair: unknown;
31
+ readonly listings: unknown;
32
+ readonly moderation: unknown;
33
+ readonly modNote: unknown;
34
+ readonly newModmail: unknown;
35
+ readonly privateMessages: unknown;
36
+ readonly widgets: unknown;
37
+ readonly wiki: unknown;
38
+ constructor();
39
+ /**
40
+ * Returns all registered plugin mocks keyed by their proto service names. You should likely
41
+ * never need to use this method, for internal use only!
42
+ */
43
+ getPluginRegistrations(): {
44
+ "devvit.plugin.redditapi.flair.Flair": unknown;
45
+ "devvit.plugin.redditapi.graphql.GraphQL": GraphQLMock;
46
+ "devvit.plugin.redditapi.linksandcomments.LinksAndComments": LinksAndCommentsMock;
47
+ "devvit.plugin.redditapi.listings.Listings": unknown;
48
+ "devvit.plugin.redditapi.moderation.Moderation": unknown;
49
+ "devvit.plugin.redditapi.modnote.ModNote": unknown;
50
+ "devvit.plugin.redditapi.newmodmail.NewModmail": unknown;
51
+ "devvit.plugin.redditapi.privatemessages.PrivateMessages": unknown;
52
+ "devvit.plugin.redditapi.subreddits.Subreddits": SubredditMock;
53
+ "devvit.plugin.redditapi.users.Users": UserMock;
54
+ "devvit.plugin.redditapi.widgets.Widgets": unknown;
55
+ "devvit.plugin.redditapi.wiki.Wiki": unknown;
56
+ };
57
+ /**
58
+ * Helper to seed the mock database with a User.
59
+ * This allows tests to set up state before calling `reddit.getUserByUsername`.
60
+ */
61
+ addUser(user: Omit<Partial<User>, 'id'> & {
62
+ name: string;
63
+ id: T2;
64
+ }): User;
65
+ /**
66
+ * Helper to seed the mock database with a Post.
67
+ * This allows tests to set up state before calling `reddit.getPostById`.
68
+ */
69
+ addPost(post: Omit<Partial<RedditObject>, 'id'> & {
70
+ id: T3;
71
+ title: string;
72
+ }): RedditObject;
73
+ /**
74
+ * Helper to seed the mock database with a Subreddit.
75
+ * This allows tests to set up state before calling `reddit.getSubredditByName`.
76
+ */
77
+ addSubreddit(data: Partial<SubredditAboutResponse_AboutData> & {
78
+ id: T5;
79
+ displayName: string;
80
+ }): SubredditAboutResponse_AboutData;
81
+ private _createUnimplementedPluginService;
82
+ }
83
+ //# sourceMappingURL=RedditPluginMock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RedditPluginMock.d.ts","sourceRoot":"","sources":["../../src/mocks/RedditPluginMock.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mEAAmE,CAAC;AAQtG,OAAO,KAAK,EAAE,gCAAgC,EAAE,MAAM,2EAA2E,CAAC;AAKlI,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,4CAA4C,CAAC;AACvE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,EAAE,EAAE,MAAM,6BAA6B,CAAC;AAEjD,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACjE,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzC;;;;;;;;;;;;;;GAcG;AACH,qBAAa,gBAAgB;IAE3B,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC;IACzB,QAAQ,CAAC,gBAAgB,EAAE,oBAAoB,CAAC;IAChD,QAAQ,CAAC,UAAU,EAAE,aAAa,CAAC;IACnC,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;IAC9B,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC;IAClC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;;IAwCvB;;;OAGG;IACH,sBAAsB;;;;;;;;;;;;;;IAiBtB;;;OAGG;IACH,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,GAAG;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,EAAE,CAAA;KAAE,GAAG,IAAI;IAIzE;;;OAGG;IACH,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,IAAI,CAAC,GAAG;QAAE,EAAE,EAAE,EAAE,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,YAAY;IAI1F;;;OAGG;IACH,YAAY,CACV,IAAI,EAAE,OAAO,CAAC,gCAAgC,CAAC,GAAG;QAAE,EAAE,EAAE,EAAE,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,GAChF,gCAAgC;IAInC,OAAO,CAAC,iCAAiC;CAa1C"}
@@ -0,0 +1,114 @@
1
+ import { NewModmailDefinition } from '@devvit/protos';
2
+ import { FlairDefinition } from '@devvit/protos/types/devvit/plugin/redditapi/flair/flair_svc.js';
3
+ import { GraphQLDefinition } from '@devvit/protos/types/devvit/plugin/redditapi/graphql/graphql_svc.js';
4
+ import { LinksAndCommentsDefinition } from '@devvit/protos/types/devvit/plugin/redditapi/linksandcomments/linksandcomments_svc.js';
5
+ import { ListingsDefinition } from '@devvit/protos/types/devvit/plugin/redditapi/listings/listings_svc.js';
6
+ import { ModerationDefinition } from '@devvit/protos/types/devvit/plugin/redditapi/moderation/moderation_svc.js';
7
+ import { ModNoteDefinition } from '@devvit/protos/types/devvit/plugin/redditapi/modnote/modnote_svc.js';
8
+ import { PrivateMessagesDefinition } from '@devvit/protos/types/devvit/plugin/redditapi/privatemessages/privatemessages_svc.js';
9
+ import { SubredditsDefinition } from '@devvit/protos/types/devvit/plugin/redditapi/subreddits/subreddits_svc.js';
10
+ import { UsersDefinition } from '@devvit/protos/types/devvit/plugin/redditapi/users/users_svc.js';
11
+ import { WidgetsDefinition } from '@devvit/protos/types/devvit/plugin/redditapi/widgets/widgets_svc.js';
12
+ import { WikiDefinition } from '@devvit/protos/types/devvit/plugin/redditapi/wiki/wiki_svc.js';
13
+ import { T3 } from '@devvit/shared';
14
+ import { T2 } from '@devvit/shared-types/tid.js';
15
+ import { GraphQLMock } from './GraphQLMock.js';
16
+ import { LinksAndCommentsMock } from './LinksAndCommentsMock.js';
17
+ import { SubredditMock } from './SubredditMock.js';
18
+ import { UserMock } from './UserMock.js';
19
+ /**
20
+ * RedditPluginMock serves as the registry for all Reddit backend plugin mocks.
21
+ *
22
+ * It acts as the "Server" side of the mock infrastructure. When the `RedditClient` (client-side)
23
+ * makes an RPC call (e.g. `reddit.getPostById()`), it eventually routes to a plugin method on the backend.
24
+ *
25
+ * This class intercepts those plugin requests.
26
+ *
27
+ * - If a mock implementation exists (e.g. `Users`), it routes the request to that mock.
28
+ * - If no implementation exists (e.g. `Subreddits`), it returns a proxy that throws a helpful error
29
+ * when any method is called, informing the user that the specific plugin is not yet mocked.
30
+ *
31
+ * This "partial implementation" strategy allows us to incrementally add support for more Reddit APIs
32
+ * without breaking the entire harness or requiring a full implementation of every Reddit service upfront.
33
+ */
34
+ export class RedditPluginMock {
35
+ constructor() {
36
+ this.users = new UserMock();
37
+ this.linksAndComments = new LinksAndCommentsMock();
38
+ this.subreddits = new SubredditMock();
39
+ this.graphQL = new GraphQLMock(this.linksAndComments);
40
+ this.flair = this._createUnimplementedPluginService('Flair');
41
+ this.listings = this._createUnimplementedPluginService('Listings');
42
+ this.moderation = this._createUnimplementedPluginService('Moderation');
43
+ this.modNote = this._createUnimplementedPluginService('ModNote');
44
+ this.newModmail = this._createUnimplementedPluginService('NewModmail');
45
+ this.privateMessages = this._createUnimplementedPluginService('PrivateMessages');
46
+ this.widgets = this._createUnimplementedPluginService('Widgets');
47
+ this.wiki = this._createUnimplementedPluginService('Wiki');
48
+ return new Proxy(this, {
49
+ get: (target, prop, receiver) => {
50
+ // 1. Check if we have a concrete implementation for this plugin (e.g. "Users")
51
+ if (prop in target) {
52
+ return Reflect.get(target, prop, receiver);
53
+ }
54
+ // 2. Fallback: Return a "Dummy Service" for plugins we haven't implemented yet.
55
+ // Accessing properties on this dummy service is fine, but calling methods will throw.
56
+ return new Proxy({}, {
57
+ get: () => () => {
58
+ throw new Error(`Reddit API plugin ${String(prop)} is not implemented in the test harness.\n` +
59
+ `For more information, visit https://developers.reddit.com/docs/guides/tools/devvit_test`);
60
+ },
61
+ });
62
+ },
63
+ });
64
+ }
65
+ /**
66
+ * Returns all registered plugin mocks keyed by their proto service names. You should likely
67
+ * never need to use this method, for internal use only!
68
+ */
69
+ getPluginRegistrations() {
70
+ return {
71
+ [FlairDefinition.fullName]: this.flair,
72
+ [GraphQLDefinition.fullName]: this.graphQL,
73
+ [LinksAndCommentsDefinition.fullName]: this.linksAndComments,
74
+ [ListingsDefinition.fullName]: this.listings,
75
+ [ModerationDefinition.fullName]: this.moderation,
76
+ [ModNoteDefinition.fullName]: this.modNote,
77
+ [NewModmailDefinition.fullName]: this.newModmail,
78
+ [PrivateMessagesDefinition.fullName]: this.privateMessages,
79
+ [SubredditsDefinition.fullName]: this.subreddits,
80
+ [UsersDefinition.fullName]: this.users,
81
+ [WidgetsDefinition.fullName]: this.widgets,
82
+ [WikiDefinition.fullName]: this.wiki,
83
+ };
84
+ }
85
+ /**
86
+ * Helper to seed the mock database with a User.
87
+ * This allows tests to set up state before calling `reddit.getUserByUsername`.
88
+ */
89
+ addUser(user) {
90
+ return this.users.addUser(user);
91
+ }
92
+ /**
93
+ * Helper to seed the mock database with a Post.
94
+ * This allows tests to set up state before calling `reddit.getPostById`.
95
+ */
96
+ addPost(post) {
97
+ return this.linksAndComments.addPost(post);
98
+ }
99
+ /**
100
+ * Helper to seed the mock database with a Subreddit.
101
+ * This allows tests to set up state before calling `reddit.getSubredditByName`.
102
+ */
103
+ addSubreddit(data) {
104
+ return this.subreddits.addSubreddit(data);
105
+ }
106
+ _createUnimplementedPluginService(pluginName) {
107
+ return new Proxy({}, {
108
+ get: () => () => {
109
+ throw new Error(`Reddit API plugin ${pluginName} is not implemented in the test harness.\n` +
110
+ `For more information, visit https://developers.reddit.com/docs/guides/tools/devvit_test`);
111
+ },
112
+ });
113
+ }
114
+ }
@@ -0,0 +1,39 @@
1
+ import type { JsonStatus, Listing, Metadata, Subreddits } from '@devvit/protos';
2
+ import type { Empty, StringValue } from '@devvit/protos/community.js';
3
+ import type { AboutWhereRequest, BasicSearchRequest, BasicSubredditRequest, BasicWhereRequest, DeleteSrImgRequest, SearchRedditNamesResponse, SearchSubredditsResponse, SiteAdminRequest, StickyRequest, StickyResponse, SubmitTextResponse, SubredditAboutEditRequest, SubredditAboutEditResponse, SubredditAboutResponse, SubredditAboutResponse_AboutData, SubredditAboutRulesResponse, SubredditAboutTrafficResponse, SubredditAddRemovalReasonRequest, SubredditAddRemovalReasonResponse, SubredditAutocompleteRequest, SubredditAutocompleteResponse, SubredditGetRemovalReasonsRequest, SubredditGetRemovalReasonsResponse, SubredditPostRequirementsResponse, SubredditsSearchRequest, SubredditsSearchResponse, SubredditStylesheetRequest, SubscribeRequest, UploadSrImgRequest, UploadSrImgResponse, UserSearchResponse, UsersSearchRequest } from '@devvit/protos/types/devvit/plugin/redditapi/subreddits/subreddits_msg.js';
4
+ import type { T5 } from '@devvit/shared';
5
+ export declare class SubredditMock implements Subreddits {
6
+ private _subreddits;
7
+ AboutWhere(_request: AboutWhereRequest, _metadata?: Metadata): Promise<Listing>;
8
+ DeleteSrBanner(_request: BasicSubredditRequest, _metadata?: Metadata): Promise<JsonStatus>;
9
+ DeleteSrHeader(_request: BasicSubredditRequest, _metadata?: Metadata): Promise<JsonStatus>;
10
+ DeleteSrIcon(_request: BasicSubredditRequest, _metadata?: Metadata): Promise<JsonStatus>;
11
+ DeleteSrImg(_request: DeleteSrImgRequest, _metadata?: Metadata): Promise<JsonStatus>;
12
+ SearchRedditNames(_request: BasicSearchRequest, _metadata?: Metadata): Promise<SearchRedditNamesResponse>;
13
+ SearchSubreddits(_request: BasicSearchRequest, _metadata?: Metadata): Promise<SearchSubredditsResponse>;
14
+ Sidebar(_request: BasicSubredditRequest, _metadata?: Metadata): Promise<StringValue>;
15
+ SiteAdmin(_request: SiteAdminRequest, _metadata?: Metadata): Promise<JsonStatus>;
16
+ Sticky(_request: StickyRequest, _metadata?: Metadata): Promise<StickyResponse>;
17
+ SubmitText(_request: BasicSubredditRequest, _metadata?: Metadata): Promise<SubmitTextResponse>;
18
+ SubredditAbout(request: BasicSubredditRequest, _metadata?: Metadata): Promise<SubredditAboutResponse>;
19
+ SubredditAboutEdit(_request: SubredditAboutEditRequest, _metadata?: Metadata): Promise<SubredditAboutEditResponse>;
20
+ SubredditAboutRules(_request: BasicSubredditRequest, _metadata?: Metadata): Promise<SubredditAboutRulesResponse>;
21
+ SubredditAboutTraffic(_request: BasicSubredditRequest, _metadata?: Metadata): Promise<SubredditAboutTrafficResponse>;
22
+ SubredditAddRemovalReason(_request: SubredditAddRemovalReasonRequest, _metadata?: Metadata): Promise<SubredditAddRemovalReasonResponse>;
23
+ SubredditAutocomplete(_request: SubredditAutocompleteRequest, _metadata?: Metadata): Promise<SubredditAutocompleteResponse>;
24
+ SubredditGetRemovalReasons(_request: SubredditGetRemovalReasonsRequest, _metadata?: Metadata): Promise<SubredditGetRemovalReasonsResponse>;
25
+ SubredditPostRequirements(_request: BasicSubredditRequest, _metadata?: Metadata): Promise<SubredditPostRequirementsResponse>;
26
+ SubredditStylesheet(_request: SubredditStylesheetRequest, _metadata?: Metadata): Promise<JsonStatus>;
27
+ SubredditsMineWhere(_request: BasicWhereRequest, _metadata?: Metadata): Promise<Listing>;
28
+ SubredditsSearch(_request: SubredditsSearchRequest, _metadata?: Metadata): Promise<SubredditsSearchResponse>;
29
+ SubredditsWhere(_request: BasicWhereRequest, _metadata?: Metadata): Promise<SubredditsSearchResponse>;
30
+ Subscribe(_request: SubscribeRequest, _metadata?: Metadata): Promise<Empty>;
31
+ UploadSrImg(_request: UploadSrImgRequest, _metadata?: Metadata): Promise<UploadSrImgResponse>;
32
+ UsersSearch(_request: UsersSearchRequest, _metadata?: Metadata): Promise<UserSearchResponse>;
33
+ UsersWhere(_request: BasicWhereRequest, _metadata?: Metadata): Promise<SubredditsSearchResponse>;
34
+ addSubreddit(data: Partial<SubredditAboutResponse_AboutData> & {
35
+ id: T5;
36
+ displayName: string;
37
+ }): SubredditAboutResponse_AboutData;
38
+ }
39
+ //# sourceMappingURL=SubredditMock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SubredditMock.d.ts","sourceRoot":"","sources":["../../src/mocks/SubredditMock.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,140 @@
1
+ export class SubredditMock {
2
+ constructor() {
3
+ this._subreddits = new Map();
4
+ }
5
+ async AboutWhere(_request, _metadata) {
6
+ throw new Error(`Reddit API method Subreddits.AboutWhere is not implemented in the test harness.\n` +
7
+ `For more information, visit https://developers.reddit.com/docs/guides/tools/devvit_test`);
8
+ }
9
+ async DeleteSrBanner(_request, _metadata) {
10
+ throw new Error(`Reddit API method Subreddits.DeleteSrBanner is not implemented in the test harness.\n` +
11
+ `For more information, visit https://developers.reddit.com/docs/guides/tools/devvit_test`);
12
+ }
13
+ async DeleteSrHeader(_request, _metadata) {
14
+ throw new Error(`Reddit API method Subreddits.DeleteSrHeader is not implemented in the test harness.\n` +
15
+ `For more information, visit https://developers.reddit.com/docs/guides/tools/devvit_test`);
16
+ }
17
+ async DeleteSrIcon(_request, _metadata) {
18
+ throw new Error(`Reddit API method Subreddits.DeleteSrIcon is not implemented in the test harness.\n` +
19
+ `For more information, visit https://developers.reddit.com/docs/guides/tools/devvit_test`);
20
+ }
21
+ async DeleteSrImg(_request, _metadata) {
22
+ throw new Error(`Reddit API method Subreddits.DeleteSrImg is not implemented in the test harness.\n` +
23
+ `For more information, visit https://developers.reddit.com/docs/guides/tools/devvit_test`);
24
+ }
25
+ async SearchRedditNames(_request, _metadata) {
26
+ throw new Error(`Reddit API method Subreddits.SearchRedditNames is not implemented in the test harness.\n` +
27
+ `For more information, visit https://developers.reddit.com/docs/guides/tools/devvit_test`);
28
+ }
29
+ async SearchSubreddits(_request, _metadata) {
30
+ throw new Error(`Reddit API method Subreddits.SearchSubreddits is not implemented in the test harness.\n` +
31
+ `For more information, visit https://developers.reddit.com/docs/guides/tools/devvit_test`);
32
+ }
33
+ async Sidebar(_request, _metadata) {
34
+ throw new Error(`Reddit API method Subreddits.Sidebar is not implemented in the test harness.\n` +
35
+ `For more information, visit https://developers.reddit.com/docs/guides/tools/devvit_test`);
36
+ }
37
+ async SiteAdmin(_request, _metadata) {
38
+ throw new Error(`Reddit API method Subreddits.SiteAdmin is not implemented in the test harness.\n` +
39
+ `For more information, visit https://developers.reddit.com/docs/guides/tools/devvit_test`);
40
+ }
41
+ async Sticky(_request, _metadata) {
42
+ throw new Error(`Reddit API method Subreddits.Sticky is not implemented in the test harness.\n` +
43
+ `For more information, visit https://developers.reddit.com/docs/guides/tools/devvit_test`);
44
+ }
45
+ async SubmitText(_request, _metadata) {
46
+ throw new Error(`Reddit API method Subreddits.SubmitText is not implemented in the test harness.\n` +
47
+ `For more information, visit https://developers.reddit.com/docs/guides/tools/devvit_test`);
48
+ }
49
+ async SubredditAbout(request, _metadata) {
50
+ const subredditName = request.subreddit;
51
+ let found;
52
+ for (const [name, data] of this._subreddits.entries()) {
53
+ if (name.toLowerCase() === subredditName.toLowerCase()) {
54
+ found = data;
55
+ break;
56
+ }
57
+ }
58
+ if (!found) {
59
+ throw new Error('HTTP 404 Not Found');
60
+ }
61
+ return { data: found };
62
+ }
63
+ async SubredditAboutEdit(_request, _metadata) {
64
+ throw new Error(`Reddit API method Subreddits.SubredditAboutEdit is not implemented in the test harness.\n` +
65
+ `For more information, visit https://developers.reddit.com/docs/guides/tools/devvit_test`);
66
+ }
67
+ async SubredditAboutRules(_request, _metadata) {
68
+ throw new Error(`Reddit API method Subreddits.SubredditAboutRules is not implemented in the test harness.\n` +
69
+ `For more information, visit https://developers.reddit.com/docs/guides/tools/devvit_test`);
70
+ }
71
+ async SubredditAboutTraffic(_request, _metadata) {
72
+ throw new Error(`Reddit API method Subreddits.SubredditAboutTraffic is not implemented in the test harness.\n` +
73
+ `For more information, visit https://developers.reddit.com/docs/guides/tools/devvit_test`);
74
+ }
75
+ async SubredditAddRemovalReason(_request, _metadata) {
76
+ throw new Error(`Reddit API method Subreddits.SubredditAddRemovalReason is not implemented in the test harness.\n` +
77
+ `For more information, visit https://developers.reddit.com/docs/guides/tools/devvit_test`);
78
+ }
79
+ async SubredditAutocomplete(_request, _metadata) {
80
+ throw new Error(`Reddit API method Subreddits.SubredditAutocomplete is not implemented in the test harness.\n` +
81
+ `For more information, visit https://developers.reddit.com/docs/guides/tools/devvit_test`);
82
+ }
83
+ async SubredditGetRemovalReasons(_request, _metadata) {
84
+ throw new Error(`Reddit API method Subreddits.SubredditGetRemovalReasons is not implemented in the test harness.\n` +
85
+ `For more information, visit https://developers.reddit.com/docs/guides/tools/devvit_test`);
86
+ }
87
+ async SubredditPostRequirements(_request, _metadata) {
88
+ throw new Error(`Reddit API method Subreddits.SubredditPostRequirements is not implemented in the test harness.\n` +
89
+ `For more information, visit https://developers.reddit.com/docs/guides/tools/devvit_test`);
90
+ }
91
+ async SubredditStylesheet(_request, _metadata) {
92
+ throw new Error(`Reddit API method Subreddits.SubredditStylesheet is not implemented in the test harness.\n` +
93
+ `For more information, visit https://developers.reddit.com/docs/guides/tools/devvit_test`);
94
+ }
95
+ async SubredditsMineWhere(_request, _metadata) {
96
+ throw new Error(`Reddit API method Subreddits.SubredditsMineWhere is not implemented in the test harness.\n` +
97
+ `For more information, visit https://developers.reddit.com/docs/guides/tools/devvit_test`);
98
+ }
99
+ async SubredditsSearch(_request, _metadata) {
100
+ throw new Error(`Reddit API method Subreddits.SubredditsSearch is not implemented in the test harness.\n` +
101
+ `For more information, visit https://developers.reddit.com/docs/guides/tools/devvit_test`);
102
+ }
103
+ async SubredditsWhere(_request, _metadata) {
104
+ throw new Error(`Reddit API method Subreddits.SubredditsWhere is not implemented in the test harness.\n` +
105
+ `For more information, visit https://developers.reddit.com/docs/guides/tools/devvit_test`);
106
+ }
107
+ async Subscribe(_request, _metadata) {
108
+ throw new Error(`Reddit API method Subreddits.Subscribe is not implemented in the test harness.\n` +
109
+ `For more information, visit https://developers.reddit.com/docs/guides/tools/devvit_test`);
110
+ }
111
+ async UploadSrImg(_request, _metadata) {
112
+ throw new Error(`Reddit API method Subreddits.UploadSrImg is not implemented in the test harness.\n` +
113
+ `For more information, visit https://developers.reddit.com/docs/guides/tools/devvit_test`);
114
+ }
115
+ async UsersSearch(_request, _metadata) {
116
+ throw new Error(`Reddit API method Subreddits.UsersSearch is not implemented in the test harness.\n` +
117
+ `For more information, visit https://developers.reddit.com/docs/guides/tools/devvit_test`);
118
+ }
119
+ async UsersWhere(_request, _metadata) {
120
+ throw new Error(`Reddit API method Subreddits.UsersWhere is not implemented in the test harness.\n` +
121
+ `For more information, visit https://developers.reddit.com/docs/guides/tools/devvit_test`);
122
+ }
123
+ addSubreddit(data) {
124
+ const subreddit = {
125
+ createdUtc: Math.floor(Date.now() / 1000),
126
+ subscribers: 0,
127
+ activeUserCount: 0,
128
+ over18: false,
129
+ lang: 'en',
130
+ url: `/r/${data.name}/`,
131
+ title: data.displayName,
132
+ description: '',
133
+ subredditType: 'public',
134
+ ...data,
135
+ id: data.id.replace(/^t5_/, ''),
136
+ };
137
+ this._subreddits.set(data.displayName, subreddit);
138
+ return subreddit;
139
+ }
140
+ }
@@ -0,0 +1,27 @@
1
+ import type { Empty, JsonStatus, Listing, Metadata, Users } from '@devvit/protos';
2
+ import type { BoolValue } from '@devvit/protos/community.js';
3
+ import type { BlockUserRequest, BlockUserResponse, FriendRequest, GeneralFriendResponse, GenericUsersRequest, GetUserKarmaForSubredditRequest, GetUserKarmaForSubredditResponse, ReportUserRequest, SetPermissionsRequest, UnfriendRequest, UpdateFriendRelationshipRequest, UserAboutRequest, UserAboutResponse, UserDataByAccountIdsRequest, UserDataByAccountIdsResponse, UsernameAvailableRequest, UserTrophiesResponse, UserWhereRequest } from '@devvit/protos/types/devvit/plugin/redditapi/users/users_msg.js';
4
+ import type { User } from '@devvit/protos/types/devvit/reddit/user.js';
5
+ import { T2 } from '@devvit/shared-types/tid.js';
6
+ export declare class UserMock implements Users {
7
+ private _users;
8
+ UserAbout(request: UserAboutRequest, _metadata?: Metadata): Promise<UserAboutResponse>;
9
+ UserDataByAccountIds(request: UserDataByAccountIdsRequest, _metadata?: Metadata): Promise<UserDataByAccountIdsResponse>;
10
+ BlockUser(_request: BlockUserRequest, _metadata?: Metadata): Promise<BlockUserResponse>;
11
+ Friend(_request: FriendRequest, _metadata?: Metadata): Promise<JsonStatus>;
12
+ GetFriendInformation(_request: GenericUsersRequest, _metadata?: Metadata): Promise<GeneralFriendResponse>;
13
+ GetUserKarmaForSubreddit(_request: GetUserKarmaForSubredditRequest, _metadata?: Metadata): Promise<GetUserKarmaForSubredditResponse>;
14
+ ReportUser(_request: ReportUserRequest, _metadata?: Metadata): Promise<Empty>;
15
+ SetPermissions(_request: SetPermissionsRequest, _metadata?: Metadata): Promise<JsonStatus>;
16
+ Unfriend(_request: UnfriendRequest, _metadata?: Metadata): Promise<Empty>;
17
+ UnfriendUser(_request: GenericUsersRequest, _metadata?: Metadata): Promise<Empty>;
18
+ UpdateFriendRelationship(_request: UpdateFriendRelationshipRequest, _metadata?: Metadata): Promise<GeneralFriendResponse>;
19
+ UserTrophies(_request: GenericUsersRequest, _metadata?: Metadata): Promise<UserTrophiesResponse>;
20
+ UserWhere(_request: UserWhereRequest, _metadata?: Metadata): Promise<Listing>;
21
+ UsernameAvailable(_request: UsernameAvailableRequest, _metadata?: Metadata): Promise<BoolValue>;
22
+ addUser(data: Omit<Partial<User>, 'id'> & {
23
+ name: string;
24
+ id: T2;
25
+ }): User;
26
+ }
27
+ //# sourceMappingURL=UserMock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"UserMock.d.ts","sourceRoot":"","sources":["../../src/mocks/UserMock.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAClF,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,KAAK,EACV,gBAAgB,EAChB,iBAAiB,EACjB,aAAa,EACb,qBAAqB,EACrB,mBAAmB,EACnB,+BAA+B,EAC/B,gCAAgC,EAChC,iBAAiB,EACjB,qBAAqB,EACrB,eAAe,EACf,+BAA+B,EAC/B,gBAAgB,EAChB,iBAAiB,EACjB,2BAA2B,EAC3B,4BAA4B,EAE5B,wBAAwB,EACxB,oBAAoB,EACpB,gBAAgB,EACjB,MAAM,iEAAiE,CAAC;AACzE,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,4CAA4C,CAAC;AACvE,OAAO,EAAQ,EAAE,EAAE,MAAM,6BAA6B,CAAC;AAIvD,qBAAa,QAAS,YAAW,KAAK;IACpC,OAAO,CAAC,MAAM,CAA6B;IAErC,SAAS,CAAC,OAAO,EAAE,gBAAgB,EAAE,SAAS,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAStF,oBAAoB,CACxB,OAAO,EAAE,2BAA2B,EACpC,SAAS,CAAC,EAAE,QAAQ,GACnB,OAAO,CAAC,4BAA4B,CAAC;IA6BlC,SAAS,CAAC,QAAQ,EAAE,gBAAgB,EAAE,SAAS,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAOvF,MAAM,CAAC,QAAQ,EAAE,aAAa,EAAE,SAAS,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC;IAO1E,oBAAoB,CACxB,QAAQ,EAAE,mBAAmB,EAC7B,SAAS,CAAC,EAAE,QAAQ,GACnB,OAAO,CAAC,qBAAqB,CAAC;IAO3B,wBAAwB,CAC5B,QAAQ,EAAE,+BAA+B,EACzC,SAAS,CAAC,EAAE,QAAQ,GACnB,OAAO,CAAC,gCAAgC,CAAC;IAOtC,UAAU,CAAC,QAAQ,EAAE,iBAAiB,EAAE,SAAS,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC;IAO7E,cAAc,CAAC,QAAQ,EAAE,qBAAqB,EAAE,SAAS,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC;IAO1F,QAAQ,CAAC,QAAQ,EAAE,eAAe,EAAE,SAAS,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC;IAOzE,YAAY,CAAC,QAAQ,EAAE,mBAAmB,EAAE,SAAS,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC;IAOjF,wBAAwB,CAC5B,QAAQ,EAAE,+BAA+B,EACzC,SAAS,CAAC,EAAE,QAAQ,GACnB,OAAO,CAAC,qBAAqB,CAAC;IAO3B,YAAY,CAChB,QAAQ,EAAE,mBAAmB,EAC7B,SAAS,CAAC,EAAE,QAAQ,GACnB,OAAO,CAAC,oBAAoB,CAAC;IAO1B,SAAS,CAAC,QAAQ,EAAE,gBAAgB,EAAE,SAAS,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC;IAO7E,iBAAiB,CACrB,QAAQ,EAAE,wBAAwB,EAClC,SAAS,CAAC,EAAE,QAAQ,GACnB,OAAO,CAAC,SAAS,CAAC;IAOrB,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,GAAG;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,EAAE,CAAA;KAAE,GAAG,IAAI;CA4B1E"}
@@ -0,0 +1,113 @@
1
+ import { isT2, T2 } from '@devvit/shared-types/tid.js';
2
+ export class UserMock {
3
+ constructor() {
4
+ this._users = new Map();
5
+ }
6
+ async UserAbout(request, _metadata) {
7
+ const user = this._users.get(request.username);
8
+ if (!user) {
9
+ // Simulate 404
10
+ throw new Error('HTTP 404 Not Found');
11
+ }
12
+ return { data: user };
13
+ }
14
+ async UserDataByAccountIds(request, _metadata) {
15
+ const ids = request.ids.split(',');
16
+ const responseUsers = {};
17
+ for (const id of ids) {
18
+ const targetId = T2(isT2(id) ? id : `t2_${id}`);
19
+ const user = Array.from(this._users.values()).find((u) => {
20
+ if (!u.id) {
21
+ return false;
22
+ }
23
+ const uId = T2(isT2(u.id) ? u.id : `t2_${u.id}`);
24
+ return uId === targetId;
25
+ });
26
+ if (user) {
27
+ // The protobuf expects a specific structure for UserAccountData
28
+ responseUsers[id] = {
29
+ name: user.name,
30
+ createdUtc: user.createdUtc,
31
+ linkKarma: user.linkKarma,
32
+ commentKarma: user.commentKarma,
33
+ profileOver18: user.over18,
34
+ };
35
+ }
36
+ }
37
+ return { users: responseUsers };
38
+ }
39
+ async BlockUser(_request, _metadata) {
40
+ throw new Error(`Reddit API method Users.BlockUser is not implemented in the test harness.\n` +
41
+ `For more information, visit https://developers.reddit.com/docs/guides/tools/devvit_test`);
42
+ }
43
+ async Friend(_request, _metadata) {
44
+ throw new Error(`Reddit API method Users.Friend is not implemented in the test harness.\n` +
45
+ `For more information, visit https://developers.reddit.com/docs/guides/tools/devvit_test`);
46
+ }
47
+ async GetFriendInformation(_request, _metadata) {
48
+ throw new Error(`Reddit API method Users.GetFriendInformation is not implemented in the test harness.\n` +
49
+ `For more information, visit https://developers.reddit.com/docs/guides/tools/devvit_test`);
50
+ }
51
+ async GetUserKarmaForSubreddit(_request, _metadata) {
52
+ throw new Error(`Reddit API method Users.GetUserKarmaForSubreddit is not implemented in the test harness.\n` +
53
+ `For more information, visit https://developers.reddit.com/docs/guides/tools/devvit_test`);
54
+ }
55
+ async ReportUser(_request, _metadata) {
56
+ throw new Error(`Reddit API method Users.ReportUser is not implemented in the test harness.\n` +
57
+ `For more information, visit https://developers.reddit.com/docs/guides/tools/devvit_test`);
58
+ }
59
+ async SetPermissions(_request, _metadata) {
60
+ throw new Error(`Reddit API method Users.SetPermissions is not implemented in the test harness.\n` +
61
+ `For more information, visit https://developers.reddit.com/docs/guides/tools/devvit_test`);
62
+ }
63
+ async Unfriend(_request, _metadata) {
64
+ throw new Error(`Reddit API method Users.Unfriend is not implemented in the test harness.\n` +
65
+ `For more information, visit https://developers.reddit.com/docs/guides/tools/devvit_test`);
66
+ }
67
+ async UnfriendUser(_request, _metadata) {
68
+ throw new Error(`Reddit API method Users.UnfriendUser is not implemented in the test harness.\n` +
69
+ `For more information, visit https://developers.reddit.com/docs/guides/tools/devvit_test`);
70
+ }
71
+ async UpdateFriendRelationship(_request, _metadata) {
72
+ throw new Error(`Reddit API method Users.UpdateFriendRelationship is not implemented in the test harness.\n` +
73
+ `For more information, visit https://developers.reddit.com/docs/guides/tools/devvit_test`);
74
+ }
75
+ async UserTrophies(_request, _metadata) {
76
+ throw new Error(`Reddit API method Users.UserTrophies is not implemented in the test harness.\n` +
77
+ `For more information, visit https://developers.reddit.com/docs/guides/tools/devvit_test`);
78
+ }
79
+ async UserWhere(_request, _metadata) {
80
+ throw new Error(`Reddit API method Users.UserWhere is not implemented in the test harness.\n` +
81
+ `For more information, visit https://developers.reddit.com/docs/guides/tools/devvit_test`);
82
+ }
83
+ async UsernameAvailable(_request, _metadata) {
84
+ throw new Error(`Reddit API method Users.UsernameAvailable is not implemented in the test harness.\n` +
85
+ `For more information, visit https://developers.reddit.com/docs/guides/tools/devvit_test`);
86
+ }
87
+ addUser(data) {
88
+ const user = {
89
+ createdUtc: data.createdUtc ?? Math.floor(Date.now() / 1000),
90
+ linkKarma: data.linkKarma ?? 0,
91
+ commentKarma: data.commentKarma ?? 0,
92
+ hasVerifiedEmail: data.hasVerifiedEmail ?? false,
93
+ isEmployee: data.isEmployee ?? false,
94
+ isMod: data.isMod ?? false,
95
+ isGold: data.isGold ?? false,
96
+ isSuspended: data.isSuspended ?? false,
97
+ over18: data.over18 ?? false,
98
+ iconImg: data.iconImg ?? '',
99
+ subreddit: data.subreddit,
100
+ snoovatarImg: data.snoovatarImg ?? '',
101
+ awardeeKarma: data.awardeeKarma ?? 0,
102
+ awarderKarma: data.awarderKarma ?? 0,
103
+ totalKarma: data.totalKarma ?? 0,
104
+ acceptFollowers: data.acceptFollowers ?? true,
105
+ prefShowSnoovatar: data.prefShowSnoovatar ?? true,
106
+ snoovatarSize: data.snoovatarSize ?? [],
107
+ ...data,
108
+ id: data.id.replace(/^t2_/, ''),
109
+ };
110
+ this._users.set(data.name, user);
111
+ return user;
112
+ }
113
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@devvit/reddit",
3
- "version": "0.12.6-next-2025-12-09-22-01-39-77cc3d62a.0",
3
+ "version": "0.12.6-next-2025-12-10-21-30-51-8567b4083.0",
4
4
  "license": "BSD-3-Clause",
5
5
  "repository": {
6
6
  "type": "git",
@@ -12,7 +12,8 @@
12
12
  "browser": "./serverImportInClientCodePanic.js",
13
13
  "default": "./index.js"
14
14
  },
15
- "./package.json": "./package.json"
15
+ "./package.json": "./package.json",
16
+ "./test": "./test.js"
16
17
  },
17
18
  "files": [
18
19
  "**"
@@ -31,22 +32,22 @@
31
32
  "test:unit-with-coverage": "vitest run --coverage"
32
33
  },
33
34
  "dependencies": {
34
- "@devvit/protos": "0.12.6-next-2025-12-09-22-01-39-77cc3d62a.0",
35
- "@devvit/public-api": "0.12.6-next-2025-12-09-22-01-39-77cc3d62a.0",
36
- "@devvit/shared": "0.12.6-next-2025-12-09-22-01-39-77cc3d62a.0",
37
- "@devvit/shared-types": "0.12.6-next-2025-12-09-22-01-39-77cc3d62a.0",
38
- "@devvit/splash": "0.12.6-next-2025-12-09-22-01-39-77cc3d62a.0"
35
+ "@devvit/protos": "0.12.6-next-2025-12-10-21-30-51-8567b4083.0",
36
+ "@devvit/public-api": "0.12.6-next-2025-12-10-21-30-51-8567b4083.0",
37
+ "@devvit/shared": "0.12.6-next-2025-12-10-21-30-51-8567b4083.0",
38
+ "@devvit/shared-types": "0.12.6-next-2025-12-10-21-30-51-8567b4083.0",
39
+ "@devvit/splash": "0.12.6-next-2025-12-10-21-30-51-8567b4083.0"
39
40
  },
40
41
  "peerDependencies": {
41
42
  "@devvit/server": "*"
42
43
  },
43
44
  "devDependencies": {
44
- "@devvit/repo-tools": "0.12.6-next-2025-12-09-22-01-39-77cc3d62a.0",
45
- "@devvit/server": "0.12.6-next-2025-12-09-22-01-39-77cc3d62a.0",
46
- "@devvit/tsconfig": "0.12.6-next-2025-12-09-22-01-39-77cc3d62a.0",
45
+ "@devvit/repo-tools": "0.12.6-next-2025-12-10-21-30-51-8567b4083.0",
46
+ "@devvit/server": "0.12.6-next-2025-12-10-21-30-51-8567b4083.0",
47
+ "@devvit/tsconfig": "0.12.6-next-2025-12-10-21-30-51-8567b4083.0",
47
48
  "eslint": "9.11.1",
48
49
  "typescript": "5.8.3",
49
50
  "vitest": "1.6.1"
50
51
  },
51
- "gitHead": "8bfbd5035ccf97cdac44004ac41645c50cdd8a02"
52
+ "gitHead": "56e32304ebcb604200637d5e6d27f61ab3fc437b"
52
53
  }
package/plugin.js CHANGED
@@ -1,13 +1,11 @@
1
1
  import { FlairDefinition, GraphQLDefinition, LinksAndCommentsDefinition, ListingsDefinition, ModerationDefinition, ModNoteDefinition, NewModmailDefinition, PrivateMessagesDefinition, SubredditsDefinition, UsersDefinition, WidgetsDefinition, WikiDefinition, } from '@devvit/protos';
2
2
  import { UserActionsDefinition } from '@devvit/protos';
3
3
  import { getDevvitConfig } from '@devvit/shared-types/server/get-devvit-config.js';
4
- let redditApiPlugin;
5
- let userActionsPlugin;
6
4
  /**
7
5
  * @internal
8
6
  */
9
7
  export function getRedditApiPlugins() {
10
- return (redditApiPlugin ?? (redditApiPlugin = {
8
+ return {
11
9
  Flair: getDevvitConfig().use(FlairDefinition),
12
10
  GraphQL: getDevvitConfig().use(GraphQLDefinition),
13
11
  LinksAndComments: getDevvitConfig().use(LinksAndCommentsDefinition),
@@ -20,7 +18,7 @@ export function getRedditApiPlugins() {
20
18
  Users: getDevvitConfig().use(UsersDefinition),
21
19
  Widgets: getDevvitConfig().use(WidgetsDefinition),
22
20
  Wiki: getDevvitConfig().use(WikiDefinition),
23
- }));
21
+ };
24
22
  }
25
23
  /**
26
24
  * @internal
@@ -29,5 +27,5 @@ export function getUserActionsPlugin() {
29
27
  if (!getDevvitConfig().uses(UserActionsDefinition)) {
30
28
  throw new Error(`UserActions plugin is not enabled. To use 'runAs: "USER"', set 'permissions.reddit.asUser: [ "PERMISSION_SCOPE_NAME" ]' in your devvit.json file.`);
31
29
  }
32
- return (userActionsPlugin ?? (userActionsPlugin = getDevvitConfig().use(UserActionsDefinition)));
30
+ return getDevvitConfig().use(UserActionsDefinition);
33
31
  }
package/test.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ export * from './mocks/GraphQLMock.js';
2
+ export * from './mocks/LinksAndCommentsMock.js';
3
+ export * from './mocks/RedditPluginMock.js';
4
+ export * from './mocks/SubredditMock.js';
5
+ export * from './mocks/UserMock.js';
6
+ //# sourceMappingURL=test.d.ts.map
package/test.d.ts.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test.d.ts","sourceRoot":"","sources":["../src/test.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC;AACvC,cAAc,iCAAiC,CAAC;AAChD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,0BAA0B,CAAC;AACzC,cAAc,qBAAqB,CAAC"}
package/test.js ADDED
@@ -0,0 +1,5 @@
1
+ export * from './mocks/GraphQLMock.js';
2
+ export * from './mocks/LinksAndCommentsMock.js';
3
+ export * from './mocks/RedditPluginMock.js';
4
+ export * from './mocks/SubredditMock.js';
5
+ export * from './mocks/UserMock.js';