Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ This changelog follows the principles of [Keep a Changelog](https://keepachangel

### Added

- Datasets: Added `getDatasetStorageDriver` use case and repository method to support Dataverse endpoint `GET /datasets/{identifier}/storageDriver`, for retrieving dataset storage driver configuration with properties: name, type, label, directUpload, directDownload, and uploadOutOfBand.
- Datasets: Added `updateDatasetLicense` use case and repository method to support Dataverse endpoint `PUT /datasets/{id}/license`, for updating dataset license or custom terms
- New Use Case: [Get Collections For Linking Use Case](./docs/useCases.md#get-collections-for-linking).
- New Use Case: [Create a Dataset Template](./docs/useCases.md#create-a-dataset-template) under Collections.
Expand Down
25 changes: 25 additions & 0 deletions docs/useCases.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ The different use cases currently available in the package are classified below,
- [Get Dataset Linked Collections](#get-dataset-linked-collections)
- [Get Dataset Available Categories](#get-dataset-available-categories)
- [Get Dataset Templates](#get-dataset-templates)
- [Get Dataset Storage Driver](#get-dataset-storage-driver)
- [Get Dataset Available Dataset Types](#get-dataset-available-dataset-types)
- [Get Dataset Available Dataset Type](#get-dataset-available-dataset-type)
- [Datasets write use cases](#datasets-write-use-cases)
Expand Down Expand Up @@ -1351,6 +1352,30 @@ getDatasetTemplates.execute(collectionIdOrAlias).then((datasetTemplates: Dataset

_See [use case](../src/datasets/domain/useCases/GetDatasetTemplates.ts)_ definition.

#### Get Dataset Storage Driver

Returns a [StorageDriver](../src/datasets/domain/models/StorageDriver.ts) instance with storage driver configuration for a dataset, including properties like name, type, label, and upload/download capabilities.

##### Example call:

```typescript
import { getDatasetStorageDriver } from '@iqss/dataverse-client-javascript'

/* ... */

const datasetId = 'doi:10.77777/FK2/AAAAAA'

getDatasetStorageDriver.execute(datasetId).then((storageDriver: StorageDriver) => {
/* ... */
})

/* ... */
```

_See [use case](../src/datasets/domain/useCases/GetDatasetStorageDriver.ts)_ implementation\_.
Comment thread
ChengShi-1 marked this conversation as resolved.
Outdated

The `datasetId` parameter can be a string, for persistent identifiers, or a number, for numeric identifiers.

#### Add a Dataset Type

Adds a dataset types that can be used at dataset creation.
Expand Down
8 changes: 8 additions & 0 deletions src/datasets/domain/models/StorageDriver.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export interface StorageDriver {
name: string
type: string
label: string
directUpload: boolean
directDownload: boolean
uploadOutOfBand: boolean
}
2 changes: 2 additions & 0 deletions src/datasets/domain/repositories/IDatasetsRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { DatasetType } from '../models/DatasetType'
import { TermsOfAccess } from '../models/Dataset'
import { DatasetLicenseUpdateRequest } from '../dtos/DatasetLicenseUpdateRequest'
import { DatasetTypeDTO } from '../dtos/DatasetTypeDTO'
import { StorageDriver } from '../models/StorageDriver'

export interface IDatasetsRepository {
getDataset(
Expand Down Expand Up @@ -102,4 +103,5 @@ export interface IDatasetsRepository {
datasetId: number | string,
payload: DatasetLicenseUpdateRequest
): Promise<void>
getDatasetStorageDriver(datasetId: number | string): Promise<StorageDriver>
}
21 changes: 21 additions & 0 deletions src/datasets/domain/useCases/GetDatasetStorageDriver.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { UseCase } from '../../../core/domain/useCases/UseCase'
import { IDatasetsRepository } from '../repositories/IDatasetsRepository'
import { StorageDriver } from '../models/StorageDriver'

export class GetDatasetStorageDriver implements UseCase<StorageDriver> {
private datasetsRepository: IDatasetsRepository

constructor(datasetsRepository: IDatasetsRepository) {
this.datasetsRepository = datasetsRepository
}

/**
* Returns the storage driver information for a given Dataset.
*
* @param {number | string} [datasetId] - The dataset identifier, which can be a string (for persistent identifiers), or a number (for numeric identifiers).
* @returns {Promise<StorageDriver>}
*/
async execute(datasetId: number | string): Promise<StorageDriver> {
return this.datasetsRepository.getDatasetStorageDriver(datasetId)
}
}
5 changes: 4 additions & 1 deletion src/datasets/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import { GetDatasetCitationInOtherFormats } from './domain/useCases/GetDatasetCi
import { GetDatasetTemplates } from './domain/useCases/GetDatasetTemplates'
import { UpdateTermsOfAccess } from './domain/useCases/UpdateTermsOfAccess'
import { UpdateDatasetLicense } from './domain/useCases/UpdateDatasetLicense'
import { GetDatasetStorageDriver } from './domain/useCases/GetDatasetStorageDriver'

const datasetsRepository = new DatasetsRepository()

Expand Down Expand Up @@ -84,6 +85,7 @@ const getDatasetCitationInOtherFormats = new GetDatasetCitationInOtherFormats(da
const getDatasetTemplates = new GetDatasetTemplates(datasetsRepository)
const updateTermsOfAccess = new UpdateTermsOfAccess(datasetsRepository)
const updateDatasetLicense = new UpdateDatasetLicense(datasetsRepository)
const getDatasetStorageDriver = new GetDatasetStorageDriver(datasetsRepository)

export {
getDataset,
Expand Down Expand Up @@ -115,7 +117,8 @@ export {
linkDatasetTypeWithMetadataBlocks,
setAvailableLicensesForDatasetType,
deleteDatasetType,
updateDatasetLicense
updateDatasetLicense,
getDatasetStorageDriver
Comment thread
ChengShi-1 marked this conversation as resolved.
}
export { DatasetNotNumberedVersion } from './domain/models/DatasetNotNumberedVersion'
export { DatasetUserPermissions } from './domain/models/DatasetUserPermissions'
Expand Down
12 changes: 12 additions & 0 deletions src/datasets/infra/repositories/DatasetsRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import { TermsOfAccess } from '../../domain/models/Dataset'
import { transformTermsOfAccessToUpdatePayload } from './transformers/termsOfAccessTransformers'
import { DatasetLicenseUpdateRequest } from '../../domain/dtos/DatasetLicenseUpdateRequest'
import { DatasetTypeDTO } from '../../domain/dtos/DatasetTypeDTO'
import { StorageDriver } from '../../domain/models/StorageDriver'

export interface GetAllDatasetPreviewsQueryParams {
per_page?: number
Expand Down Expand Up @@ -515,4 +516,15 @@ export class DatasetsRepository extends ApiRepository implements IDatasetsReposi
throw error
})
}

public async getDatasetStorageDriver(datasetId: number | string): Promise<StorageDriver> {
return this.doGet(
this.buildApiEndpoint(this.datasetsResourceName, 'storageDriver', datasetId),
true
)
.then((response) => response.data.data as StorageDriver)
.catch((error) => {
throw error
})
}
}
24 changes: 24 additions & 0 deletions test/integration/datasets/DatasetsRepository.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2244,4 +2244,28 @@ describe('DatasetsRepository', () => {
await deleteUnpublishedDatasetViaApi(testDatasetIds.numericId)
})
})

describe('getDatasetStorageDriver', () => {
let testDatasetIds: CreatedDatasetIdentifiers

beforeAll(async () => {
testDatasetIds = await createDataset.execute(TestConstants.TEST_NEW_DATASET_DTO)
await publishDatasetViaApi(testDatasetIds.numericId)
await waitForNoLocks(testDatasetIds.numericId, 10)
})

afterAll(async () => {
await deletePublishedDatasetViaApi(testDatasetIds.persistentId)
})

test('should return storage driver info for dataset', async () => {
const storageDriver = await sut.getDatasetStorageDriver(testDatasetIds.numericId)
expect(storageDriver).toHaveProperty('name')
expect(storageDriver).toHaveProperty('type')
expect(storageDriver).toHaveProperty('label')
expect(typeof storageDriver.directUpload).toBe('boolean')
expect(typeof storageDriver.directDownload).toBe('boolean')
expect(typeof storageDriver.uploadOutOfBand).toBe('boolean')
})
})
})
51 changes: 51 additions & 0 deletions test/unit/datasets/GetDatasetStorageDriver.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { GetDatasetStorageDriver } from '../../../src/datasets/domain/useCases/GetDatasetStorageDriver'
import { IDatasetsRepository } from '../../../src/datasets/domain/repositories/IDatasetsRepository'
import { StorageDriver } from '../../../src/datasets/domain/models/StorageDriver'
import { ReadError } from '../../../src/core/domain/repositories/ReadError'

describe('GetDatasetStorageDriver (unit)', () => {
const testStorageDriver: StorageDriver = {
name: 'local',
type: 'filesystem',
label: 'Local Storage',
directUpload: true,
directDownload: true,
uploadOutOfBand: false
}

test('should return storage driver on repository success', async () => {
const datasetsRepositoryStub: IDatasetsRepository = {} as IDatasetsRepository
datasetsRepositoryStub.getDatasetStorageDriver = jest.fn().mockResolvedValue(testStorageDriver)
const sut = new GetDatasetStorageDriver(datasetsRepositoryStub)

const actual = await sut.execute(1)

expect(actual).toEqual(testStorageDriver)
expect(actual.name).toBe('local')
expect(actual.type).toBe('filesystem')
expect(actual.label).toBe('Local Storage')
expect(actual.directUpload).toBe(true)
expect(actual.directDownload).toBe(true)
expect(actual.uploadOutOfBand).toBe(false)
})

test('should return storage driver when using persistent id', async () => {
const datasetsRepositoryStub: IDatasetsRepository = {} as IDatasetsRepository
datasetsRepositoryStub.getDatasetStorageDriver = jest.fn().mockResolvedValue(testStorageDriver)
const sut = new GetDatasetStorageDriver(datasetsRepositoryStub)

const actual = await sut.execute('doi:10.77777/FK2/AAAAAA')

expect(actual).toEqual(testStorageDriver)
})

test('should return error result on repository error', async () => {
const datasetsRepositoryStub: IDatasetsRepository = {} as IDatasetsRepository
datasetsRepositoryStub.getDatasetStorageDriver = jest
.fn()
.mockRejectedValue(new ReadError('[404] Dataset not found'))
const sut = new GetDatasetStorageDriver(datasetsRepositoryStub)

await expect(sut.execute(1)).rejects.toThrow(ReadError)
})
})