@nurama/sdk 0.0.0-stage → 1.4.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 (220) hide show
  1. package/LICENSE +202 -0
  2. package/NOTICE +5 -0
  3. package/README.md +1080 -2
  4. package/dist/BotClient.d.ts +66 -0
  5. package/dist/BotClient.d.ts.map +1 -0
  6. package/dist/BotClient.js +68 -0
  7. package/dist/BotClient.js.map +1 -0
  8. package/dist/NuramaClient.d.ts +448 -0
  9. package/dist/NuramaClient.d.ts.map +1 -0
  10. package/dist/NuramaClient.js +864 -0
  11. package/dist/NuramaClient.js.map +1 -0
  12. package/dist/browser/nurama-bot-sdk.js +11780 -0
  13. package/dist/browser/nurama-bot-sdk.min.js +1 -0
  14. package/dist/browser/nurama-sdk.js +11732 -0
  15. package/dist/browser/nurama-sdk.min.js +1 -0
  16. package/dist/routes/ai.d.ts +280 -0
  17. package/dist/routes/ai.d.ts.map +1 -0
  18. package/dist/routes/ai.js +173 -0
  19. package/dist/routes/ai.js.map +1 -0
  20. package/dist/routes/asset.d.ts +493 -0
  21. package/dist/routes/asset.d.ts.map +1 -0
  22. package/dist/routes/asset.js +848 -0
  23. package/dist/routes/asset.js.map +1 -0
  24. package/dist/routes/auth.d.ts +218 -0
  25. package/dist/routes/auth.d.ts.map +1 -0
  26. package/dist/routes/auth.js +454 -0
  27. package/dist/routes/auth.js.map +1 -0
  28. package/dist/routes/blogPosts.d.ts +17 -0
  29. package/dist/routes/blogPosts.d.ts.map +1 -0
  30. package/dist/routes/blogPosts.js +29 -0
  31. package/dist/routes/blogPosts.js.map +1 -0
  32. package/dist/routes/board.d.ts +187 -0
  33. package/dist/routes/board.d.ts.map +1 -0
  34. package/dist/routes/board.js +270 -0
  35. package/dist/routes/board.js.map +1 -0
  36. package/dist/routes/bot.d.ts +147 -0
  37. package/dist/routes/bot.d.ts.map +1 -0
  38. package/dist/routes/bot.js +157 -0
  39. package/dist/routes/bot.js.map +1 -0
  40. package/dist/routes/chat.d.ts +842 -0
  41. package/dist/routes/chat.d.ts.map +1 -0
  42. package/dist/routes/chat.js +863 -0
  43. package/dist/routes/chat.js.map +1 -0
  44. package/dist/routes/chatAi.d.ts +51 -0
  45. package/dist/routes/chatAi.d.ts.map +1 -0
  46. package/dist/routes/chatAi.js +109 -0
  47. package/dist/routes/chatAi.js.map +1 -0
  48. package/dist/routes/config.d.ts +11 -0
  49. package/dist/routes/config.d.ts.map +1 -0
  50. package/dist/routes/config.js +24 -0
  51. package/dist/routes/config.js.map +1 -0
  52. package/dist/routes/convo.d.ts +169 -0
  53. package/dist/routes/convo.d.ts.map +1 -0
  54. package/dist/routes/convo.js +284 -0
  55. package/dist/routes/convo.js.map +1 -0
  56. package/dist/routes/credits.d.ts +82 -0
  57. package/dist/routes/credits.d.ts.map +1 -0
  58. package/dist/routes/credits.js +49 -0
  59. package/dist/routes/credits.js.map +1 -0
  60. package/dist/routes/device.d.ts +74 -0
  61. package/dist/routes/device.d.ts.map +1 -0
  62. package/dist/routes/device.js +122 -0
  63. package/dist/routes/device.js.map +1 -0
  64. package/dist/routes/folder.d.ts +75 -0
  65. package/dist/routes/folder.d.ts.map +1 -0
  66. package/dist/routes/folder.js +99 -0
  67. package/dist/routes/folder.js.map +1 -0
  68. package/dist/routes/invite.d.ts +61 -0
  69. package/dist/routes/invite.d.ts.map +1 -0
  70. package/dist/routes/invite.js +86 -0
  71. package/dist/routes/invite.js.map +1 -0
  72. package/dist/routes/joinLink.d.ts +38 -0
  73. package/dist/routes/joinLink.d.ts.map +1 -0
  74. package/dist/routes/joinLink.js +81 -0
  75. package/dist/routes/joinLink.js.map +1 -0
  76. package/dist/routes/membership.d.ts +116 -0
  77. package/dist/routes/membership.d.ts.map +1 -0
  78. package/dist/routes/membership.js +183 -0
  79. package/dist/routes/membership.js.map +1 -0
  80. package/dist/routes/notification.d.ts +103 -0
  81. package/dist/routes/notification.d.ts.map +1 -0
  82. package/dist/routes/notification.js +89 -0
  83. package/dist/routes/notification.js.map +1 -0
  84. package/dist/routes/payment.d.ts +56 -0
  85. package/dist/routes/payment.d.ts.map +1 -0
  86. package/dist/routes/payment.js +78 -0
  87. package/dist/routes/payment.js.map +1 -0
  88. package/dist/routes/product.d.ts +43 -0
  89. package/dist/routes/product.d.ts.map +1 -0
  90. package/dist/routes/product.js +53 -0
  91. package/dist/routes/product.js.map +1 -0
  92. package/dist/routes/project.d.ts +821 -0
  93. package/dist/routes/project.d.ts.map +1 -0
  94. package/dist/routes/project.js +1153 -0
  95. package/dist/routes/project.js.map +1 -0
  96. package/dist/routes/public.d.ts +269 -0
  97. package/dist/routes/public.d.ts.map +1 -0
  98. package/dist/routes/public.js +412 -0
  99. package/dist/routes/public.js.map +1 -0
  100. package/dist/routes/scratch.d.ts +70 -0
  101. package/dist/routes/scratch.d.ts.map +1 -0
  102. package/dist/routes/scratch.js +67 -0
  103. package/dist/routes/scratch.js.map +1 -0
  104. package/dist/routes/settings.d.ts +102 -0
  105. package/dist/routes/settings.d.ts.map +1 -0
  106. package/dist/routes/settings.js +94 -0
  107. package/dist/routes/settings.js.map +1 -0
  108. package/dist/routes/shortlink.d.ts +79 -0
  109. package/dist/routes/shortlink.d.ts.map +1 -0
  110. package/dist/routes/shortlink.js +25 -0
  111. package/dist/routes/shortlink.js.map +1 -0
  112. package/dist/routes/socket.d.ts +108 -0
  113. package/dist/routes/socket.d.ts.map +1 -0
  114. package/dist/routes/socket.js +555 -0
  115. package/dist/routes/socket.js.map +1 -0
  116. package/dist/routes/storage.d.ts +44 -0
  117. package/dist/routes/storage.d.ts.map +1 -0
  118. package/dist/routes/storage.js +49 -0
  119. package/dist/routes/storage.js.map +1 -0
  120. package/dist/routes/subscription.d.ts +184 -0
  121. package/dist/routes/subscription.d.ts.map +1 -0
  122. package/dist/routes/subscription.js +219 -0
  123. package/dist/routes/subscription.js.map +1 -0
  124. package/dist/routes/supportChat.d.ts +40 -0
  125. package/dist/routes/supportChat.d.ts.map +1 -0
  126. package/dist/routes/supportChat.js +53 -0
  127. package/dist/routes/supportChat.js.map +1 -0
  128. package/dist/routes/supportTicket.d.ts +89 -0
  129. package/dist/routes/supportTicket.d.ts.map +1 -0
  130. package/dist/routes/supportTicket.js +54 -0
  131. package/dist/routes/supportTicket.js.map +1 -0
  132. package/dist/routes/tag.d.ts +72 -0
  133. package/dist/routes/tag.d.ts.map +1 -0
  134. package/dist/routes/tag.js +81 -0
  135. package/dist/routes/tag.js.map +1 -0
  136. package/dist/routes/task.d.ts +252 -0
  137. package/dist/routes/task.d.ts.map +1 -0
  138. package/dist/routes/task.js +284 -0
  139. package/dist/routes/task.js.map +1 -0
  140. package/dist/routes/taskRelation.d.ts +80 -0
  141. package/dist/routes/taskRelation.d.ts.map +1 -0
  142. package/dist/routes/taskRelation.js +71 -0
  143. package/dist/routes/taskRelation.js.map +1 -0
  144. package/dist/routes/token.d.ts +75 -0
  145. package/dist/routes/token.d.ts.map +1 -0
  146. package/dist/routes/token.js +51 -0
  147. package/dist/routes/token.js.map +1 -0
  148. package/dist/routes/user.d.ts +112 -0
  149. package/dist/routes/user.d.ts.map +1 -0
  150. package/dist/routes/user.js +151 -0
  151. package/dist/routes/user.js.map +1 -0
  152. package/dist/routes/version.d.ts +42 -0
  153. package/dist/routes/version.d.ts.map +1 -0
  154. package/dist/routes/version.js +38 -0
  155. package/dist/routes/version.js.map +1 -0
  156. package/dist/routes/webhook.d.ts +170 -0
  157. package/dist/routes/webhook.d.ts.map +1 -0
  158. package/dist/routes/webhook.js +173 -0
  159. package/dist/routes/webhook.js.map +1 -0
  160. package/dist/routes/workspace.d.ts +120 -0
  161. package/dist/routes/workspace.d.ts.map +1 -0
  162. package/dist/routes/workspace.js +199 -0
  163. package/dist/routes/workspace.js.map +1 -0
  164. package/dist/utils/uploadSessionManager.d.ts +133 -0
  165. package/dist/utils/uploadSessionManager.d.ts.map +1 -0
  166. package/dist/utils/uploadSessionManager.js +321 -0
  167. package/dist/utils/uploadSessionManager.js.map +1 -0
  168. package/dist/utils/urlParams.d.ts +35 -0
  169. package/dist/utils/urlParams.d.ts.map +1 -0
  170. package/dist/utils/urlParams.js +146 -0
  171. package/dist/utils/urlParams.js.map +1 -0
  172. package/dist/version.d.ts +15 -0
  173. package/dist/version.d.ts.map +1 -0
  174. package/dist/version.js +12 -0
  175. package/dist/version.js.map +1 -0
  176. package/package.json +87 -3
  177. package/src/BotClient.ts +113 -0
  178. package/src/NuramaClient.ts +1193 -0
  179. package/src/bot-browser-entry.js +15 -0
  180. package/src/browser-entry.js +20 -0
  181. package/src/routes/ai.ts +378 -0
  182. package/src/routes/asset.ts +1104 -0
  183. package/src/routes/auth.ts +587 -0
  184. package/src/routes/blogPosts.ts +29 -0
  185. package/src/routes/board.ts +403 -0
  186. package/src/routes/bot.ts +257 -0
  187. package/src/routes/chat.ts +1292 -0
  188. package/src/routes/chatAi.ts +125 -0
  189. package/src/routes/config.ts +31 -0
  190. package/src/routes/convo.ts +321 -0
  191. package/src/routes/credits.ts +112 -0
  192. package/src/routes/device.ts +133 -0
  193. package/src/routes/folder.ts +154 -0
  194. package/src/routes/invite.ts +133 -0
  195. package/src/routes/joinLink.ts +100 -0
  196. package/src/routes/membership.ts +237 -0
  197. package/src/routes/notification.ts +166 -0
  198. package/src/routes/payment.ts +104 -0
  199. package/src/routes/product.ts +67 -0
  200. package/src/routes/project.ts +1528 -0
  201. package/src/routes/public.ts +496 -0
  202. package/src/routes/scratch.ts +94 -0
  203. package/src/routes/settings.ts +152 -0
  204. package/src/routes/shortlink.ts +90 -0
  205. package/src/routes/socket.ts +739 -0
  206. package/src/routes/storage.ts +83 -0
  207. package/src/routes/subscription.ts +307 -0
  208. package/src/routes/supportChat.ts +62 -0
  209. package/src/routes/supportTicket.ts +114 -0
  210. package/src/routes/tag.ts +131 -0
  211. package/src/routes/task.ts +431 -0
  212. package/src/routes/taskRelation.ts +125 -0
  213. package/src/routes/token.ts +113 -0
  214. package/src/routes/user.ts +214 -0
  215. package/src/routes/version.ts +62 -0
  216. package/src/routes/webhook.ts +295 -0
  217. package/src/routes/workspace.ts +223 -0
  218. package/src/utils/uploadSessionManager.ts +407 -0
  219. package/src/utils/urlParams.ts +181 -0
  220. package/src/version.ts +22 -0
@@ -0,0 +1,587 @@
1
+ import NuramaClient from "../NuramaClient.js"; // Adjust path if needed
2
+ import {
3
+ type User,
4
+ type AuthTokens,
5
+ type MFAEnableResponse,
6
+ type MFAVerifyResponse,
7
+ type LockAccountRequest,
8
+ type OAuthProvider,
9
+ type LinkedAuthProvider,
10
+ type OAuthExchangeRequest,
11
+ type OAuthExchangeResponse,
12
+ } from '@nurama/types';
13
+
14
+ // Define specific types for auth requests
15
+ export interface RegisterUserData
16
+ extends Pick<User, "firstName" | "lastName" | "email"> {
17
+ password: string;
18
+ }
19
+ export interface LoginCredentials {
20
+ login: string;
21
+ password: string;
22
+ /**
23
+ * Optional. When signing in to accept an invite, pass the invite id: it
24
+ * only reaches the user through the message sent to that address, so
25
+ * quoting it proves control of the inbox and lifts the email-verification
26
+ * grace block for this login. Credentials are still required.
27
+ */
28
+ inviteId?: string;
29
+ }
30
+ export interface ResetPasswordData {
31
+ token: string;
32
+ password: string;
33
+ }
34
+ export interface VerifyMFAData {
35
+ mfaToken: string;
36
+ }
37
+ export interface VerifyBackupCodeData {
38
+ backupCode: string;
39
+ }
40
+ export interface DisableMFAData {
41
+ mfaToken: string;
42
+ }
43
+ export interface ChangePasswordData {
44
+ currentPassword: string;
45
+ newPassword: string;
46
+ mfaToken?: string;
47
+ }
48
+
49
+ // Define specific response structures combining User and Tokens
50
+ export interface LoginRegisterResponse {
51
+ user: User;
52
+ tokens: AuthTokens;
53
+ }
54
+
55
+ // Type for refresh response (just tokens)
56
+ export interface RefreshResponse extends AuthTokens {}
57
+
58
+ /**
59
+ * Defines authentication-related methods for the NuramaClient.
60
+ * @param {NuramaClient} client - The NuramaClient instance.
61
+ * @returns {object} An object containing the authentication methods.
62
+ */
63
+ export default function createAuthMethods(client: NuramaClient) {
64
+ // Specify return type more accurately if possible, using AuthMethods interface
65
+ return {
66
+ /**
67
+ * Registers a new user.
68
+ * @param userData - User registration data.
69
+ * @returns {Promise<object>} Object containing user info and tokens.
70
+ */
71
+ async register(userData: RegisterUserData): Promise<LoginRegisterResponse> {
72
+ const result: LoginRegisterResponse = await client._request({
73
+ endpoint: "/v1/auth/register",
74
+ method: "POST",
75
+ body: userData,
76
+ sendJWT: false,
77
+ });
78
+ // Store tokens upon successful registration
79
+ if (
80
+ result &&
81
+ result.tokens &&
82
+ result.tokens.access &&
83
+ result.tokens.refresh
84
+ ) {
85
+ // Accessing the private _setTokens - might need adjustment if visibility changes
86
+ (client as any)._setTokens(
87
+ result.tokens.access.token,
88
+ result.tokens.refresh.token,
89
+ result.tokens.access.expires,
90
+ result.tokens.refresh.expires
91
+ );
92
+ } else {
93
+ console.warn("Register response did not contain expected tokens.");
94
+ }
95
+ return result;
96
+ },
97
+
98
+ /**
99
+ * Logs in a user.
100
+ * @param credentials - Login credentials.
101
+ * @returns {Promise<object>} Object containing user info and tokens (or MFA challenge token).
102
+ */
103
+ async login(
104
+ credentials: LoginCredentials
105
+ ): Promise<LoginRegisterResponse /* | MFAChallengeResponse */> {
106
+ const result: LoginRegisterResponse /* | MFAChallengeResponse */ =
107
+ await client._request({
108
+ endpoint: "/v1/auth/login",
109
+ method: "POST",
110
+ body: credentials,
111
+ sendJWT: false,
112
+ });
113
+ // Store tokens upon successful login
114
+ if (
115
+ result &&
116
+ "tokens" in result &&
117
+ result.tokens &&
118
+ result.tokens.access &&
119
+ result.tokens.refresh
120
+ ) {
121
+ (client as any)._setTokens(
122
+ result.tokens.access.token,
123
+ result.tokens.refresh.token,
124
+ result.tokens.access.expires,
125
+ result.tokens.refresh.expires
126
+ );
127
+ } else if (
128
+ result &&
129
+ "tokens" in result &&
130
+ result.tokens &&
131
+ result.tokens.verifyMfa
132
+ ) {
133
+ // MFA Challenge - store the verifyMfa token for verification
134
+ (client as any)._setTokens(null, null);
135
+ (client as any)._setVerifyMfaToken(result.tokens.verifyMfa.token);
136
+ } else {
137
+ console.warn(
138
+ "Login response did not contain expected tokens or MFA challenge."
139
+ );
140
+ (client as any)._setTokens(null, null);
141
+ }
142
+ return result;
143
+ },
144
+
145
+ /**
146
+ * Logs out a user.
147
+ * @param refreshToken - The refresh token to invalidate.
148
+ * @returns {Promise<void>}
149
+ */
150
+ async logout(refreshToken: string): Promise<void> {
151
+ // Get the refresh token *before* potentially clearing it
152
+ const tokenToInvalidate =
153
+ refreshToken || (client as any)._getRefreshToken();
154
+
155
+ if (tokenToInvalidate) {
156
+ try {
157
+ await client._request({
158
+ endpoint: "/v1/auth/logout",
159
+ method: "POST",
160
+ body: { refreshToken: tokenToInvalidate },
161
+ sendJWT: false, // Logout might not need JWT, depends on API
162
+ });
163
+ } catch (error) {
164
+ // Ignore errors - token may already be invalid/deleted
165
+ // The goal is to clear local tokens regardless
166
+ console.warn('Logout API call failed, but clearing local tokens:', error);
167
+ }
168
+ }
169
+ // Clear tokens locally regardless of API call success/failure
170
+ (client as any)._setTokens(null, null);
171
+ },
172
+
173
+ /**
174
+ * Refreshes user tokens.
175
+ * @param refreshToken - The refresh token.
176
+ * @returns {Promise<object>} Object containing new access and refresh tokens.
177
+ */
178
+ async refreshTokens(refreshToken?: string): Promise<RefreshResponse> {
179
+ const tokenToUse = refreshToken || (client as any)._getRefreshToken();
180
+ if (!tokenToUse) {
181
+ throw new Error(
182
+ "No refresh token provided or found in client storage."
183
+ );
184
+ }
185
+ const result: RefreshResponse = await client._request({
186
+ endpoint: "/v1/auth/refresh-tokens",
187
+ method: "POST",
188
+ body: { refreshToken: tokenToUse },
189
+ sendJWT: false, // Refresh endpoint uses the refresh token, not the access token
190
+ _isInternalRefresh: true, // Mark as internal to prevent recursive refresh loop if called by _request
191
+ });
192
+ // Store the *new* tokens
193
+ if (result && result.access && result.refresh) {
194
+ (client as any)._setTokens(
195
+ result.access.token,
196
+ result.refresh.token,
197
+ result.access.expires,
198
+ result.refresh.expires
199
+ );
200
+ } else {
201
+ console.warn("Refresh response did not contain expected tokens.");
202
+ // Clear tokens if refresh failed to return new ones
203
+ (client as any)._setTokens(null, null);
204
+ }
205
+ return result;
206
+ },
207
+
208
+ /**
209
+ * Forgets a user's password.
210
+ * @param email - The user's email address.
211
+ * @returns {Promise<void>}
212
+ */
213
+ async forgotPassword(email: string): Promise<void> {
214
+ await client._request<void>({
215
+ // Specify void return type
216
+ endpoint: "/v1/auth/forgot-password",
217
+ method: "POST",
218
+ body: { email },
219
+ sendJWT: false, // Usually doesn't require JWT
220
+ });
221
+ },
222
+
223
+ /**
224
+ * Resets a user's password.
225
+ * @param params - Input parameters.
226
+ * @param params.token - The password reset token.
227
+ * @param params.password - The new password.
228
+ * @returns Promise resolving when complete.
229
+ */
230
+ async resetPassword({ token, password }: ResetPasswordData): Promise<void> {
231
+ await client._request<void>({
232
+ // Specify void return type
233
+ endpoint: "/v1/auth/reset-password",
234
+ method: "POST",
235
+ body: { token, password },
236
+ sendJWT: false, // Token is the authentication here
237
+ });
238
+ },
239
+
240
+ /**
241
+ * Sends a verification email to the authenticated user.
242
+ * @returns Promise resolving when complete.
243
+ */
244
+ async sendVerificationEmail(): Promise<void> {
245
+ await client._request<void>({
246
+ // Specify void return type
247
+ endpoint: "/v1/auth/send-verification-email",
248
+ method: "POST",
249
+ sendJWT: true,
250
+ });
251
+ },
252
+
253
+ /**
254
+ * Public, unauthenticated resend of the verification email keyed by
255
+ * address. For users past the verification grace window who can't log
256
+ * in or call the authed sendVerificationEmail. Always resolves (the
257
+ * server returns 204 regardless of whether the email exists).
258
+ * @param email - The email address to resend the verification link to.
259
+ */
260
+ async resendVerification(email: string): Promise<void> {
261
+ await client._request<void>({
262
+ endpoint: "/v1/auth/resend-verification",
263
+ method: "POST",
264
+ body: { email },
265
+ sendJWT: false,
266
+ });
267
+ },
268
+
269
+ /**
270
+ * Verifies a user's email using the provided token.
271
+ * @param token - The email verification token.
272
+ * @returns Promise resolving when complete.
273
+ */
274
+ async verifyEmail(token: string): Promise<void> {
275
+ await client._request<void>({
276
+ // Specify void return type
277
+ endpoint: `/v1/auth/verify-email?token=${encodeURIComponent(token)}`,
278
+ method: "POST",
279
+ sendJWT: false, // Token is the authentication here
280
+ });
281
+ },
282
+
283
+ /**
284
+ * Enables multi-factor authentication for the authenticated user.
285
+ * @returns Promise resolving to MFA setup details (secret, OTP URL, backup codes).
286
+ */
287
+ async enableMfa(): Promise<MFAEnableResponse> {
288
+ return client._request<MFAEnableResponse>({
289
+ endpoint: "/v1/auth/enable-mfa",
290
+ method: "POST",
291
+ sendJWT: true,
292
+ });
293
+ },
294
+
295
+ /**
296
+ * Verifies an MFA token (e.g., TOTP code).
297
+ * This is used both during initial MFA setup and during login challenges.
298
+ * @param mfaToken - The MFA token code.
299
+ * @returns Promise resolving to user/token data upon successful verification.
300
+ */
301
+ async verifyMfa(mfaToken: string): Promise<MFAVerifyResponse> {
302
+ // Response can be full login data (if completing challenge) or just user data (if setting up)
303
+
304
+ // Check if we have a verifyMfa token from login (for login challenge)
305
+ const verifyMfaToken = (client as any)._getVerifyMfaToken();
306
+
307
+ const requestOptions: any = {
308
+ endpoint: "/v1/auth/verify-mfa",
309
+ method: "POST",
310
+ body: { mfaToken } satisfies VerifyMFAData,
311
+ };
312
+
313
+ if (verifyMfaToken) {
314
+ // During MFA login challenge - use the verifyMfa token
315
+ requestOptions.sendJWT = false;
316
+ requestOptions.customHeaders = {
317
+ 'Authorization': `Bearer ${verifyMfaToken}`
318
+ };
319
+ } else {
320
+ // During MFA setup - use regular access token
321
+ requestOptions.sendJWT = true;
322
+ }
323
+
324
+ const result = await client._request<MFAVerifyResponse>(requestOptions);
325
+
326
+ // If login challenge was completed, set the new tokens and clear verifyMfa token
327
+ if (result && result.tokens?.access) {
328
+ (client as any)._setTokens(
329
+ result.tokens.access.token,
330
+ result.tokens.refresh.token,
331
+ result.tokens.access.expires,
332
+ result.tokens.refresh.expires
333
+ );
334
+ // Clear the verifyMfa token as it's no longer needed
335
+ (client as any)._setVerifyMfaToken(null);
336
+ }
337
+ return result;
338
+ },
339
+
340
+ /**
341
+ * Verifies an MFA backup code.
342
+ * This is used during login when a user has lost access to their authenticator app.
343
+ * @param backupCode - The backup code (8-character hex string).
344
+ * @returns Promise resolving to user/token data upon successful verification.
345
+ */
346
+ async verifyBackupCode(backupCode: string): Promise<MFAVerifyResponse> {
347
+ // Check if we have a verifyMfa token from login (for login challenge)
348
+ const verifyMfaToken = (client as any)._getVerifyMfaToken();
349
+
350
+ const requestOptions: any = {
351
+ endpoint: "/v1/auth/verify-backup-code",
352
+ method: "POST",
353
+ body: { backupCode } satisfies VerifyBackupCodeData,
354
+ };
355
+
356
+ if (verifyMfaToken) {
357
+ // During MFA login challenge - use the verifyMfa token
358
+ requestOptions.sendJWT = false;
359
+ requestOptions.customHeaders = {
360
+ 'Authorization': `Bearer ${verifyMfaToken}`
361
+ };
362
+ } else {
363
+ // During MFA setup - use regular access token
364
+ requestOptions.sendJWT = true;
365
+ }
366
+
367
+ const result = await client._request<MFAVerifyResponse>(requestOptions);
368
+
369
+ // If login challenge was completed, set the new tokens and clear verifyMfa token
370
+ if (result && result.tokens?.access) {
371
+ (client as any)._setTokens(
372
+ result.tokens.access.token,
373
+ result.tokens.refresh.token,
374
+ result.tokens.access.expires,
375
+ result.tokens.refresh.expires
376
+ );
377
+ // Clear the verifyMfa token as it's no longer needed
378
+ (client as any)._setVerifyMfaToken(null);
379
+ }
380
+ return result;
381
+ },
382
+
383
+ /**
384
+ * Disables multi-factor authentication for the authenticated user.
385
+ * Requires a current valid MFA token for confirmation.
386
+ * @param mfaToken - The current MFA token code.
387
+ * @returns Promise resolving when complete.
388
+ */
389
+ async disableMfa(mfaToken: string): Promise<void> {
390
+ await client._request<void>({
391
+ // Specify void return type
392
+ endpoint: "/v1/auth/disable-mfa",
393
+ method: "POST",
394
+ body: { mfaToken } satisfies DisableMFAData, // Use interface for body
395
+ sendJWT: true,
396
+ });
397
+ },
398
+
399
+ /**
400
+ * Changes the authenticated user's password.
401
+ * Requires current password verification and MFA token if MFA is enabled.
402
+ * All refresh tokens will be invalidated after password change.
403
+ * @param currentPassword - The current password for verification.
404
+ * @param newPassword - The new password.
405
+ * @param mfaToken - MFA token (required if MFA is enabled).
406
+ * @returns Promise resolving when complete.
407
+ */
408
+ async changePassword(currentPassword: string, newPassword: string, mfaToken?: string): Promise<void> {
409
+ await client._request<void>({
410
+ endpoint: "/v1/auth/change-password",
411
+ method: "POST",
412
+ body: { currentPassword, newPassword, mfaToken } satisfies ChangePasswordData,
413
+ sendJWT: true,
414
+ });
415
+
416
+ // Clear local tokens since all sessions are invalidated
417
+ (client as any)._setTokens(null, null);
418
+ },
419
+
420
+ /**
421
+ * Locks a user account using a lock account token.
422
+ * This is used when a user receives a password changed notification
423
+ * for a change they did not initiate, allowing them to immediately
424
+ * secure their account.
425
+ * @param token - The lock account token from the password changed email.
426
+ * @returns Promise resolving when the account is locked.
427
+ */
428
+ async lockAccount(token: string): Promise<void> {
429
+ await client._request<void>({
430
+ endpoint: "/v1/auth/lock-account",
431
+ method: "POST",
432
+ body: { token } satisfies LockAccountRequest,
433
+ sendJWT: false, // Token is the authentication here
434
+ });
435
+
436
+ // Clear local tokens since the account is now locked
437
+ (client as any)._setTokens(null, null);
438
+ },
439
+
440
+ /**
441
+ * Sets a password for an OAuth-only user account.
442
+ * This allows OAuth users to add local authentication as a backup.
443
+ * @param password - The password to set.
444
+ * @param mfaToken - MFA token (required if MFA is enabled).
445
+ * @returns Promise resolving when complete.
446
+ */
447
+ async setPassword(password: string, mfaToken?: string): Promise<void> {
448
+ await client._request<void>({
449
+ endpoint: "/v1/auth/set-password",
450
+ method: "POST",
451
+ body: { password, mfaToken },
452
+ sendJWT: true,
453
+ });
454
+ },
455
+
456
+ /**
457
+ * Links an OAuth provider to the authenticated user's account.
458
+ * This allows users to sign in with multiple OAuth providers.
459
+ * @param provider - The OAuth provider to link (google, apple, microsoft, adobe).
460
+ * @returns Promise resolving to user data with updated linked providers.
461
+ */
462
+ async linkOAuthProvider(provider: OAuthProvider): Promise<LoginRegisterResponse> {
463
+ const result: LoginRegisterResponse = await client._request({
464
+ endpoint: `/v1/auth/${provider}/link`,
465
+ method: "POST",
466
+ sendJWT: true,
467
+ });
468
+ return result;
469
+ },
470
+
471
+ /**
472
+ * Unlinks an OAuth provider from the authenticated user's account.
473
+ * User must have at least one authentication method remaining (password or another OAuth provider).
474
+ * @param provider - The OAuth provider to unlink (google, apple, microsoft, adobe).
475
+ * @returns Promise resolving when complete.
476
+ */
477
+ async unlinkOAuthProvider(provider: OAuthProvider): Promise<void> {
478
+ await client._request<void>({
479
+ endpoint: `/v1/auth/oauth/${provider}/unlink`,
480
+ method: "DELETE",
481
+ sendJWT: true,
482
+ });
483
+ },
484
+
485
+ /**
486
+ * Gets all OAuth providers linked to the authenticated user's account.
487
+ * @returns Promise resolving to array of linked OAuth providers.
488
+ */
489
+ async getLinkedOAuthProviders(): Promise<LinkedAuthProvider[]> {
490
+ return client._request<LinkedAuthProvider[]>({
491
+ endpoint: "/v1/auth/oauth/providers",
492
+ method: "GET",
493
+ sendJWT: true,
494
+ });
495
+ },
496
+
497
+ /**
498
+ * Exchanges an OAuth authorization code for JWT tokens.
499
+ * This is called after the OAuth callback redirects the user back to the app with an exchange code.
500
+ * The exchange code is a short-lived (5 min), single-use token that can be traded for JWT tokens.
501
+ * @param code - The exchange code received from the OAuth callback.
502
+ * @returns Promise resolving to user data, tokens, and optional return URL.
503
+ */
504
+ /**
505
+ * Registers a guest account for public chat participation.
506
+ * Always returns void (204) regardless of outcome for anti-enumeration.
507
+ * @param data - Guest registration data (email, displayName, optional approved color, publicToken).
508
+ */
509
+ async registerGuest(data: { email: string; displayName: string; color?: string; publicToken: string }): Promise<void> {
510
+ await client._request<void>({
511
+ endpoint: "/v1/auth/register-guest",
512
+ method: "POST",
513
+ body: data,
514
+ sendJWT: false,
515
+ });
516
+ },
517
+
518
+ /**
519
+ * Verifies a guest account using the token from the verification email.
520
+ * Stores auth tokens on success and returns user data.
521
+ * @param token - The guest verification token.
522
+ * @returns Promise resolving to user data and auth tokens.
523
+ */
524
+ async verifyGuest(token: string): Promise<LoginRegisterResponse> {
525
+ const result: LoginRegisterResponse = await client._request({
526
+ endpoint: `/v1/auth/verify-guest?token=${encodeURIComponent(token)}`,
527
+ method: "POST",
528
+ sendJWT: false,
529
+ });
530
+ if (result?.tokens?.access && result?.tokens?.refresh) {
531
+ (client as any)._setTokens(
532
+ result.tokens.access.token,
533
+ result.tokens.refresh.token,
534
+ result.tokens.access.expires,
535
+ result.tokens.refresh.expires
536
+ );
537
+ }
538
+ return result;
539
+ },
540
+
541
+ /**
542
+ * Upgrades a guest account to a standard account with a password.
543
+ * Requires the user to be authenticated as a guest.
544
+ * @param data - Upgrade data (password, optional firstName, lastName, company, userName).
545
+ * @returns Promise resolving to the upgraded user data.
546
+ */
547
+ async upgradeGuest(data: { password: string; firstName?: string; lastName?: string; company?: string; userName?: string }): Promise<{ user: User }> {
548
+ return client._request<{ user: User }>({
549
+ endpoint: "/v1/auth/upgrade-guest",
550
+ method: "POST",
551
+ body: data,
552
+ sendJWT: true,
553
+ });
554
+ },
555
+
556
+ async exchangeOAuthCode(code: string): Promise<OAuthExchangeResponse> {
557
+ const result: OAuthExchangeResponse = await client._request({
558
+ endpoint: "/v1/auth/oauth/exchange",
559
+ method: "POST",
560
+ body: { code } satisfies OAuthExchangeRequest,
561
+ sendJWT: false, // No authentication needed - the code is the proof
562
+ });
563
+
564
+ // Store tokens upon successful exchange
565
+ // Check if this is MFA flow or regular auth
566
+ if (result && result.tokens) {
567
+ if (result.tokens.access && result.tokens.refresh) {
568
+ // Regular auth - store access and refresh tokens
569
+ (client as any)._setTokens(
570
+ result.tokens.access.token,
571
+ result.tokens.refresh.token,
572
+ result.tokens.access.expires,
573
+ result.tokens.refresh.expires
574
+ );
575
+ } else if ((result.tokens as any).verifyMfa) {
576
+ // MFA required - verifyMfa token will be handled by frontend
577
+ console.log("[SDK] OAuth login requires MFA verification");
578
+ } else {
579
+ console.warn("OAuth exchange response did not contain expected tokens.");
580
+ }
581
+ }
582
+
583
+ return result;
584
+ },
585
+
586
+ };
587
+ }
@@ -0,0 +1,29 @@
1
+ import NuramaClient from '../NuramaClient.js';
2
+ import type { BlogPostListParams, BlogPostListResponse } from '@nurama/types';
3
+
4
+ /**
5
+ * Read-only blog feed (Nurama News on the /news page) sourced via the
6
+ * backend's Ghost Content API proxy. Auth: any signed-in user. No
7
+ * workspace coupling — the feed is platform-level, identical for every
8
+ * user.
9
+ *
10
+ * The proxy normalises Ghost's payload and sanitises post HTML
11
+ * server-side, so the returned `bodyHtml` is safe to render via the
12
+ * FE's controlled HTML primitive inside a modal.
13
+ */
14
+ export default function createBlogPostsMethods(client: NuramaClient) {
15
+ return {
16
+ /** List the most recent Nurama News posts. */
17
+ async listBlogPosts(params: BlogPostListParams = {}): Promise<BlogPostListResponse> {
18
+ const search = new URLSearchParams();
19
+ if (params.limit != null) search.set('limit', String(params.limit));
20
+ if (params.page != null) search.set('page', String(params.page));
21
+ const query = search.toString();
22
+ return client._request({
23
+ endpoint: `/v1/blog-posts${query ? `?${query}` : ''}`,
24
+ method: 'GET',
25
+ sendJWT: true,
26
+ });
27
+ },
28
+ };
29
+ }