Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/oauth-scopes.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ Before running the function, `invoke()` also acquires a Studio Web license for t
| `getByName()` | `OR.Buckets` or `OR.Buckets.Read` |
| `getFileMetaData()` | `OR.Buckets` or `OR.Buckets.Read` |
| `getReadUri()` | `OR.Buckets` or `OR.Buckets.Read` |
| `uploadFile()` | `OR.Buckets` |
| `uploadFile()` | `OR.Buckets` or `OR.Buckets.Write` |
| `deleteFile()` | `OR.Buckets` or `OR.Buckets.Write` |
| `getFiles()` | `OR.Buckets` or `OR.Buckets.Read` |

Expand Down
168 changes: 126 additions & 42 deletions src/models/orchestrator/buckets.models.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { BucketGetAllOptions, BucketGetByIdOptions, BucketGetByNameOptions, BucketGetResponse, BucketGetFileMetaDataWithPaginationOptions, BucketGetReadUriOptions, BucketGetReadUriRequestOptions, BucketGetUriResponse, BucketUploadFileOptions, BucketUploadFileRequestOptions, BucketUploadResponse, BlobItem, BucketGetFilesOptions, BucketFile, BucketDeleteFileOptions } from './buckets.types';
import { BucketGetAllOptions, BucketGetByIdOptions, BucketGetByNameOptions, BucketGetResponse, BucketGetFileMetaDataWithPaginationOptions, BucketGetReadUriOptions, BucketGetReadUriRequestOptions, BucketGetUriResponse, BucketRef, BucketUploadFileOptions, BucketUploadFileRequestOptions, BucketUploadResponse, BlobItem, BucketGetFilesOptions, BucketFile, BucketDeleteFileOptions } from './buckets.types';
import { PaginatedResponse, NonPaginatedResponse, HasPaginationOptions } from '../../utils/pagination';

/**
Expand Down Expand Up @@ -111,33 +111,49 @@ export interface BucketServiceModel {
* - A NonPaginatedResponse with items array (when no pagination parameters are provided)
* - A PaginatedResponse with navigation cursors (when any pagination parameter is provided)
*
* @param bucketId - The ID of the bucket to get file metadata from
* @param bucketRef - Bucket ref (`{ id }` or `{ name }`). `{ name }` triggers an internal
* name lookup where runtime resource overrides may redirect the target across folders.
* @param options - Folder scoping (`folderId` / `folderKey` / `folderPath`) and optional parameters for filtering and pagination
* @returns Promise resolving to either an array of files metadata NonPaginatedResponse<BlobItem> or a PaginatedResponse<BlobItem> when pagination options are used.
* {@link BlobItem}
* @example
* ```typescript
* // By folder ID
* const fileMetadata = await buckets.getFileMetaData(<bucketId>, { folderId: <folderId> });
*
* // By folder key (GUID)
* await buckets.getFileMetaData(<bucketId>, { folderKey: '5f6dadf1-3677-49dc-8aca-c2999dd4b3ba' });
* // By bucket id
* const fileMetadata = await buckets.getFileMetaData({ id: <bucketId> }, { folderId: <folderId> });
*
* // By folder path
* await buckets.getFileMetaData(<bucketId>, { folderPath: 'Shared/Finance' });
* // By bucket name (folder scoping applies to both the name lookup and the meta-data read)
* await buckets.getFileMetaData({ name: 'InvoicesBucket' }, { folderPath: 'Shared/Finance' });
*
* // Filter by prefix
* await buckets.getFileMetaData(<bucketId>, { folderId: <folderId>, prefix: '/folder1' });
* await buckets.getFileMetaData({ id: <bucketId> }, { folderId: <folderId>, prefix: '/folder1' });
*
* // First page with pagination
* const page1 = await buckets.getFileMetaData(<bucketId>, { folderId: <folderId>, pageSize: 10 });
* const page1 = await buckets.getFileMetaData({ id: <bucketId> }, { folderId: <folderId>, pageSize: 10 });
*
* // Navigate using cursor
* if (page1.hasNextPage) {
* const page2 = await buckets.getFileMetaData(<bucketId>, { folderId: <folderId>, cursor: page1.nextCursor });
* const page2 = await buckets.getFileMetaData({ id: <bucketId> }, { folderId: <folderId>, cursor: page1.nextCursor });
* }
* ```
*/
getFileMetaData<T extends BucketGetFileMetaDataWithPaginationOptions = BucketGetFileMetaDataWithPaginationOptions>(
bucketRef: BucketRef,
options?: T,
): Promise<
T extends HasPaginationOptions<T>
? PaginatedResponse<BlobItem>
: NonPaginatedResponse<BlobItem>
>;
/**
* Gets metadata for files in a bucket — numeric bucket id form.
*
* @deprecated Use the ref-based form: `getFileMetaData({ id: bucketId }, options?)`. See {@link BucketRef}.
*
* @param bucketId - The ID of the bucket to get file metadata from
* @param options - Folder scoping (`folderId` / `folderKey` / `folderPath`) and optional parameters for filtering and pagination
* @returns Promise resolving to either an array of files metadata NonPaginatedResponse<BlobItem> or a PaginatedResponse<BlobItem> when pagination options are used.
* {@link BlobItem}
*/
getFileMetaData<T extends BucketGetFileMetaDataWithPaginationOptions = BucketGetFileMetaDataWithPaginationOptions>(
bucketId: number,
options?: T,
Expand All @@ -149,7 +165,7 @@ export interface BucketServiceModel {
/**
* Gets metadata for files in a bucket — positional `folderId` form.
*
* @deprecated Use the options-object form: `getFileMetaData(bucketId, { folderId })`. See {@link BucketGetFileMetaDataWithPaginationOptions} for the supported options.
* @deprecated Use the ref-based form: `getFileMetaData({ id: bucketId }, { folderId })`. See {@link BucketRef}.
*
* @param bucketId - The ID of the bucket to get file metadata from
* @param folderId - Required folder ID (numeric)
Expand All @@ -173,23 +189,37 @@ export interface BucketServiceModel {
* Folder context can be supplied as `folderId`, `folderKey`, or `folderPath`
* in the options.
*
* @param bucketId - The ID of the bucket
* @param bucketRef - Bucket ref (`{ id }` or `{ name }`). `{ name }` triggers an internal
* name lookup where runtime resource overrides may redirect the target across folders.
* @param path - The full path to the file
* @param options - Folder scoping (`folderId` / `folderKey` / `folderPath`) and optional `expiryInMinutes`
* @returns Promise resolving to blob file access information
* {@link BucketGetUriResponse}
* @example
* ```typescript
* // By folder ID
* await buckets.getReadUri(<bucketId>, '/folder/file.pdf', { folderId: <folderId> });
* // By bucket id
* await buckets.getReadUri({ id: <bucketId> }, '/folder/file.pdf', { folderId: <folderId> });
*
* // By folder key (GUID)
* await buckets.getReadUri(<bucketId>, '/folder/file.pdf', { folderKey: '5f6dadf1-3677-49dc-8aca-c2999dd4b3ba' });
*
* // By folder path
* await buckets.getReadUri(<bucketId>, '/folder/file.pdf', { folderPath: 'Shared/Finance' });
* // By bucket name (folder scoping applies to both the name lookup and the read)
* await buckets.getReadUri({ name: 'MyBucket' }, '/folder/file.pdf', { folderPath: 'Shared/Finance' });
* ```
*/
getReadUri(
bucketRef: BucketRef,
path: string,
options?: BucketGetReadUriRequestOptions,
): Promise<BucketGetUriResponse>;
/**
* Gets a direct download URL for a file in the bucket — numeric bucket id form.
*
* @deprecated Use the ref-based form: `getReadUri({ id: bucketId }, path, options?)`. See {@link BucketRef}.
*
* @param bucketId - The ID of the bucket
* @param path - The full path to the file
* @param options - Folder scoping (`folderId` / `folderKey` / `folderPath`) and optional `expiryInMinutes`
* @returns Promise resolving to blob file access information
* {@link BucketGetUriResponse}
*/
getReadUri(
bucketId: number,
path: string,
Expand All @@ -198,7 +228,7 @@ export interface BucketServiceModel {
/**
* Gets a direct download URL for a file in the bucket — options-only form.
*
* @deprecated Use the positional form: `getReadUri(bucketId, path, options?)`. See {@link BucketGetReadUriRequestOptions} for the supported options.
* @deprecated Use the ref-based form: `getReadUri({ id: bucketId }, path, options?)`. See {@link BucketRef}.
*
* @param options - Contains bucketId, folder scoping (`folderId` / `folderKey` / `folderPath`), file path and optional expiry time
* @returns Promise resolving to blob file access information
Expand All @@ -212,29 +242,45 @@ export interface BucketServiceModel {
* Folder context can be supplied as `folderId`, `folderKey`, or `folderPath`
* in the options.
*
* @param bucketId - The ID of the bucket to upload to
* @param bucketRef - Bucket ref (`{ id }` or `{ name }`). `{ name }` triggers an internal
* name lookup where runtime resource overrides may redirect the target across folders.
* @param path - Path where the file should be stored in the bucket
* @param content - File content to upload
* @param options - Folder scoping (`folderId` / `folderKey` / `folderPath`)
* @returns Promise resolving bucket upload response
* {@link BucketUploadResponse}
* @example
* ```typescript
* // By folder ID
* // By bucket id
* const file = new File(['file content'], 'example.txt');
* await buckets.uploadFile(<bucketId>, '/folder/example.txt', file, { folderId: <folderId> });
* await buckets.uploadFile({ id: <bucketId> }, '/folder/example.txt', file, { folderId: <folderId> });
*
* // By folder key (GUID)
* await buckets.uploadFile(<bucketId>, '/folder/example.txt', file, { folderKey: '5f6dadf1-3677-49dc-8aca-c2999dd4b3ba' });
*
* // By folder path
* await buckets.uploadFile(<bucketId>, '/folder/example.txt', file, { folderPath: 'Shared/Finance' });
* // By bucket name (folder scoping applies to both the name lookup and the upload)
* await buckets.uploadFile({ name: 'MyBucket' }, '/folder/example.txt', file, { folderPath: 'Shared/Finance' });
*
* // In Node env with Uint8Array or Buffer
* const content = new TextEncoder().encode('file content');
* await buckets.uploadFile(<bucketId>, '/folder/example.txt', content, { folderId: <folderId> });
* await buckets.uploadFile({ id: <bucketId> }, '/folder/example.txt', content, { folderId: <folderId> });
* ```
*/
uploadFile(
bucketRef: BucketRef,
path: string,
content: Blob | Uint8Array<ArrayBuffer> | File,
options?: BucketUploadFileRequestOptions,
): Promise<BucketUploadResponse>;
/**
* Uploads a file to a bucket — numeric bucket id form.
*
* @deprecated Use the ref-based form: `uploadFile({ id: bucketId }, path, content, options?)`. See {@link BucketRef}.
*
* @param bucketId - The ID of the bucket
* @param path - Path where the file should be stored in the bucket
* @param content - File content to upload
* @param options - Folder scoping (`folderId` / `folderKey` / `folderPath`)
* @returns Promise resolving bucket upload response
* {@link BucketUploadResponse}
*/
uploadFile(
bucketId: number,
path: string,
Expand All @@ -244,7 +290,7 @@ export interface BucketServiceModel {
/**
* Uploads a file to a bucket — options-only form.
*
* @deprecated Use the positional form: `uploadFile(bucketId, path, content, options?)`. See {@link BucketUploadFileRequestOptions} for the supported options.
* @deprecated Use the ref-based form: `uploadFile({ id: bucketId }, path, content, options?)`. See {@link BucketRef}.
*
* @param options - Options for file upload including bucket ID, folder scoping (`folderId` / `folderKey` / `folderPath`), path, and content
* @returns Promise resolving bucket upload response
Expand All @@ -255,16 +301,31 @@ export interface BucketServiceModel {
/**
* Deletes a file from a bucket
*
* @param bucketId - The ID of the bucket
* @param bucketRef - Bucket ref (`{ id }` or `{ name }`). `{ name }` triggers an internal
* name lookup where runtime resource overrides may redirect the target across folders.
* @param path - The full path to the file to delete
* @param options - Folder scoping (`folderId` / `folderKey` / `folderPath`)
* @returns Promise resolving when the file is deleted
* @example
* ```typescript
* // Delete a file from a bucket
* await buckets.deleteFile(<bucketId>, '/folder/file.pdf', { folderId: <folderId> });
* // By bucket id
* await buckets.deleteFile({ id: <bucketId> }, '/folder/file.pdf', { folderId: <folderId> });
*
* // By bucket name
* await buckets.deleteFile({ name: 'MyBucket' }, '/folder/file.pdf', { folderPath: 'Shared/Finance' });
* ```
*/
deleteFile(bucketRef: BucketRef, path: string, options?: BucketDeleteFileOptions): Promise<void>;
/**
* Deletes a file from a bucket — numeric bucket id form.
*
* @deprecated Use the ref-based form: `deleteFile({ id: bucketId }, path, options?)`. See {@link BucketRef}.
*
* @param bucketId - The ID of the bucket
* @param path - The full path to the file to delete
* @param options - Folder scoping (`folderId` / `folderKey` / `folderPath`)
* @returns Promise resolving when the file is deleted
*/
deleteFile(bucketId: number, path: string, options?: BucketDeleteFileOptions): Promise<void>;

/**
Expand All @@ -278,38 +339,61 @@ export interface BucketServiceModel {
* - A NonPaginatedResponse with items array (when no pagination parameters are provided)
* - A PaginatedResponse with navigation cursors (when any pagination parameter is provided)
*
* @param bucketId - The ID of the bucket
* @param bucketRef - Bucket ref (`{ id }` or `{ name }`). `{ name }` triggers an internal
* name lookup where runtime resource overrides may redirect the target across folders.
* @param options - Folder scoping (`folderId` / `folderKey` / `folderPath`) and optional parameters for regex filtering, query options, and pagination
* {@link BucketGetFilesOptions}
* @returns Promise resolving to either an array of files NonPaginatedResponse<BucketFile> or a PaginatedResponse<BucketFile> when pagination options are used.
* {@link BucketFile}
* @example
* ```typescript
* // List all files in the bucket
* const files = await buckets.getFiles(<bucketId>, { folderId: <folderId> });
* // By bucket id
* const files = await buckets.getFiles({ id: <bucketId> }, { folderId: <folderId> });
*
* // By bucket name (folder scoping applies to both the name lookup and the listing)
* const filesByName = await buckets.getFiles({ name: 'MyBucket' }, { folderPath: 'Shared/Finance' });
*
* // Filter by regex pattern
* const pdfs = await buckets.getFiles(<bucketId>, {
* const pdfs = await buckets.getFiles({ id: <bucketId> }, {
* folderId: <folderId>,
* fileNameRegex: '.*\\.pdf$'
* });
*
* // First page with pagination
* const page1 = await buckets.getFiles(<bucketId>, { folderId: <folderId>, pageSize: 10 });
* const page1 = await buckets.getFiles({ id: <bucketId> }, { folderId: <folderId>, pageSize: 10 });
*
* // Navigate using cursor
* if (page1.hasNextPage) {
* const page2 = await buckets.getFiles(<bucketId>, { folderId: <folderId>, cursor: page1.nextCursor });
* const page2 = await buckets.getFiles({ id: <bucketId> }, { folderId: <folderId>, cursor: page1.nextCursor });
* }
*
* // Jump to specific page
* const page5 = await buckets.getFiles(<bucketId>, {
* const page5 = await buckets.getFiles({ id: <bucketId> }, {
* folderId: <folderId>,
* jumpToPage: 5,
* pageSize: 10
* });
* ```
*/
getFiles<T extends BucketGetFilesOptions = BucketGetFilesOptions>(
bucketRef: BucketRef,
options?: T
): Promise<
T extends HasPaginationOptions<T>
? PaginatedResponse<BucketFile>
: NonPaginatedResponse<BucketFile>
>;
/**
* Lists all files in a bucket — numeric bucket id form.
*
* @deprecated Use the ref-based form: `getFiles({ id: bucketId }, options?)`. See {@link BucketRef}.
*
* @param bucketId - The ID of the bucket
* @param options - Folder scoping (`folderId` / `folderKey` / `folderPath`) and optional parameters for regex filtering, query options, and pagination
* {@link BucketGetFilesOptions}
* @returns Promise resolving to either an array of files NonPaginatedResponse<BucketFile> or a PaginatedResponse<BucketFile> when pagination options are used.
* {@link BucketFile}
*/
getFiles<T extends BucketGetFilesOptions = BucketGetFilesOptions>(
bucketId: number,
options?: T
Expand Down
14 changes: 14 additions & 0 deletions src/models/orchestrator/buckets.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,20 @@ export interface BucketGetByIdOptions extends BaseOptions {}
*/
export interface BucketGetByNameOptions extends FolderScopedOptions {}

/**
* Selects a bucket by exactly one identifier — `{ id }` numeric or `{ name }`
* (folder-scoped). Used by the ref-based file-op signatures on
* {@link BucketServiceModel} (`uploadFile`, `deleteFile`, `getReadUri`,
* `getFiles`, `getFileMetaData`). `{ name }` triggers an internal
* folder-scoped lookup so runtime overrides apply; `{ id }` skips the lookup.
*
* Narrower than the generic {@link ResourceRef} — buckets don't have a public GUID key
* on their operational routes, so `{ key }` is intentionally not part of this union.
*/
export type BucketRef =
| { id: number; name?: never; key?: never }
| { name: string; id?: never; key?: never };

/**
* Maps header names to their values
*
Expand Down
Loading
Loading