@foru-ms/sdk 0.1.0 → 1.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 (53) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +189 -0
  3. package/dist/Client.d.ts +18 -0
  4. package/dist/Client.js +18 -0
  5. package/dist/index.d.ts +9 -0
  6. package/dist/index.js +9 -0
  7. package/dist/resources/Auth.d.ts +12 -0
  8. package/dist/resources/Auth.js +19 -0
  9. package/dist/resources/Integrations.d.ts +20 -0
  10. package/dist/resources/Integrations.js +30 -0
  11. package/dist/resources/Notifications.d.ts +32 -0
  12. package/dist/resources/Notifications.js +48 -0
  13. package/dist/resources/Posts.d.ts +13 -0
  14. package/dist/resources/Posts.js +55 -0
  15. package/dist/resources/PrivateMessages.d.ts +29 -0
  16. package/dist/resources/PrivateMessages.js +44 -0
  17. package/dist/resources/Reports.d.ts +46 -0
  18. package/dist/resources/Reports.js +56 -0
  19. package/dist/resources/Roles.d.ts +26 -0
  20. package/dist/resources/Roles.js +44 -0
  21. package/dist/resources/SSO.d.ts +17 -0
  22. package/dist/resources/SSO.js +25 -0
  23. package/dist/resources/Search.d.ts +11 -0
  24. package/dist/resources/Search.js +20 -0
  25. package/dist/resources/Stats.d.ts +13 -0
  26. package/dist/resources/Stats.js +22 -0
  27. package/dist/resources/Tags.d.ts +27 -0
  28. package/dist/resources/Tags.js +47 -0
  29. package/dist/resources/Threads.d.ts +14 -0
  30. package/dist/resources/Threads.js +61 -0
  31. package/dist/resources/Users.d.ts +47 -0
  32. package/dist/resources/Users.js +54 -0
  33. package/dist/resources/Webhooks.d.ts +35 -0
  34. package/dist/resources/Webhooks.js +44 -0
  35. package/dist/types.d.ts +149 -0
  36. package/package.json +17 -4
  37. package/src/Client.ts +27 -0
  38. package/src/index.ts +9 -0
  39. package/src/resources/Auth.ts +28 -0
  40. package/src/resources/Integrations.ts +39 -0
  41. package/src/resources/Notifications.ts +69 -0
  42. package/src/resources/Posts.ts +67 -0
  43. package/src/resources/PrivateMessages.ts +67 -0
  44. package/src/resources/Reports.ts +93 -0
  45. package/src/resources/Roles.ts +64 -0
  46. package/src/resources/SSO.ts +33 -0
  47. package/src/resources/Search.ts +27 -0
  48. package/src/resources/Stats.ts +31 -0
  49. package/src/resources/Tags.ts +68 -0
  50. package/src/resources/Threads.ts +74 -0
  51. package/src/resources/Users.ts +91 -0
  52. package/src/resources/Webhooks.ts +60 -0
  53. package/src/types.ts +165 -0
package/dist/types.d.ts CHANGED
@@ -135,4 +135,153 @@ export interface UserListResponse {
135
135
  export interface TagListResponse {
136
136
  tags: Tag[];
137
137
  nextTagCursor?: string;
138
+ count?: number;
139
+ }
140
+ export interface Notification {
141
+ id: string;
142
+ threadId?: string;
143
+ postId?: string;
144
+ privateMessageId?: string;
145
+ notifierId: string;
146
+ notifiedId: string;
147
+ type: string;
148
+ description?: string;
149
+ read: boolean;
150
+ createdAt: string;
151
+ extendedData?: Record<string, any>;
152
+ post?: Post;
153
+ thread?: Thread;
154
+ notifier?: User;
155
+ message?: string;
156
+ isSystem?: boolean;
157
+ }
158
+ export interface NotificationListResponse {
159
+ list: Notification[];
160
+ nextCursor?: string;
161
+ count: number;
162
+ }
163
+ export interface SearchResponse {
164
+ type?: 'tags' | 'posts' | 'threads' | 'users';
165
+ tags?: Tag[];
166
+ posts?: Post[];
167
+ threads?: Thread[];
168
+ nextCursor?: string;
169
+ }
170
+ export interface Webhook {
171
+ id: string;
172
+ name: string;
173
+ url: string;
174
+ events: {
175
+ events: string[];
176
+ } | string[];
177
+ active: boolean;
178
+ secret?: string;
179
+ createdAt: string;
180
+ updatedAt: string;
181
+ _count?: {
182
+ deliveries: number;
183
+ };
184
+ }
185
+ export interface WebhookListResponse {
186
+ webhooks: Webhook[];
187
+ }
188
+ export interface StatsResponse {
189
+ counts: {
190
+ threads: number;
191
+ posts: number;
192
+ users: number;
193
+ reports: number;
194
+ };
195
+ latest: {
196
+ id: string;
197
+ createdAt: string;
198
+ type: 'thread' | 'post' | 'user' | 'report';
199
+ [key: string]: any;
200
+ }[];
201
+ usage: Record<string, any>;
202
+ cursors: {
203
+ threadCursor: string | null;
204
+ postCursor: string | null;
205
+ userCursor: string | null;
206
+ reportCursor: string | null;
207
+ };
208
+ }
209
+ export interface Integration {
210
+ id: string;
211
+ type: 'SLACK' | 'DISCORD' | 'SALESFORCE' | 'HUBSPOT' | 'OKTA' | 'AUTH0';
212
+ name: string;
213
+ active: boolean;
214
+ createdAt: string;
215
+ config?: any;
216
+ }
217
+ export interface IntegrationListResponse {
218
+ integrations: Integration[];
219
+ }
220
+ export interface PrivateMessage {
221
+ id: string;
222
+ senderId: string;
223
+ recipientId: string;
224
+ title?: string;
225
+ body: string;
226
+ read: boolean;
227
+ parentId?: string;
228
+ children?: PrivateMessage[];
229
+ sender?: User;
230
+ recipient?: User;
231
+ createdAt: string;
232
+ updatedAt: string;
233
+ extendedData?: Record<string, any>;
234
+ }
235
+ export interface PrivateMessageListResponse {
236
+ privateMessages: PrivateMessage[];
237
+ nextPrivateMessageCursor?: string;
238
+ count: number;
239
+ }
240
+ export interface Report {
241
+ id: string;
242
+ reporterId: string;
243
+ reportedId?: string;
244
+ threadId?: string;
245
+ postId?: string;
246
+ privateMessageId?: string;
247
+ type: string;
248
+ description?: string;
249
+ read: boolean;
250
+ createdAt: string;
251
+ post?: Post;
252
+ thread?: Thread;
253
+ privateMessage?: PrivateMessage;
254
+ reported?: User;
255
+ extendedData?: Record<string, any>;
256
+ }
257
+ export interface ReportListResponse {
258
+ list: Report[];
259
+ nextCursor?: string;
260
+ count: number;
261
+ }
262
+ export interface Role {
263
+ id: string;
264
+ name: string;
265
+ description?: string;
266
+ color?: string;
267
+ users?: User[];
268
+ createdAt: string;
269
+ updatedAt: string;
270
+ extendedData?: Record<string, any>;
271
+ }
272
+ export interface RoleListResponse {
273
+ roles: Role[];
274
+ nextCursor?: string;
275
+ count: number;
276
+ }
277
+ export interface SSOProvider {
278
+ id: string;
279
+ provider: 'OKTA' | 'AUTH0' | 'SAML';
280
+ domain: string;
281
+ active: boolean;
282
+ createdAt: string;
283
+ config?: any;
284
+ }
285
+ export interface SSOProviderListResponse {
286
+ ssoProviders: SSOProvider[];
138
287
  }
package/package.json CHANGED
@@ -1,15 +1,28 @@
1
1
  {
2
2
  "name": "@foru-ms/sdk",
3
- "version": "0.1.0",
3
+ "version": "1.1.0",
4
+ "description": "JavaScript SDK for Foru.ms",
4
5
  "main": "dist/index.js",
5
6
  "types": "dist/index.d.ts",
6
7
  "scripts": {
7
8
  "build": "tsc",
8
9
  "prepublishOnly": "npm run build"
9
10
  },
10
- "keywords": [],
11
- "author": "",
12
- "license": "ISC",
11
+ "repository": {
12
+ "type": "git",
13
+ "url": "git+https://github.com/foru-ms/sdk.git"
14
+ },
15
+ "keywords": [
16
+ "forums",
17
+ "sdk",
18
+ "api",
19
+ "community",
20
+ "social",
21
+ "typescript",
22
+ "discussion"
23
+ ],
24
+ "author": "Foru.ms",
25
+ "license": "MIT",
13
26
  "dependencies": {
14
27
  "cross-fetch": "^3.1.5"
15
28
  },
package/src/Client.ts CHANGED
@@ -3,6 +3,15 @@ import { ThreadsResource } from './resources/Threads';
3
3
  import { PostsResource } from './resources/Posts';
4
4
  import { UsersResource } from './resources/Users';
5
5
  import { TagsResource } from './resources/Tags';
6
+ import { NotificationsResource } from './resources/Notifications';
7
+ import { SearchResource } from './resources/Search';
8
+ import { WebhooksResource } from './resources/Webhooks';
9
+ import { StatsResource } from './resources/Stats';
10
+ import { IntegrationsResource } from './resources/Integrations';
11
+ import { PrivateMessagesResource } from './resources/PrivateMessages';
12
+ import { ReportsResource } from './resources/Reports';
13
+ import { RolesResource } from './resources/Roles';
14
+ import { SSOResource } from './resources/SSO';
6
15
 
7
16
  // Polyfill fetch if needed (e.g. older Node versions)
8
17
  const fetch = globalThis.fetch || require('cross-fetch');
@@ -17,6 +26,15 @@ export class ForumClient {
17
26
  public posts: PostsResource;
18
27
  public users: UsersResource;
19
28
  public tags: TagsResource;
29
+ public notifications: NotificationsResource;
30
+ public search: SearchResource;
31
+ public webhooks: WebhooksResource;
32
+ public stats: StatsResource;
33
+ public integrations: IntegrationsResource;
34
+ public privateMessages: PrivateMessagesResource;
35
+ public reports: ReportsResource;
36
+ public roles: RolesResource;
37
+ public sso: SSOResource;
20
38
 
21
39
  constructor(options: { apiKey: string; baseUrl?: string }) {
22
40
  this.apiKey = options.apiKey;
@@ -27,6 +45,15 @@ export class ForumClient {
27
45
  this.posts = new PostsResource(this);
28
46
  this.users = new UsersResource(this);
29
47
  this.tags = new TagsResource(this);
48
+ this.notifications = new NotificationsResource(this);
49
+ this.search = new SearchResource(this);
50
+ this.webhooks = new WebhooksResource(this);
51
+ this.stats = new StatsResource(this);
52
+ this.integrations = new IntegrationsResource(this);
53
+ this.privateMessages = new PrivateMessagesResource(this);
54
+ this.reports = new ReportsResource(this);
55
+ this.roles = new RolesResource(this);
56
+ this.sso = new SSOResource(this);
30
57
  }
31
58
 
32
59
  public async request<T>(path: string, options: RequestInit = {}): Promise<T> {
package/src/index.ts CHANGED
@@ -5,3 +5,12 @@ export * from './resources/Threads';
5
5
  export * from './resources/Posts';
6
6
  export * from './resources/Users';
7
7
  export * from './resources/Tags';
8
+ export * from './resources/Notifications';
9
+ export * from './resources/Search';
10
+ export * from './resources/Webhooks';
11
+ export * from './resources/Stats';
12
+ export * from './resources/Integrations';
13
+ export * from './resources/PrivateMessages';
14
+ export * from './resources/Reports';
15
+ export * from './resources/Roles';
16
+ export * from './resources/SSO';
@@ -33,4 +33,32 @@ export class AuthResource {
33
33
  method: 'GET',
34
34
  });
35
35
  }
36
+
37
+ async forgotPassword(email: string): Promise<{ resetToken?: string; message?: string }> {
38
+ return this.client.request<{ resetToken?: string; message?: string }>('/auth/forgot-password', {
39
+ method: 'POST',
40
+ body: JSON.stringify({ email }),
41
+ });
42
+ }
43
+
44
+ async resetPassword(payload: {
45
+ password: string;
46
+ oldPassword?: string;
47
+ email?: string;
48
+ token?: string;
49
+ }): Promise<{ message: string }> {
50
+ const headers: Record<string, string> = {};
51
+ if (payload.token) {
52
+ headers['Authorization'] = `Bearer ${payload.token}`;
53
+ }
54
+
55
+ // Remove token from body
56
+ const { token, ...body } = payload;
57
+
58
+ return this.client.request<{ message: string }>('/auth/reset-password', {
59
+ method: 'POST',
60
+ headers,
61
+ body: JSON.stringify(body),
62
+ });
63
+ }
36
64
  }
@@ -0,0 +1,39 @@
1
+ import { ForumClient } from '../Client';
2
+ import { Integration, IntegrationListResponse } from '../types';
3
+
4
+ export class IntegrationsResource {
5
+ private client: ForumClient;
6
+
7
+ constructor(client: ForumClient) {
8
+ this.client = client;
9
+ }
10
+
11
+ async list(): Promise<IntegrationListResponse> {
12
+ return this.client.request<IntegrationListResponse>('/integrations', {
13
+ method: 'GET',
14
+ });
15
+ }
16
+
17
+ async create(payload: {
18
+ type: 'SLACK' | 'DISCORD' | 'SALESFORCE' | 'HUBSPOT' | 'OKTA' | 'AUTH0';
19
+ name: string;
20
+ config: any;
21
+ }): Promise<{ integration: Integration }> {
22
+ return this.client.request<{ integration: Integration }>('/integrations', {
23
+ method: 'POST',
24
+ body: JSON.stringify(payload),
25
+ });
26
+ }
27
+
28
+ async retrieve(id: string): Promise<{ integration: Integration }> {
29
+ return this.client.request<{ integration: Integration }>(`/integrations/${id}`, {
30
+ method: 'GET',
31
+ });
32
+ }
33
+
34
+ async delete(id: string): Promise<{ success: boolean }> {
35
+ return this.client.request<{ success: boolean }>(`/integrations/${id}`, {
36
+ method: 'DELETE',
37
+ });
38
+ }
39
+ }
@@ -0,0 +1,69 @@
1
+ import { ForumClient } from '../Client';
2
+ import { NotificationListResponse, Notification } from '../types';
3
+
4
+ export class NotificationsResource {
5
+ private client: ForumClient;
6
+
7
+ constructor(client: ForumClient) {
8
+ this.client = client;
9
+ }
10
+
11
+ async list(params: {
12
+ userId: string;
13
+ read?: boolean;
14
+ filter?: 'newest' | 'oldest';
15
+ cursor?: string;
16
+ }): Promise<NotificationListResponse> {
17
+ const searchParams = new URLSearchParams();
18
+ Object.entries(params).forEach(([key, value]) => {
19
+ if (value !== undefined) {
20
+ searchParams.append(key, String(value));
21
+ }
22
+ });
23
+
24
+ return this.client.request<NotificationListResponse>(`/notifications?${searchParams.toString()}`, {
25
+ method: 'GET',
26
+ });
27
+ }
28
+
29
+ async markAllAsRead(userId: string, read: boolean = true): Promise<{ count: number }> {
30
+ return this.client.request<{ count: number }>('/notifications', {
31
+ method: 'PATCH',
32
+ body: JSON.stringify({ userId, read }),
33
+ });
34
+ }
35
+
36
+ async retrieve(id: string): Promise<Notification> {
37
+ return this.client.request<Notification>(`/notification/${id}`, {
38
+ method: 'GET',
39
+ });
40
+ }
41
+
42
+ async update(id: string, payload: { read: boolean }): Promise<Notification> {
43
+ return this.client.request<Notification>(`/notification/${id}`, {
44
+ method: 'PATCH',
45
+ body: JSON.stringify(payload),
46
+ });
47
+ }
48
+
49
+ async delete(id: string): Promise<Notification & { deleted: boolean }> {
50
+ return this.client.request<Notification & { deleted: boolean }>(`/notification/${id}`, {
51
+ method: 'DELETE',
52
+ });
53
+ }
54
+ async create(payload: {
55
+ threadId?: string;
56
+ postId?: string;
57
+ privateMessageId?: string;
58
+ notifierId: string;
59
+ notifiedId: string;
60
+ type: string;
61
+ description?: string;
62
+ extendedData?: Record<string, any>;
63
+ }): Promise<Notification> {
64
+ return this.client.request<Notification>('/notification', {
65
+ method: 'POST',
66
+ body: JSON.stringify(payload),
67
+ });
68
+ }
69
+ }
@@ -55,4 +55,71 @@ export class PostsResource {
55
55
  body: payload ? JSON.stringify(payload) : undefined,
56
56
  });
57
57
  }
58
+ async getChildren(id: string, params?: {
59
+ query?: string;
60
+ cursor?: string;
61
+ filter?: 'newest' | 'oldest';
62
+ }): Promise<any> {
63
+ const searchParams = new URLSearchParams();
64
+ if (params) {
65
+ Object.entries(params).forEach(([key, value]) => {
66
+ if (value !== undefined) {
67
+ searchParams.append(key, value as string);
68
+ }
69
+ });
70
+ }
71
+ return this.client.request(`/post/${id}/posts?${searchParams.toString()}`, { method: 'GET' });
72
+ }
73
+
74
+ async like(id: string, userId?: string, extendedData?: any): Promise<any> {
75
+ return this.client.request(`/post/${id}/likes`, {
76
+ method: 'POST',
77
+ body: JSON.stringify({ userId, extendedData }),
78
+ });
79
+ }
80
+
81
+ async unlike(id: string, userId: string): Promise<any> {
82
+ return this.client.request(`/post/${id}/likes?userId=${userId}`, {
83
+ method: 'DELETE',
84
+ });
85
+ }
86
+
87
+ async dislike(id: string, userId?: string, extendedData?: any): Promise<any> {
88
+ return this.client.request(`/post/${id}/dislikes`, {
89
+ method: 'POST',
90
+ body: JSON.stringify({ userId, extendedData }),
91
+ });
92
+ }
93
+
94
+ async undislike(id: string, userId: string): Promise<any> {
95
+ return this.client.request(`/post/${id}/dislikes?userId=${userId}`, {
96
+ method: 'DELETE',
97
+ });
98
+ }
99
+
100
+ async upvote(id: string, userId?: string, extendedData?: any): Promise<any> {
101
+ return this.client.request(`/post/${id}/upvotes`, {
102
+ method: 'POST',
103
+ body: JSON.stringify({ userId, extendedData }),
104
+ });
105
+ }
106
+
107
+ async unupvote(id: string, userId: string): Promise<any> {
108
+ return this.client.request(`/post/${id}/upvotes?userId=${userId}`, {
109
+ method: 'DELETE',
110
+ });
111
+ }
112
+
113
+ async downvote(id: string, userId?: string, extendedData?: any): Promise<any> {
114
+ return this.client.request(`/post/${id}/downvotes`, {
115
+ method: 'POST',
116
+ body: JSON.stringify({ userId, extendedData }),
117
+ });
118
+ }
119
+
120
+ async undownvote(id: string, userId: string): Promise<any> {
121
+ return this.client.request(`/post/${id}/downvotes?userId=${userId}`, {
122
+ method: 'DELETE',
123
+ });
124
+ }
58
125
  }
@@ -0,0 +1,67 @@
1
+ import { ForumClient } from '../Client';
2
+ import { PrivateMessage, PrivateMessageListResponse } from '../types';
3
+
4
+ export class PrivateMessagesResource {
5
+ private client: ForumClient;
6
+
7
+ constructor(client: ForumClient) {
8
+ this.client = client;
9
+ }
10
+
11
+ async list(params?: {
12
+ query?: string;
13
+ userId?: string;
14
+ filter?: 'newest' | 'oldest';
15
+ cursor?: string;
16
+ }): Promise<PrivateMessageListResponse> {
17
+ const searchParams = new URLSearchParams();
18
+ if (params) {
19
+ Object.entries(params).forEach(([key, value]) => {
20
+ if (value !== undefined) {
21
+ searchParams.append(key, value as string);
22
+ }
23
+ });
24
+ }
25
+
26
+ return this.client.request<PrivateMessageListResponse>(`/private-messages?${searchParams.toString()}`, {
27
+ method: 'GET',
28
+ });
29
+ }
30
+
31
+ async create(payload: {
32
+ title?: string;
33
+ body: string;
34
+ recipientId: string;
35
+ senderId?: string; // Optional if inferred from token
36
+ extendedData?: Record<string, any>;
37
+ }): Promise<PrivateMessage> {
38
+ return this.client.request<PrivateMessage>('/private-message', {
39
+ method: 'POST',
40
+ body: JSON.stringify(payload),
41
+ });
42
+ }
43
+
44
+ async retrieve(id: string): Promise<PrivateMessage> {
45
+ return this.client.request<PrivateMessage>(`/private-message/${id}`, {
46
+ method: 'GET',
47
+ });
48
+ }
49
+
50
+ async reply(id: string, payload: {
51
+ body: string;
52
+ senderId: string;
53
+ recipientId: string;
54
+ extendedData?: Record<string, any>;
55
+ }): Promise<PrivateMessage> {
56
+ return this.client.request<PrivateMessage>(`/private-message/${id}`, {
57
+ method: 'POST',
58
+ body: JSON.stringify(payload),
59
+ });
60
+ }
61
+
62
+ async delete(id: string): Promise<PrivateMessage & { deleted: boolean }> {
63
+ return this.client.request<PrivateMessage & { deleted: boolean }>(`/private-message/${id}`, {
64
+ method: 'DELETE',
65
+ });
66
+ }
67
+ }
@@ -0,0 +1,93 @@
1
+ import { ForumClient } from '../Client';
2
+ import { Report, ReportListResponse } from '../types';
3
+
4
+ export class ReportsResource {
5
+ private client: ForumClient;
6
+
7
+ constructor(client: ForumClient) {
8
+ this.client = client;
9
+ }
10
+
11
+ async list(params?: {
12
+ reporterId?: string;
13
+ reportedId?: string;
14
+ read?: boolean;
15
+ cursor?: string;
16
+ filter?: 'newest' | 'oldest';
17
+ }): Promise<ReportListResponse> {
18
+ const searchParams = new URLSearchParams();
19
+ if (params) {
20
+ Object.entries(params).forEach(([key, value]) => {
21
+ if (value !== undefined) {
22
+ searchParams.append(key, String(value));
23
+ }
24
+ });
25
+ }
26
+
27
+ return this.client.request<ReportListResponse>(`/reports?${searchParams.toString()}`, {
28
+ method: 'GET',
29
+ });
30
+ }
31
+
32
+ async create(payload: {
33
+ reporterId: string;
34
+ reportedId?: string;
35
+ threadId?: string;
36
+ postId?: string;
37
+ privateMessageId?: string;
38
+ type?: string;
39
+ description?: string;
40
+ extendedData?: Record<string, any>;
41
+ }): Promise<Report> {
42
+ return this.client.request<Report>('/report', {
43
+ method: 'POST',
44
+ body: JSON.stringify(payload),
45
+ });
46
+ }
47
+
48
+ async batchUpdate(payload: {
49
+ reportIds: string[];
50
+ read: boolean;
51
+ }): Promise<{ count?: number; message?: string }> {
52
+ return this.client.request<{ count?: number; message?: string }>('/reports', {
53
+ method: 'PATCH',
54
+ body: JSON.stringify(payload),
55
+ });
56
+ }
57
+
58
+ async retrieve(id: string): Promise<Report> {
59
+ return this.client.request<Report>(`/report/${id}`, {
60
+ method: 'GET',
61
+ });
62
+ }
63
+
64
+ async update(id: string, payload: {
65
+ threadId?: string;
66
+ postId?: string;
67
+ privateMessageId?: string;
68
+ reportedId?: string;
69
+ reporterId?: string;
70
+ type?: string;
71
+ description?: string;
72
+ read?: boolean;
73
+ extendedData?: Record<string, any>;
74
+ }): Promise<Report> {
75
+ return this.client.request<Report>(`/report/${id}`, {
76
+ method: 'PUT',
77
+ body: JSON.stringify(payload),
78
+ });
79
+ }
80
+
81
+ async delete(id: string): Promise<Report & { deleted: boolean }> {
82
+ return this.client.request<Report & { deleted: boolean }>(`/report/${id}`, {
83
+ method: 'DELETE',
84
+ });
85
+ }
86
+
87
+ async updateStatus(id: string, read: boolean): Promise<Report> {
88
+ return this.client.request<Report>(`/report/${id}`, {
89
+ method: 'PATCH',
90
+ body: JSON.stringify({ read }),
91
+ });
92
+ }
93
+ }
@@ -0,0 +1,64 @@
1
+ import { ForumClient } from '../Client';
2
+ import { Role, RoleListResponse } from '../types';
3
+
4
+ export class RolesResource {
5
+ private client: ForumClient;
6
+
7
+ constructor(client: ForumClient) {
8
+ this.client = client;
9
+ }
10
+
11
+ async list(params?: {
12
+ filter?: 'newest' | 'oldest';
13
+ cursor?: string;
14
+ }): Promise<RoleListResponse> {
15
+ const searchParams = new URLSearchParams();
16
+ if (params) {
17
+ Object.entries(params).forEach(([key, value]) => {
18
+ if (value !== undefined) {
19
+ searchParams.append(key, value as string);
20
+ }
21
+ });
22
+ }
23
+
24
+ return this.client.request<RoleListResponse>(`/roles?${searchParams.toString()}`, {
25
+ method: 'GET',
26
+ });
27
+ }
28
+
29
+ async create(payload: {
30
+ name: string;
31
+ description?: string;
32
+ color?: string;
33
+ extendedData?: Record<string, any>;
34
+ }): Promise<Role> {
35
+ return this.client.request<Role>('/role', {
36
+ method: 'POST',
37
+ body: JSON.stringify(payload),
38
+ });
39
+ }
40
+
41
+ async retrieve(id: string): Promise<Role> {
42
+ return this.client.request<Role>(`/role/${id}`, {
43
+ method: 'GET',
44
+ });
45
+ }
46
+
47
+ async update(id: string, payload: {
48
+ name?: string;
49
+ description?: string;
50
+ color?: string;
51
+ extendedData?: Record<string, any>;
52
+ }): Promise<Role> {
53
+ return this.client.request<Role>(`/role/${id}`, {
54
+ method: 'PUT',
55
+ body: JSON.stringify(payload),
56
+ });
57
+ }
58
+
59
+ async delete(id: string): Promise<Role & { deleted: boolean }> {
60
+ return this.client.request<Role & { deleted: boolean }>(`/role/${id}`, {
61
+ method: 'DELETE',
62
+ });
63
+ }
64
+ }