@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,496 @@
1
+ import NuramaClient from '../NuramaClient.js';
2
+ import { type ResolvePublicDownloadResponse, type PublicDownloadUrlResponse, type PublicEmbedFilesResponse } from './shortlink.js';
3
+ import {
4
+ FileSystem,
5
+ CursorPaginatedResult,
6
+ DownloadSignedUrlData,
7
+ ObjectId,
8
+ Chat,
9
+ ChatMessage,
10
+ CreatePublicChatMessageRequest,
11
+ CreatePublicAssetChatMessageResponse,
12
+ GetPublicChatMessagesParams,
13
+ PublicChatMessagesResponse,
14
+ PublicAssetResponse,
15
+ } from '@nurama/types';
16
+
17
+ /**
18
+ * Base pagination parameters
19
+ */
20
+ export interface PaginationParams {
21
+ limit?: number;
22
+ paginate?: 'cursor' | 'index';
23
+ // Cursor specific
24
+ cursor?: string;
25
+ paginateReverse?: boolean;
26
+ includeCursorRecord?: boolean;
27
+ includeCounts?: boolean;
28
+ startAt?: string;
29
+ includeStartAtRecord?: boolean;
30
+ // Index specific
31
+ page?: number;
32
+ // Sorting
33
+ sort?: Record<string, 1 | -1>;
34
+ }
35
+
36
+ /**
37
+ * Pagination parameters specific to public routes
38
+ */
39
+ export interface PublicPaginationParams extends PaginationParams {
40
+ resourceIds?: ObjectId[];
41
+ resourceSlugs?: string[];
42
+ resourceType?: 'asset' | 'folder';
43
+ resourceTags?: ObjectId[];
44
+ creatorId?: ObjectId;
45
+ mediaTypes?: ('image' | 'video' | 'audio' | 'file' | 'folder')[];
46
+ resourceStatus?: 'active' | 'pendingDelete';
47
+ nameSearch?: string;
48
+ recursiveSearch?: boolean;
49
+ }
50
+
51
+ /**
52
+ * Request body for downloading public assets
53
+ */
54
+ export interface DownloadPublicAssetsData {
55
+ assetIds: ObjectId[];
56
+ }
57
+
58
+ /**
59
+ * Response type for paginated public file system items
60
+ */
61
+ export type PublicFileSystemResponse = CursorPaginatedResult & {
62
+ results?: FileSystem[];
63
+ };
64
+
65
+ /**
66
+ * Response type for a single public file system
67
+ */
68
+ export interface PublicFileSystemDetailsResponse {
69
+ id: string;
70
+ projectId: string;
71
+ token: string;
72
+ title: string;
73
+ description?: string;
74
+ itemPaths: string[];
75
+ expiresAt: string;
76
+ createdAt: string;
77
+ updatedAt: string;
78
+ /**
79
+ * Whether unauthenticated visitors may comment on this release by supplying a
80
+ * display name (no account). Drives the anonymous compose flow in the UI.
81
+ */
82
+ allowAnonymousComments?: boolean;
83
+ }
84
+
85
+ /**
86
+ * Defines public route methods for unauthenticated access to public file systems.
87
+ */
88
+ export default function createPublicMethods(client: NuramaClient) {
89
+ return {
90
+ /**
91
+ * Gets public file system details by token.
92
+ * This endpoint does not require authentication - access is controlled by the token.
93
+ *
94
+ * @param {string} token - The 10-character alphanumeric public access token.
95
+ * @returns {Promise<PublicFileSystemDetailsResponse>} The public file system details.
96
+ *
97
+ * @example
98
+ * ```typescript
99
+ * const publicFileSystem = await nuramaClient.public.getPublicFileSystem('abc123def4');
100
+ * ```
101
+ */
102
+ async getPublicFileSystem(token: string): Promise<PublicFileSystemDetailsResponse> {
103
+ if (!token) throw new Error('token is required.');
104
+ if (token.length !== 10) throw new Error('token must be exactly 10 characters long.');
105
+ if (!/^[a-zA-Z0-9]{10}$/.test(token)) throw new Error('token must contain only alphanumeric characters.');
106
+
107
+ return client._request<PublicFileSystemDetailsResponse>({
108
+ endpoint: `/v1/public/${token}`,
109
+ method: 'GET',
110
+ sendJWT: false, // This is a public endpoint
111
+ });
112
+ },
113
+
114
+ /**
115
+ * Gets public items at the root level of a public file system.
116
+ * This endpoint does not require authentication - access is controlled by the token.
117
+ *
118
+ * @param {string} token - The 10-character alphanumeric public access token.
119
+ * @param {PublicPaginationParams} params - Optional pagination and filtering parameters.
120
+ * @returns {Promise<PublicFileSystemResponse>} Paginated list of public file system items.
121
+ *
122
+ * @example
123
+ * ```typescript
124
+ * const publicItems = await nuramaClient.public.getPublicItems('abc123def4');
125
+ * ```
126
+ */
127
+ async getPublicItems(token: string, params?: PublicPaginationParams): Promise<PublicFileSystemResponse> {
128
+ if (!token) throw new Error('token is required.');
129
+ if (token.length !== 10) throw new Error('token must be exactly 10 characters long.');
130
+ if (!/^[a-zA-Z0-9]{10}$/.test(token)) throw new Error('token must contain only alphanumeric characters.');
131
+
132
+ // Convert arrays to proper format for query params
133
+ const queryParams = params ? {
134
+ ...params,
135
+ resourceIds: Array.isArray(params.resourceIds) ? params.resourceIds : (params.resourceIds ? [params.resourceIds] : []),
136
+ resourceSlugs: Array.isArray(params.resourceSlugs) ? params.resourceSlugs : (params.resourceSlugs ? [params.resourceSlugs] : []),
137
+ resourceTags: Array.isArray(params.resourceTags) ? params.resourceTags : (params.resourceTags ? [params.resourceTags] : []),
138
+ mediaTypes: Array.isArray(params.mediaTypes) ? params.mediaTypes : (params.mediaTypes ? [params.mediaTypes] : []),
139
+ } : {};
140
+
141
+ return client._request<PublicFileSystemResponse>({
142
+ endpoint: `/v1/public/${token}/files`,
143
+ method: 'GET',
144
+ params: queryParams,
145
+ sendJWT: false, // This is a public endpoint
146
+ });
147
+ },
148
+
149
+ /**
150
+ * Gets public items at a specific path within a public file system.
151
+ * This endpoint does not require authentication - access is controlled by the token.
152
+ *
153
+ * @param {string} token - The 10-character alphanumeric public access token.
154
+ * @param {string} path - The path within the public file system to retrieve items from.
155
+ * @param {PublicPaginationParams} params - Optional pagination and filtering parameters.
156
+ * @returns {Promise<PublicFileSystemResponse>} Paginated list of public file system items.
157
+ *
158
+ * @example
159
+ * ```typescript
160
+ * const items = await nuramaClient.public.getPublicItemsAtPath('abc123def4', 'folder1/subfolder');
161
+ * ```
162
+ */
163
+ async getPublicItemsAtPath(token: string, path: string, params?: PublicPaginationParams): Promise<PublicFileSystemResponse> {
164
+ if (!token) throw new Error('token is required.');
165
+ if (token.length !== 10) throw new Error('token must be exactly 10 characters long.');
166
+ if (!/^[a-zA-Z0-9]{10}$/.test(token)) throw new Error('token must contain only alphanumeric characters.');
167
+ if (path === null || path === undefined) throw new Error('path is required.');
168
+
169
+ // Remove leading slash if present
170
+ const cleanPath = path.startsWith('/') ? path.substring(1) : path;
171
+
172
+ // Convert arrays to proper format for query params
173
+ const queryParams = params ? {
174
+ ...params,
175
+ resourceIds: Array.isArray(params.resourceIds) ? params.resourceIds : (params.resourceIds ? [params.resourceIds] : []),
176
+ resourceSlugs: Array.isArray(params.resourceSlugs) ? params.resourceSlugs : (params.resourceSlugs ? [params.resourceSlugs] : []),
177
+ resourceTags: Array.isArray(params.resourceTags) ? params.resourceTags : (params.resourceTags ? [params.resourceTags] : []),
178
+ mediaTypes: Array.isArray(params.mediaTypes) ? params.mediaTypes : (params.mediaTypes ? [params.mediaTypes] : []),
179
+ } : {};
180
+
181
+ return client._request<PublicFileSystemResponse>({
182
+ endpoint: `/v1/public/${token}/files/${cleanPath}`,
183
+ method: 'GET',
184
+ params: queryParams,
185
+ sendJWT: false, // This is a public endpoint
186
+ });
187
+ },
188
+
189
+ /**
190
+ * Downloads public assets by generating signed URLs for the original files.
191
+ * This endpoint does not require authentication - access is controlled by the token.
192
+ *
193
+ * @param {string} token - The 10-character alphanumeric public access token.
194
+ * @param {DownloadPublicAssetsData} downloadData - The asset IDs to download.
195
+ * @returns {Promise<DownloadSignedUrlData[]>} Array of signed download URLs for the requested assets.
196
+ *
197
+ * @example
198
+ * ```typescript
199
+ * const downloadUrls = await nuramaClient.public.downloadAssets('abc123def4', {
200
+ * assetIds: ['507f1f77bcf86cd799439011', '507f191e810c19729de860ea']
201
+ * });
202
+ * ```
203
+ */
204
+ async downloadAssets(token: string, downloadData: DownloadPublicAssetsData): Promise<DownloadSignedUrlData[]> {
205
+ if (!token) throw new Error('token is required.');
206
+ if (token.length !== 10) throw new Error('token must be exactly 10 characters long.');
207
+ if (!/^[a-zA-Z0-9]{10}$/.test(token)) throw new Error('token must contain only alphanumeric characters.');
208
+ if (!downloadData) throw new Error('downloadData is required.');
209
+ if (!downloadData.assetIds || !Array.isArray(downloadData.assetIds) || downloadData.assetIds.length === 0) {
210
+ throw new Error('downloadData.assetIds must be a non-empty array.');
211
+ }
212
+
213
+ return client._request<DownloadSignedUrlData[]>({
214
+ endpoint: `/v1/public/${token}/download`,
215
+ method: 'POST',
216
+ body: downloadData,
217
+ sendJWT: false, // This is a public endpoint
218
+ });
219
+ },
220
+
221
+ // ============================================================================
222
+ // Public Chat Methods
223
+ // ============================================================================
224
+
225
+ /**
226
+ * Gets the main public file system chat or a specific chat by ID.
227
+ * This endpoint does not require authentication for read access.
228
+ *
229
+ * @param {string} token - The 10-character alphanumeric public access token.
230
+ * @param {string} [chatId] - Optional specific chat ID to retrieve.
231
+ * @returns {Promise<Chat | null>} The chat object, or null if no main chat exists yet.
232
+ *
233
+ * @example
234
+ * ```typescript
235
+ * // Get main public file system chat
236
+ * const mainChat = await nuramaClient.public.getPublicChat('abc123def4');
237
+ *
238
+ * // Get specific chat by ID
239
+ * const chat = await nuramaClient.public.getPublicChat('abc123def4', 'chat-id-here');
240
+ * ```
241
+ */
242
+ async getPublicChat(token: string, chatId?: string): Promise<Chat | null> {
243
+ if (!token) throw new Error('token is required.');
244
+ if (token.length !== 10) throw new Error('token must be exactly 10 characters long.');
245
+ if (!/^[a-zA-Z0-9]{10}$/.test(token)) throw new Error('token must contain only alphanumeric characters.');
246
+
247
+ const endpoint = chatId ? `/v1/public/${token}/chat/${chatId}` : `/v1/public/${token}/chat`;
248
+
249
+ return client._request<Chat | null>({
250
+ endpoint,
251
+ method: 'GET',
252
+ sendJWT: false, // Read access is public
253
+ });
254
+ },
255
+
256
+ /**
257
+ * Gets paginated messages for a public chat.
258
+ * This endpoint does not require authentication for read access.
259
+ *
260
+ * @param {string} token - The 10-character alphanumeric public access token.
261
+ * @param {string} chatId - The ID of the chat to get messages from.
262
+ * @param {GetPublicChatMessagesParams} [params] - Optional pagination parameters.
263
+ * @returns {Promise<PublicChatMessagesResponse>} Paginated list of chat messages.
264
+ *
265
+ * @example
266
+ * ```typescript
267
+ * const messages = await nuramaClient.public.getPublicChatMessages('abc123def4', 'chat-id', {
268
+ * limit: 20,
269
+ * paginateReverse: false,
270
+ * });
271
+ * ```
272
+ */
273
+ async getPublicChatMessages(
274
+ token: string,
275
+ chatId: string,
276
+ params?: GetPublicChatMessagesParams
277
+ ): Promise<PublicChatMessagesResponse> {
278
+ if (!token) throw new Error('token is required.');
279
+ if (token.length !== 10) throw new Error('token must be exactly 10 characters long.');
280
+ if (!/^[a-zA-Z0-9]{10}$/.test(token)) throw new Error('token must contain only alphanumeric characters.');
281
+ if (!chatId) throw new Error('chatId is required.');
282
+
283
+ return client._request<PublicChatMessagesResponse>({
284
+ endpoint: `/v1/public/${token}/chat/${chatId}/messages`,
285
+ method: 'GET',
286
+ params: params || {},
287
+ sendJWT: false, // Read access is public
288
+ });
289
+ },
290
+
291
+ /**
292
+ * Creates a message in an existing public chat.
293
+ * Requires authentication.
294
+ *
295
+ * @param {string} token - The 10-character alphanumeric public access token.
296
+ * @param {string} chatId - The ID of the chat to post to.
297
+ * @param {CreatePublicChatMessageRequest} data - The message data.
298
+ * @returns {Promise<ChatMessage>} The created message.
299
+ *
300
+ * @example
301
+ * ```typescript
302
+ * const message = await nuramaClient.public.createPublicChatMessage('abc123def4', 'chat-id', {
303
+ * content: 'Hello world!',
304
+ * });
305
+ * ```
306
+ */
307
+ async createPublicChatMessage(
308
+ token: string,
309
+ chatId: string,
310
+ data: CreatePublicChatMessageRequest
311
+ ): Promise<ChatMessage> {
312
+ if (!token) throw new Error('token is required.');
313
+ if (token.length !== 10) throw new Error('token must be exactly 10 characters long.');
314
+ if (!/^[a-zA-Z0-9]{10}$/.test(token)) throw new Error('token must contain only alphanumeric characters.');
315
+ if (!chatId) throw new Error('chatId is required.');
316
+ if (!data) throw new Error('data is required.');
317
+
318
+ return client._request<ChatMessage>({
319
+ endpoint: `/v1/public/${token}/chat/${chatId}/messages`,
320
+ method: 'POST',
321
+ body: data,
322
+ sendJWT: 'optional', // Authenticated caller keeps identity; anonymous allowed when the release opts in
323
+ });
324
+ },
325
+
326
+ /**
327
+ * Creates a message on the main public topic chat.
328
+ * If no main chat exists for this public file system, one is created (lazy creation).
329
+ * Requires authentication.
330
+ *
331
+ * @param {string} token - The 10-character alphanumeric public access token.
332
+ * @param {CreatePublicChatMessageRequest} data - The message data.
333
+ * @returns {Promise<CreatePublicAssetChatMessageResponse>} The chat and created message.
334
+ *
335
+ * @example
336
+ * ```typescript
337
+ * // This creates the main chat if it doesn't exist and posts the first message
338
+ * const { chat, message } = await nuramaClient.public.createPublicTopicChatMessage('abc123def4', {
339
+ * content: 'First comment on this public file system!',
340
+ * });
341
+ * ```
342
+ */
343
+ async createPublicTopicChatMessage(
344
+ token: string,
345
+ data: CreatePublicChatMessageRequest
346
+ ): Promise<CreatePublicAssetChatMessageResponse> {
347
+ if (!token) throw new Error('token is required.');
348
+ if (token.length !== 10) throw new Error('token must be exactly 10 characters long.');
349
+ if (!/^[a-zA-Z0-9]{10}$/.test(token)) throw new Error('token must contain only alphanumeric characters.');
350
+ if (!data) throw new Error('data is required.');
351
+
352
+ return client._request<CreatePublicAssetChatMessageResponse>({
353
+ endpoint: `/v1/public/${token}/chat/messages`,
354
+ method: 'POST',
355
+ body: data,
356
+ sendJWT: 'optional', // Authenticated caller keeps identity; anonymous allowed when the release opts in
357
+ });
358
+ },
359
+
360
+ /**
361
+ * Gets an asset with its public chat in the context of a public file system.
362
+ * This endpoint does not require authentication for read access.
363
+ *
364
+ * @param {string} token - The 10-character alphanumeric public access token.
365
+ * @param {string} assetId - The ID of the asset to retrieve.
366
+ * @returns {Promise<PublicAssetResponse>} The asset with its public chat (or null if no chat exists).
367
+ *
368
+ * @example
369
+ * ```typescript
370
+ * const asset = await nuramaClient.public.getPublicAsset('abc123def4', 'asset-id');
371
+ * if (asset.chats.public) {
372
+ * console.log('Asset has public chat:', asset.chats.public.id);
373
+ * }
374
+ * ```
375
+ */
376
+ async getPublicAsset(token: string, assetId: string): Promise<PublicAssetResponse> {
377
+ if (!token) throw new Error('token is required.');
378
+ if (token.length !== 10) throw new Error('token must be exactly 10 characters long.');
379
+ if (!/^[a-zA-Z0-9]{10}$/.test(token)) throw new Error('token must contain only alphanumeric characters.');
380
+ if (!assetId) throw new Error('assetId is required.');
381
+
382
+ return client._request<PublicAssetResponse>({
383
+ endpoint: `/v1/public/${token}/assets/${assetId}`,
384
+ method: 'GET',
385
+ sendJWT: false, // Read access is public
386
+ });
387
+ },
388
+
389
+ /**
390
+ * Creates a message on an asset's public chat.
391
+ * If no public chat exists for this asset in this public file system, one is created (lazy creation).
392
+ * Requires authentication.
393
+ *
394
+ * @param {string} token - The 10-character alphanumeric public access token.
395
+ * @param {string} assetId - The ID of the asset to post to.
396
+ * @param {CreatePublicChatMessageRequest} data - The message data.
397
+ * @returns {Promise<CreatePublicAssetChatMessageResponse>} The chat and created message.
398
+ *
399
+ * @example
400
+ * ```typescript
401
+ * // This creates the chat if it doesn't exist and posts the first message
402
+ * const { chat, message } = await nuramaClient.public.createPublicAssetChatMessage('abc123def4', 'asset-id', {
403
+ * content: 'First comment on this asset!',
404
+ * });
405
+ * ```
406
+ */
407
+ async createPublicAssetChatMessage(
408
+ token: string,
409
+ assetId: string,
410
+ data: CreatePublicChatMessageRequest
411
+ ): Promise<CreatePublicAssetChatMessageResponse> {
412
+ if (!token) throw new Error('token is required.');
413
+ if (token.length !== 10) throw new Error('token must be exactly 10 characters long.');
414
+ if (!/^[a-zA-Z0-9]{10}$/.test(token)) throw new Error('token must contain only alphanumeric characters.');
415
+ if (!assetId) throw new Error('assetId is required.');
416
+ if (!data) throw new Error('data is required.');
417
+
418
+ return client._request<CreatePublicAssetChatMessageResponse>({
419
+ endpoint: `/v1/public/${token}/assets/${assetId}/messages`,
420
+ method: 'POST',
421
+ body: data,
422
+ sendJWT: 'optional', // Authenticated caller keeps identity; anonymous allowed when the release opts in
423
+ });
424
+ },
425
+
426
+ // ========================================================================
427
+ // Public asset links (/public-download)
428
+ // ========================================================================
429
+
430
+ /**
431
+ * Resolve a public asset-link token to the minimal file info the download page shows.
432
+ * Public endpoint; no authentication.
433
+ * @param {string} token - The public asset-link token.
434
+ * @returns {Promise<ResolvePublicDownloadResponse>} File name, media type and link status.
435
+ * @throws {Error} 'token is required.' when `token` is falsy.
436
+ */
437
+ async resolvePublicDownload(token: string): Promise<ResolvePublicDownloadResponse> {
438
+ if (!token) throw new Error('token is required.');
439
+ return client._request<ResolvePublicDownloadResponse>({
440
+ method: 'GET',
441
+ endpoint: `/v1/public-download/${token}`,
442
+ sendJWT: false,
443
+ });
444
+ },
445
+
446
+ /**
447
+ * Get a short-lived signed download URL for a public asset-link token.
448
+ * Public endpoint; fails with 403 for embed-only links.
449
+ * @param {string} token - The public asset-link token.
450
+ * @returns {Promise<PublicDownloadUrlResponse>} The signed URL and its expiry.
451
+ * @throws {Error} 'token is required.' when `token` is falsy.
452
+ */
453
+ async getPublicDownloadUrl(token: string): Promise<PublicDownloadUrlResponse> {
454
+ if (!token) throw new Error('token is required.');
455
+ return client._request<PublicDownloadUrlResponse>({
456
+ method: 'GET',
457
+ endpoint: `/v1/public-download/${token}/download`,
458
+ sendJWT: false,
459
+ });
460
+ },
461
+
462
+ /**
463
+ * Get the HLS stream and fallback media key paths for the embeddable player.
464
+ * Public endpoint; fails with 403 for download-only links.
465
+ * @param {string} token - The public asset-link token.
466
+ * @returns {Promise<PublicEmbedFilesResponse>} Stream and fallback key paths.
467
+ * @throws {Error} 'token is required.' when `token` is falsy.
468
+ */
469
+ async getPublicEmbedFiles(token: string): Promise<PublicEmbedFilesResponse> {
470
+ if (!token) throw new Error('token is required.');
471
+ return client._request<PublicEmbedFilesResponse>({
472
+ method: 'GET',
473
+ endpoint: `/v1/public-download/${token}/embed-files`,
474
+ sendJWT: false,
475
+ });
476
+ },
477
+
478
+ /**
479
+ * Record a play event from the embed player for a public asset link.
480
+ * Public endpoint; no authentication. The API responds 204.
481
+ * @param {string} token - The public asset-link token.
482
+ * @param {object} body - `{ eventType: 'play_started' | 'play_completed' }`.
483
+ * @returns {Promise<void>} Resolves once recorded.
484
+ * @throws {Error} 'token is required.' when `token` is falsy.
485
+ */
486
+ async recordAccessActivity(token: string, body: { eventType: 'play_started' | 'play_completed' }): Promise<void> {
487
+ if (!token) throw new Error('token is required.');
488
+ await client._request<void>({
489
+ method: 'POST',
490
+ endpoint: `/v1/public-download/${token}/access-activity`,
491
+ body,
492
+ sendJWT: false,
493
+ });
494
+ },
495
+ };
496
+ }
@@ -0,0 +1,94 @@
1
+ import NuramaClient from '../NuramaClient.js';
2
+
3
+ export interface CompleteUploadBody {
4
+ uploadId: string;
5
+ parts: Array<{ ETag: string; PartNumber: number }>;
6
+ }
7
+
8
+ export interface CompleteUploadResponse {
9
+ id: string;
10
+ url: string | null;
11
+ }
12
+
13
+ export interface PromoteBody {
14
+ /** Optional rename — lands on `Asset.name`. Defaults to a row-id-derived name. */
15
+ fileName?: string;
16
+ }
17
+
18
+ export interface PromoteResponse {
19
+ asset: unknown;
20
+ /**
21
+ * `true` when the scratch row was already promoted on a prior call
22
+ * (e.g. the same revision was Attached-to-chat earlier and the
23
+ * chat-send pipeline ran the promote synchronously). The returned
24
+ * `asset` is the existing one. The FE should treat this as a no-op
25
+ * for "newly added" UX (toast copy, list-refresh side effects) while
26
+ * still surfacing the asset.
27
+ */
28
+ alreadyPromoted: boolean;
29
+ }
30
+
31
+ /**
32
+ * Scratch — platform-wide temporary object-storage with explicit lifecycle.
33
+ *
34
+ * There is NO public surface for creating scratch rows or minting
35
+ * upload URLs. Parent processes (e.g. AI Revision) initiate the
36
+ * multipart upload server-side and return the
37
+ * `{ scratchId, uploadId, key, urls[] }` bundle in their own response
38
+ * payload. The FE uploads each part directly against its signed URL
39
+ * (same pattern as asset uploads), then calls `completeUpload` here to
40
+ * finalise.
41
+ *
42
+ * `completeUpload` mirrors `nuramaClient.asset.completeUpload`:
43
+ * the body is the same `{ uploadId, parts }` shape, the server runs the
44
+ * S3-compatible `CompleteMultipartUploadCommand`, and (for scratch
45
+ * specifically) HEADs the resulting object, increments workspace
46
+ * storage usage, and writes the audit row.
47
+ */
48
+ export default function createScratchMethods(client: NuramaClient) {
49
+ return {
50
+ /**
51
+ * Finish a multipart upload for a scratch row. Same `{ uploadId,
52
+ * parts }` body the asset complete-upload route accepts. Server
53
+ * runs `CompleteMultipartUploadCommand` against the media bucket,
54
+ * HEADs the object for size, increments workspace storage usage,
55
+ * writes the audit row, and flips status pendingUpload → active.
56
+ * Creator-only.
57
+ */
58
+ async completeUpload(scratchId: string, data: CompleteUploadBody): Promise<CompleteUploadResponse> {
59
+ if (!scratchId) throw new Error('scratchId is required.');
60
+ if (!data?.uploadId) throw new Error('uploadId is required.');
61
+ if (!Array.isArray(data?.parts) || data.parts.length === 0) {
62
+ throw new Error('parts is required.');
63
+ }
64
+ return client._request({
65
+ endpoint: `/v1/scratch/${encodeURIComponent(scratchId)}/complete-upload`,
66
+ method: 'POST',
67
+ body: data,
68
+ sendJWT: true,
69
+ });
70
+ },
71
+
72
+ /**
73
+ * Promote a scratch row to a real Asset. Creator-only — only the
74
+ * user who created the scratch row can call this. Destination is
75
+ * derived server-side from the row itself:
76
+ * - row has `projectId` → asset created in that project
77
+ * - row has only workspace → asset created at the workspace
78
+ *
79
+ * No body fields for destination on purpose: the FE doesn't get to
80
+ * claim a scratch belongs to a different workspace / project. The
81
+ * only optional input is `fileName` to override the asset's
82
+ * user-facing name.
83
+ */
84
+ async promote(scratchId: string, data: PromoteBody = {}): Promise<PromoteResponse> {
85
+ if (!scratchId) throw new Error('scratchId is required.');
86
+ return client._request({
87
+ endpoint: `/v1/scratch/${encodeURIComponent(scratchId)}/promote`,
88
+ method: 'POST',
89
+ body: data,
90
+ sendJWT: true,
91
+ });
92
+ },
93
+ };
94
+ }