@palettelab/sdk 0.1.9 → 0.1.10

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/README.md CHANGED
@@ -195,7 +195,7 @@ Included clients:
195
195
 
196
196
  - `palette.user.current()` and `palette.user.updateProfile()`
197
197
  - `palette.organization.currentId()`, `currentRole()`, and `listMine()`
198
- - `palette.dataRooms.list()`, `create()`, `get()`, `folder()`, and `uploadFile()`
198
+ - `palette.dataRooms.list()`, `create()`, `get()`, `folder()`, `createFolder()`, `ensureFolder()`, `findRoomByName()`, `findFolderByName()`, `resolveFolderPath()`, `findFileByName()`, and `uploadFile()`
199
199
  - `palette.config.get()` and `palette.config.update(values)`, with optional plugin ID override
200
200
  - `palette.permissions.has()`, `hasAny()`, and `hasAll()`
201
201
  - `palette.storage.uploadToSignedUrl()`
@@ -204,6 +204,41 @@ Included clients:
204
204
  These helpers are intentionally thin wrappers over platform APIs. Apps can still
205
205
  use `apiFetch()` directly for custom backend routes.
206
206
 
207
+ ### Data Room Folders By Name
208
+
209
+ Apps can create or reuse custom Data Room folders by name:
210
+
211
+ ```tsx
212
+ const palette = createPaletteClient(usePlatform())
213
+
214
+ const room = await palette.dataRooms.ensureRoom("Finance")
215
+ const invoices = await palette.dataRooms.ensureFolder(room.id, "Invoices")
216
+
217
+ await palette.dataRooms.uploadFile(room.id, file, {
218
+ folderId: invoices.id,
219
+ })
220
+ ```
221
+
222
+ Apps can also resolve nested folders:
223
+
224
+ ```tsx
225
+ const folder = await palette.dataRooms.resolveFolderPath(
226
+ room.id,
227
+ "Clients/Acme/Invoices",
228
+ { create: true },
229
+ )
230
+ ```
231
+
232
+ To read existing files by name:
233
+
234
+ ```tsx
235
+ const room = await palette.dataRooms.requireRoomByName("Finance")
236
+ const folder = await palette.dataRooms.resolveFolderPath(room.id, "Clients/Acme/Invoices")
237
+ const file = folder
238
+ ? await palette.dataRooms.findFileByName(room.id, "jan.pdf", { folderId: folder.id })
239
+ : null
240
+ ```
241
+
207
242
  ## Permissions
208
243
 
209
244
  Use permission helpers to keep UI actions aligned with backend permission gates.
package/dist/index.d.mts CHANGED
@@ -63,7 +63,14 @@ interface DataRoomUploadOptions {
63
63
  folderId?: number | null;
64
64
  contentType?: string;
65
65
  }
66
+ interface FindByNameOptions {
67
+ caseSensitive?: boolean;
68
+ }
69
+ interface EnsureFolderOptions extends FindByNameOptions {
70
+ parentFolderId?: number | null;
71
+ }
66
72
  declare class DataRoomClient {
73
+ private matchesName;
67
74
  list(): Promise<DataRoom[]>;
68
75
  create(input: {
69
76
  name: string;
@@ -71,6 +78,21 @@ declare class DataRoomClient {
71
78
  }): Promise<DataRoom>;
72
79
  get(roomId: number): Promise<DataRoomContents>;
73
80
  folder(roomId: number, folderId: number): Promise<DataRoomContents>;
81
+ findRoomByName(name: string, options?: FindByNameOptions): Promise<DataRoom | null>;
82
+ requireRoomByName(name: string, options?: FindByNameOptions): Promise<DataRoom>;
83
+ ensureRoom(name: string, description?: string | null): Promise<DataRoom>;
84
+ createFolder(roomId: number, input: {
85
+ name: string;
86
+ parentFolderId?: number | null;
87
+ }): Promise<DataRoomFolder>;
88
+ findFolderByName(roomId: number, name: string, options?: EnsureFolderOptions): Promise<DataRoomFolder | null>;
89
+ ensureFolder(roomId: number, name: string, options?: EnsureFolderOptions): Promise<DataRoomFolder>;
90
+ resolveFolderPath(roomId: number, path: string | string[], options?: FindByNameOptions & {
91
+ create?: boolean;
92
+ }): Promise<DataRoomFolder | null>;
93
+ findFileByName(roomId: number, name: string, options?: FindByNameOptions & {
94
+ folderId?: number | null;
95
+ }): Promise<DataRoomFile | null>;
74
96
  requestUpload(roomId: number, file: File, options?: DataRoomUploadOptions): Promise<{
75
97
  upload_url: string;
76
98
  blob_path: string;
package/dist/index.d.ts CHANGED
@@ -63,7 +63,14 @@ interface DataRoomUploadOptions {
63
63
  folderId?: number | null;
64
64
  contentType?: string;
65
65
  }
66
+ interface FindByNameOptions {
67
+ caseSensitive?: boolean;
68
+ }
69
+ interface EnsureFolderOptions extends FindByNameOptions {
70
+ parentFolderId?: number | null;
71
+ }
66
72
  declare class DataRoomClient {
73
+ private matchesName;
67
74
  list(): Promise<DataRoom[]>;
68
75
  create(input: {
69
76
  name: string;
@@ -71,6 +78,21 @@ declare class DataRoomClient {
71
78
  }): Promise<DataRoom>;
72
79
  get(roomId: number): Promise<DataRoomContents>;
73
80
  folder(roomId: number, folderId: number): Promise<DataRoomContents>;
81
+ findRoomByName(name: string, options?: FindByNameOptions): Promise<DataRoom | null>;
82
+ requireRoomByName(name: string, options?: FindByNameOptions): Promise<DataRoom>;
83
+ ensureRoom(name: string, description?: string | null): Promise<DataRoom>;
84
+ createFolder(roomId: number, input: {
85
+ name: string;
86
+ parentFolderId?: number | null;
87
+ }): Promise<DataRoomFolder>;
88
+ findFolderByName(roomId: number, name: string, options?: EnsureFolderOptions): Promise<DataRoomFolder | null>;
89
+ ensureFolder(roomId: number, name: string, options?: EnsureFolderOptions): Promise<DataRoomFolder>;
90
+ resolveFolderPath(roomId: number, path: string | string[], options?: FindByNameOptions & {
91
+ create?: boolean;
92
+ }): Promise<DataRoomFolder | null>;
93
+ findFileByName(roomId: number, name: string, options?: FindByNameOptions & {
94
+ folderId?: number | null;
95
+ }): Promise<DataRoomFile | null>;
74
96
  requestUpload(roomId: number, file: File, options?: DataRoomUploadOptions): Promise<{
75
97
  upload_url: string;
76
98
  blob_path: string;
package/dist/index.js CHANGED
@@ -231,6 +231,10 @@ function withPluginProvider(element, platform = {}) {
231
231
 
232
232
  // src/data-rooms.ts
233
233
  var DataRoomClient = class {
234
+ matchesName(actual, expected, options = {}) {
235
+ if (options.caseSensitive) return actual === expected;
236
+ return actual.localeCompare(expected, void 0, { sensitivity: "accent" }) === 0;
237
+ }
234
238
  async list() {
235
239
  const res = await apiFetch("/api/v1/data-rooms");
236
240
  return res.json();
@@ -250,6 +254,50 @@ var DataRoomClient = class {
250
254
  const res = await apiFetch(`/api/v1/data-rooms/${roomId}/folders/${folderId}`);
251
255
  return res.json();
252
256
  }
257
+ async findRoomByName(name, options = {}) {
258
+ const rooms = await this.list();
259
+ return rooms.find((room) => this.matchesName(room.name, name, options)) ?? null;
260
+ }
261
+ async requireRoomByName(name, options = {}) {
262
+ const room = await this.findRoomByName(name, options);
263
+ if (!room) throw new Error(`Data Room not found: ${name}`);
264
+ return room;
265
+ }
266
+ async ensureRoom(name, description) {
267
+ return await this.findRoomByName(name) ?? this.create({ name, description });
268
+ }
269
+ async createFolder(roomId, input) {
270
+ const res = await apiFetch(`/api/v1/data-rooms/${roomId}/folders`, {
271
+ method: "POST",
272
+ body: JSON.stringify({
273
+ name: input.name,
274
+ parent_folder_id: input.parentFolderId ?? null
275
+ })
276
+ });
277
+ return res.json();
278
+ }
279
+ async findFolderByName(roomId, name, options = {}) {
280
+ const contents = options.parentFolderId ? await this.folder(roomId, options.parentFolderId) : await this.get(roomId);
281
+ return contents.folders.find((folder) => this.matchesName(folder.name, name, options)) ?? null;
282
+ }
283
+ async ensureFolder(roomId, name, options = {}) {
284
+ return await this.findFolderByName(roomId, name, options) ?? this.createFolder(roomId, { name, parentFolderId: options.parentFolderId ?? null });
285
+ }
286
+ async resolveFolderPath(roomId, path, options = {}) {
287
+ const parts = Array.isArray(path) ? path : path.split("/").map((part) => part.trim()).filter(Boolean);
288
+ let parentFolderId = null;
289
+ let current = null;
290
+ for (const part of parts) {
291
+ current = options.create ? await this.ensureFolder(roomId, part, { ...options, parentFolderId }) : await this.findFolderByName(roomId, part, { ...options, parentFolderId });
292
+ if (!current) return null;
293
+ parentFolderId = current.id;
294
+ }
295
+ return current;
296
+ }
297
+ async findFileByName(roomId, name, options = {}) {
298
+ const contents = options.folderId ? await this.folder(roomId, options.folderId) : await this.get(roomId);
299
+ return contents.files.find((file) => this.matchesName(file.original_filename, name, options)) ?? null;
300
+ }
253
301
  async requestUpload(roomId, file, options = {}) {
254
302
  const res = await apiFetch(`/api/v1/data-rooms/${roomId}/files/request-upload`, {
255
303
  method: "POST",
package/dist/index.mjs CHANGED
@@ -177,6 +177,10 @@ function withPluginProvider(element, platform = {}) {
177
177
 
178
178
  // src/data-rooms.ts
179
179
  var DataRoomClient = class {
180
+ matchesName(actual, expected, options = {}) {
181
+ if (options.caseSensitive) return actual === expected;
182
+ return actual.localeCompare(expected, void 0, { sensitivity: "accent" }) === 0;
183
+ }
180
184
  async list() {
181
185
  const res = await apiFetch("/api/v1/data-rooms");
182
186
  return res.json();
@@ -196,6 +200,50 @@ var DataRoomClient = class {
196
200
  const res = await apiFetch(`/api/v1/data-rooms/${roomId}/folders/${folderId}`);
197
201
  return res.json();
198
202
  }
203
+ async findRoomByName(name, options = {}) {
204
+ const rooms = await this.list();
205
+ return rooms.find((room) => this.matchesName(room.name, name, options)) ?? null;
206
+ }
207
+ async requireRoomByName(name, options = {}) {
208
+ const room = await this.findRoomByName(name, options);
209
+ if (!room) throw new Error(`Data Room not found: ${name}`);
210
+ return room;
211
+ }
212
+ async ensureRoom(name, description) {
213
+ return await this.findRoomByName(name) ?? this.create({ name, description });
214
+ }
215
+ async createFolder(roomId, input) {
216
+ const res = await apiFetch(`/api/v1/data-rooms/${roomId}/folders`, {
217
+ method: "POST",
218
+ body: JSON.stringify({
219
+ name: input.name,
220
+ parent_folder_id: input.parentFolderId ?? null
221
+ })
222
+ });
223
+ return res.json();
224
+ }
225
+ async findFolderByName(roomId, name, options = {}) {
226
+ const contents = options.parentFolderId ? await this.folder(roomId, options.parentFolderId) : await this.get(roomId);
227
+ return contents.folders.find((folder) => this.matchesName(folder.name, name, options)) ?? null;
228
+ }
229
+ async ensureFolder(roomId, name, options = {}) {
230
+ return await this.findFolderByName(roomId, name, options) ?? this.createFolder(roomId, { name, parentFolderId: options.parentFolderId ?? null });
231
+ }
232
+ async resolveFolderPath(roomId, path, options = {}) {
233
+ const parts = Array.isArray(path) ? path : path.split("/").map((part) => part.trim()).filter(Boolean);
234
+ let parentFolderId = null;
235
+ let current = null;
236
+ for (const part of parts) {
237
+ current = options.create ? await this.ensureFolder(roomId, part, { ...options, parentFolderId }) : await this.findFolderByName(roomId, part, { ...options, parentFolderId });
238
+ if (!current) return null;
239
+ parentFolderId = current.id;
240
+ }
241
+ return current;
242
+ }
243
+ async findFileByName(roomId, name, options = {}) {
244
+ const contents = options.folderId ? await this.folder(roomId, options.folderId) : await this.get(roomId);
245
+ return contents.files.find((file) => this.matchesName(file.original_filename, name, options)) ?? null;
246
+ }
199
247
  async requestUpload(roomId, file, options = {}) {
200
248
  const res = await apiFetch(`/api/v1/data-rooms/${roomId}/files/request-upload`, {
201
249
  method: "POST",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@palettelab/sdk",
3
- "version": "0.1.9",
3
+ "version": "0.1.10",
4
4
  "description": "Palette Platform SDK for building plugins and apps",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",