@roundtable-bb/sdk 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json ADDED
@@ -0,0 +1,24 @@
1
+ {
2
+ "name": "@roundtable-bb/sdk",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "main": "./dist/index.js",
6
+ "module": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ "./package.json": "./package.json",
10
+ ".": {
11
+ "@org/source": "./src/index.ts",
12
+ "types": "./dist/index.d.ts",
13
+ "import": "./dist/index.js",
14
+ "default": "./dist/index.js"
15
+ }
16
+ },
17
+ "devDependencies": {
18
+ "esbuild": "*"
19
+ },
20
+ "peerDependencies": {
21
+ "@roundtable-bb/types": "*",
22
+ "zod": "^4.0.0"
23
+ }
24
+ }
package/project.json ADDED
@@ -0,0 +1,28 @@
1
+ {
2
+ "$schema": "../../node_modules/nx/schemas/project-schema.json",
3
+ "name": "@roundtable-bb/sdk",
4
+ "projectType": "library",
5
+ "sourceRoot": "packages/sdk/src",
6
+ "targets": {
7
+ "codegen": {
8
+ "executor": "nx:run-commands",
9
+ "options": {
10
+ "commands": [
11
+ "tsx --conditions @org/source packages/sdk/codegen/extract-spec.ts",
12
+ "tsx --conditions @org/source packages/sdk/codegen/generate.ts"
13
+ ],
14
+ "sequential": true,
15
+ "cwd": "{workspaceRoot}"
16
+ },
17
+ "dependsOn": []
18
+ },
19
+ "bundle": {
20
+ "executor": "nx:run-commands",
21
+ "options": {
22
+ "command": "node packages/sdk/codegen/bundle.mjs",
23
+ "cwd": "{workspaceRoot}"
24
+ },
25
+ "dependsOn": ["build"]
26
+ }
27
+ }
28
+ }
@@ -0,0 +1,229 @@
1
+ // AUTO-GENERATED — do not edit manually.
2
+ // Run `nx run @roundtable-bb/sdk:codegen` to regenerate.
3
+
4
+ import type { ApiKey, Category, CreateApiKey, CreateCategory, CreateGroup, CreatePost, CreateTenant, CreateThread, CreatedApiKey, GrantPlatformOwner, Group, Id, Notification, PaginatedResponse, PlatformSetting, Post, SearchResponse, SetGroupCategories, SetGroupPermissions, SetThreadReadStatus, SetUserMembership, Tenant, TenantToken, Thread, ThreadReadStatus, UpdateCategory, UpdateGroup, UpdatePlatformSetting, UpdateThread, UpdateUserProfile, UserMembership, UserProfile } from '@roundtable-bb/types'
5
+ import { request, type RoundtableClientOpts } from '../request.js'
6
+
7
+ export class RoundtableClient {
8
+ constructor(private readonly opts: RoundtableClientOpts) {}
9
+
10
+ /** Create a platform-scoped API key (returned once in full) */
11
+ createApiKey(body: CreateApiKey): Promise<CreatedApiKey> {
12
+ return request(this.opts, 'POST', '/platform/api-keys', { body })
13
+ }
14
+
15
+ /** Create a category (admin) */
16
+ createCategory(body: CreateCategory): Promise<Category> {
17
+ return request(this.opts, 'POST', '/categories', { body })
18
+ }
19
+
20
+ /** Create a group (admin) */
21
+ createGroup(body: CreateGroup): Promise<Group> {
22
+ return request(this.opts, 'POST', '/groups', { body })
23
+ }
24
+
25
+ /** Create a post in a thread */
26
+ createPost(params: { threadId: string }, body: CreatePost): Promise<Post> {
27
+ return request(this.opts, 'POST', `/threads/${params.threadId}/posts`, { body })
28
+ }
29
+
30
+ /** Create a new tenant (requires allow_tenant_creation platform setting or platform owner) */
31
+ createTenant(body: CreateTenant): Promise<Tenant> {
32
+ return request(this.opts, 'POST', '/tenants', { body })
33
+ }
34
+
35
+ /** Create a thread (and its first post) */
36
+ createThread(params: { categoryId: string }, body: CreateThread): Promise<Thread> {
37
+ return request(this.opts, 'POST', `/categories/${params.categoryId}/threads`, { body })
38
+ }
39
+
40
+ /** Delete a platform-scoped API key */
41
+ deleteApiKey(params: { id: string }): Promise<void> {
42
+ return request(this.opts, 'DELETE', `/platform/api-keys/${params.id}`)
43
+ }
44
+
45
+ /** Delete a category (admin) */
46
+ deleteCategory(params: { id: string }): Promise<void> {
47
+ return request(this.opts, 'DELETE', `/categories/${params.id}`)
48
+ }
49
+
50
+ /** Delete a group (admin) */
51
+ deleteGroup(params: { id: string }): Promise<void> {
52
+ return request(this.opts, 'DELETE', `/groups/${params.id}`)
53
+ }
54
+
55
+ /** Delete a notification */
56
+ deleteNotification(params: { id: string }): Promise<void> {
57
+ return request(this.opts, 'DELETE', `/notifications/${params.id}`)
58
+ }
59
+
60
+ /** Soft-delete a post */
61
+ deletePost(params: { id: string }): Promise<void> {
62
+ return request(this.opts, 'DELETE', `/posts/${params.id}`)
63
+ }
64
+
65
+ /** Delete a thread */
66
+ deleteThread(params: { id: string }): Promise<void> {
67
+ return request(this.opts, 'DELETE', `/threads/${params.id}`)
68
+ }
69
+
70
+ /** Exchange session cookie for a short-lived tenant JWT */
71
+ exchangeTenantToken(): Promise<TenantToken> {
72
+ return request(this.opts, 'POST', '/tenant-token')
73
+ }
74
+
75
+ /** Get a single category */
76
+ getCategory(params: { id: string }): Promise<Category> {
77
+ return request(this.opts, 'GET', `/categories/${params.id}`)
78
+ }
79
+
80
+ /** Get a group */
81
+ getGroup(params: { id: string }): Promise<Group> {
82
+ return request(this.opts, 'GET', `/groups/${params.id}`)
83
+ }
84
+
85
+ /** Get own profile */
86
+ getMe(): Promise<UserProfile> {
87
+ return request(this.opts, 'GET', '/users/me')
88
+ }
89
+
90
+ /** Get a single thread */
91
+ getThread(params: { id: string }): Promise<Thread> {
92
+ return request(this.opts, 'GET', `/threads/${params.id}`)
93
+ }
94
+
95
+ /** Get read status for the current user in a thread */
96
+ getThreadReadStatus(params: { id: string }): Promise<ThreadReadStatus> {
97
+ return request(this.opts, 'GET', `/threads/${params.id}/read-status`)
98
+ }
99
+
100
+ /** Get a user profile by ID */
101
+ getUser(params: { id: string }): Promise<UserProfile> {
102
+ return request(this.opts, 'GET', `/users/${params.id}`)
103
+ }
104
+
105
+ /** Get user membership in the current forum */
106
+ getUserMembership(params: { id: string }): Promise<UserMembership> {
107
+ return request(this.opts, 'GET', `/users/${params.id}/membership`)
108
+ }
109
+
110
+ /** Grant platform owner status to a user (platform owners only) */
111
+ grantPlatformOwner(body: GrantPlatformOwner): Promise<void> {
112
+ return request(this.opts, 'POST', '/platform/owners', { body })
113
+ }
114
+
115
+ /** List your platform-scoped API keys */
116
+ listApiKeys(): Promise<ApiKey[]> {
117
+ return request(this.opts, 'GET', '/platform/api-keys')
118
+ }
119
+
120
+ /** List visible categories for the requesting user */
121
+ listCategories(): Promise<Category[]> {
122
+ return request(this.opts, 'GET', '/categories')
123
+ }
124
+
125
+ /** List groups */
126
+ listGroups(): Promise<Group[]> {
127
+ return request(this.opts, 'GET', '/groups')
128
+ }
129
+
130
+ /** Get unified notification inbox */
131
+ listNotifications(query?: { cursor?: Id; limit?: number; unreadOnly?: boolean }): Promise<PaginatedResponse<Notification>> {
132
+ return request(this.opts, 'GET', '/notifications', { query })
133
+ }
134
+
135
+ /** List platform owner user IDs (platform owners only) */
136
+ listPlatformOwners(): Promise<string[]> {
137
+ return request(this.opts, 'GET', '/platform/owners')
138
+ }
139
+
140
+ /** List all platform settings (platform owners only) */
141
+ listPlatformSettings(): Promise<PlatformSetting[]> {
142
+ return request(this.opts, 'GET', '/platform/settings')
143
+ }
144
+
145
+ /** List posts in a thread — cursor pagination or anchor via ?from=postId */
146
+ listPosts(params: { threadId: string }, query?: { cursor?: Id; limit?: number; from?: Id }): Promise<PaginatedResponse<Post>> {
147
+ return request(this.opts, 'GET', `/threads/${params.threadId}/posts`, { query })
148
+ }
149
+
150
+ /** List threads in a category */
151
+ listThreads(params: { categoryId: string }, query?: { cursor?: Id; limit?: number }): Promise<PaginatedResponse<Thread>> {
152
+ return request(this.opts, 'GET', `/categories/${params.categoryId}/threads`, { query })
153
+ }
154
+
155
+ /** Mark a notification as read */
156
+ markNotificationRead(params: { id: string }): Promise<Notification> {
157
+ return request(this.opts, 'PATCH', `/notifications/${params.id}/read`)
158
+ }
159
+
160
+ /** Revoke platform owner status from a user (platform owners only) */
161
+ revokePlatformOwner(params: { userId: string }): Promise<void> {
162
+ return request(this.opts, 'DELETE', `/platform/owners/${params.userId}`)
163
+ }
164
+
165
+ /** Full-text search across threads and posts (visible categories only) */
166
+ search(query?: { q: string; categoryId?: Id; limit?: number }): Promise<SearchResponse> {
167
+ return request(this.opts, 'GET', '/search', { query })
168
+ }
169
+
170
+ /** Set category visibility for a group (admin) */
171
+ setGroupCategories(params: { id: string }, body: SetGroupCategories): Promise<Group> {
172
+ return request(this.opts, 'PUT', `/groups/${params.id}/categories`, { body })
173
+ }
174
+
175
+ /** Replace all permissions for a group (admin) */
176
+ setGroupPermissions(params: { id: string }, body: SetGroupPermissions): Promise<Group> {
177
+ return request(this.opts, 'PUT', `/groups/${params.id}/permissions`, { body })
178
+ }
179
+
180
+ /** Mark a thread as read up to a given post */
181
+ setThreadReadStatus(params: { id: string }, body: SetThreadReadStatus): Promise<void> {
182
+ return request(this.opts, 'PUT', `/threads/${params.id}/read-status`, { body })
183
+ }
184
+
185
+ /** Set user group in the current forum (admin) */
186
+ setUserMembership(params: { id: string }, body: SetUserMembership): Promise<UserMembership> {
187
+ return request(this.opts, 'PUT', `/users/${params.id}/membership`, { body })
188
+ }
189
+
190
+ /** Subscribe to a thread */
191
+ subscribeThread(params: { id: string }): Promise<void> {
192
+ return request(this.opts, 'POST', `/threads/${params.id}/subscribe`)
193
+ }
194
+
195
+ /** Unsubscribe from a thread */
196
+ unsubscribeThread(params: { id: string }): Promise<void> {
197
+ return request(this.opts, 'DELETE', `/threads/${params.id}/subscribe`)
198
+ }
199
+
200
+ /** Update a category (admin) */
201
+ updateCategory(params: { id: string }, body: UpdateCategory): Promise<Category> {
202
+ return request(this.opts, 'PATCH', `/categories/${params.id}`, { body })
203
+ }
204
+
205
+ /** Update a group (admin) */
206
+ updateGroup(params: { id: string }, body: UpdateGroup): Promise<Group> {
207
+ return request(this.opts, 'PATCH', `/groups/${params.id}`, { body })
208
+ }
209
+
210
+ /** Update own profile */
211
+ updateMe(body: UpdateUserProfile): Promise<UserProfile> {
212
+ return request(this.opts, 'PATCH', '/users/me', { body })
213
+ }
214
+
215
+ /** Update a platform setting (platform owners only) */
216
+ updatePlatformSetting(params: { key: string }, body: UpdatePlatformSetting): Promise<PlatformSetting> {
217
+ return request(this.opts, 'PATCH', `/platform/settings/${params.key}`, { body })
218
+ }
219
+
220
+ /** Edit a post (author or moderator) */
221
+ updatePost(params: { id: string }, body: CreatePost): Promise<Post> {
222
+ return request(this.opts, 'PATCH', `/posts/${params.id}`, { body })
223
+ }
224
+
225
+ /** Update a thread (title, pin, lock, move) */
226
+ updateThread(params: { id: string }, body: UpdateThread): Promise<Thread> {
227
+ return request(this.opts, 'PATCH', `/threads/${params.id}`, { body })
228
+ }
229
+ }
package/src/index.ts ADDED
@@ -0,0 +1,3 @@
1
+ export { RoundtableClient } from './generated/client.js'
2
+ export type { RoundtableClientOpts } from './request.js'
3
+ export type * from '@roundtable-bb/types'
package/src/request.ts ADDED
@@ -0,0 +1,35 @@
1
+ export interface RoundtableClientOpts {
2
+ baseUrl: string
3
+ token?: string
4
+ }
5
+
6
+ export async function request<T>(
7
+ opts: RoundtableClientOpts,
8
+ method: string,
9
+ path: string,
10
+ options?: { body?: unknown; query?: Record<string, unknown> },
11
+ ): Promise<T> {
12
+ const url = new URL(`${opts.baseUrl}${path}`)
13
+ if (options?.query) {
14
+ for (const [k, v] of Object.entries(options.query)) {
15
+ if (v !== undefined && v !== null) url.searchParams.set(k, String(v))
16
+ }
17
+ }
18
+
19
+ const res = await fetch(url.toString(), {
20
+ method,
21
+ headers: {
22
+ ...(options?.body !== undefined ? { 'Content-Type': 'application/json' } : {}),
23
+ ...(opts.token ? { Authorization: `Bearer ${opts.token}` } : {}),
24
+ },
25
+ body: options?.body !== undefined ? JSON.stringify(options.body) : undefined,
26
+ })
27
+
28
+ if (res.status === 204) return undefined as T
29
+ if (!res.ok) {
30
+ const err = await res.json().catch(() => ({ message: res.statusText }))
31
+ const msg = (err as { message?: string }).message ?? res.statusText
32
+ throw Object.assign(new Error(msg), { status: res.status })
33
+ }
34
+ return res.json() as Promise<T>
35
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,8 @@
1
+ {
2
+ "extends": "../../tsconfig.base.json",
3
+ "files": [],
4
+ "include": [],
5
+ "references": [
6
+ { "path": "./tsconfig.lib.json" }
7
+ ]
8
+ }
@@ -0,0 +1,13 @@
1
+ {
2
+ "extends": "../../tsconfig.base.json",
3
+ "compilerOptions": {
4
+ "rootDir": "src",
5
+ "outDir": "dist",
6
+ "tsBuildInfoFile": "dist/tsconfig.lib.tsbuildinfo",
7
+ "emitDeclarationOnly": false,
8
+ "forceConsistentCasingInFileNames": true,
9
+ "types": ["node"]
10
+ },
11
+ "include": ["src/**/*.ts"],
12
+ "references": []
13
+ }