@devvit/reddit 0.12.6-next-2025-12-09-15-11-17-96a26acd9.0 → 0.12.6-next-2025-12-10-15-48-50-47f19f303.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":"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"}
@@ -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"}