From 5cad35de1eef4697a18f38b11eb68164e3cc6b9d Mon Sep 17 00:00:00 2001 From: Philip Durbin Date: Tue, 9 Sep 2025 16:46:29 -0400 Subject: [PATCH 1/4] feat: new use case for getting dataset types #363 --- docs/useCases.md | 19 +++++++ src/datasets/domain/models/DatasetType.ts | 6 +++ .../repositories/IDatasetsRepository.ts | 2 + .../GetDatasetAvailableDatasetTypes.ts | 20 ++++++++ src/datasets/index.ts | 4 ++ .../infra/repositories/DatasetsRepository.ts | 9 ++++ .../GetDatasetAvailableDatasetTypes.test.ts | 29 +++++++++++ .../GetDatasetAvailableDatasetTypes.test.ts | 49 +++++++++++++++++++ 8 files changed, 138 insertions(+) create mode 100644 src/datasets/domain/models/DatasetType.ts create mode 100644 src/datasets/domain/useCases/GetDatasetAvailableDatasetTypes.ts create mode 100644 test/functional/datasets/GetDatasetAvailableDatasetTypes.test.ts create mode 100644 test/unit/datasets/GetDatasetAvailableDatasetTypes.test.ts diff --git a/docs/useCases.md b/docs/useCases.md index 7fc7b955..fd97b80a 100644 --- a/docs/useCases.md +++ b/docs/useCases.md @@ -38,6 +38,7 @@ The different use cases currently available in the package are classified below, - [Get Dataset Versions Summaries](#get-dataset-versions-summaries) - [Get Dataset Linked Collections](#get-dataset-linked-collections) - [Get Dataset Available Categories](#get-dataset-available-categories) + - [Get Dataset Available Dataset Types](#get-dataset-available-dataset-types) - [Datasets write use cases](#datasets-write-use-cases) - [Create a Dataset](#create-a-dataset) - [Update a Dataset](#update-a-dataset) @@ -1113,6 +1114,24 @@ _See [use case](../src/datasets/domain/useCases/GetDatasetAvailableCategories.ts The `datasetId` parameter is a number for numeric identifiers or string for persistent identifiers. +#### Get Dataset Available Dataset Types + +Returns a list of available dataset types that can be used at dataset creation. By default, only the type "dataset" is returned. + +###### Example call: + +```typescript +import { getDatasetAvailableDatasetTypes } from '@iqss/dataverse-client-javascript' + +/* ... */ + +getDatasetAvailableDatasetTypes.execute().then((categories: String[]) => { + /* ... */ +}) +``` + +_See [use case](../src/datasets/domain/useCases/GetDatasetAvailableDatasetTypes.ts) implementation_. + ## Files ### Files read use cases diff --git a/src/datasets/domain/models/DatasetType.ts b/src/datasets/domain/models/DatasetType.ts new file mode 100644 index 00000000..5475cdaf --- /dev/null +++ b/src/datasets/domain/models/DatasetType.ts @@ -0,0 +1,6 @@ +export interface DatasetType { + id: number + name: string + linkedMetadataBlocks?: string[] + availableLicenses?: string[] +} diff --git a/src/datasets/domain/repositories/IDatasetsRepository.ts b/src/datasets/domain/repositories/IDatasetsRepository.ts index 1b33eb14..76ea2a4e 100644 --- a/src/datasets/domain/repositories/IDatasetsRepository.ts +++ b/src/datasets/domain/repositories/IDatasetsRepository.ts @@ -12,6 +12,7 @@ import { DatasetVersionSummaryInfo } from '../models/DatasetVersionSummaryInfo' import { DatasetLinkedCollection } from '../models/DatasetLinkedCollection' import { CitationFormat } from '../models/CitationFormat' import { FormattedCitation } from '../models/FormattedCitation' +import { DatasetType } from '../models/DatasetType' export interface IDatasetsRepository { getDataset( @@ -74,4 +75,5 @@ export interface IDatasetsRepository { format: CitationFormat, includeDeaccessioned?: boolean ): Promise + getDatasetAvailableDatasetTypes(): Promise } diff --git a/src/datasets/domain/useCases/GetDatasetAvailableDatasetTypes.ts b/src/datasets/domain/useCases/GetDatasetAvailableDatasetTypes.ts new file mode 100644 index 00000000..c7dce4a5 --- /dev/null +++ b/src/datasets/domain/useCases/GetDatasetAvailableDatasetTypes.ts @@ -0,0 +1,20 @@ +import { UseCase } from '../../../core/domain/useCases/UseCase' +import { DatasetType } from '../models/DatasetType' +import { IDatasetsRepository } from '../repositories/IDatasetsRepository' + +export class GetDatasetAvailableDatasetTypes implements UseCase { + private datasetsRepository: IDatasetsRepository + + constructor(datasetsRepository: IDatasetsRepository) { + this.datasetsRepository = datasetsRepository + } + + /** + * Returns the list of available dataset types that can be selected when creating a dataset. + * + * @returns {Promise} + */ + async execute(): Promise { + return await this.datasetsRepository.getDatasetAvailableDatasetTypes() + } +} diff --git a/src/datasets/index.ts b/src/datasets/index.ts index 36b8c6b3..97abcea9 100644 --- a/src/datasets/index.ts +++ b/src/datasets/index.ts @@ -24,6 +24,7 @@ import { LinkDataset } from './domain/useCases/LinkDataset' import { UnlinkDataset } from './domain/useCases/UnlinkDataset' import { GetDatasetLinkedCollections } from './domain/useCases/GetDatasetLinkedCollections' import { GetDatasetAvailableCategories } from './domain/useCases/GetDatasetAvailableCategories' +import { GetDatasetAvailableDatasetTypes } from './domain/useCases/GetDatasetAvailableDatasetTypes' import { GetDatasetCitationInOtherFormats } from './domain/useCases/GetDatasetCitationInOtherFormats' const datasetsRepository = new DatasetsRepository() @@ -63,6 +64,7 @@ const linkDataset = new LinkDataset(datasetsRepository) const unlinkDataset = new UnlinkDataset(datasetsRepository) const getDatasetLinkedCollections = new GetDatasetLinkedCollections(datasetsRepository) const getDatasetAvailableCategories = new GetDatasetAvailableCategories(datasetsRepository) +const getDatasetAvailableDatasetTypes = new GetDatasetAvailableDatasetTypes(datasetsRepository) const getDatasetCitationInOtherFormats = new GetDatasetCitationInOtherFormats(datasetsRepository) export { @@ -86,6 +88,7 @@ export { unlinkDataset, getDatasetLinkedCollections, getDatasetAvailableCategories, + getDatasetAvailableDatasetTypes, getDatasetCitationInOtherFormats } export { DatasetNotNumberedVersion } from './domain/models/DatasetNotNumberedVersion' @@ -121,3 +124,4 @@ export { DatasetVersionSummaryStringValues } from './domain/models/DatasetVersionSummaryInfo' export { DatasetLinkedCollection } from './domain/models/DatasetLinkedCollection' +export { DatasetType } from './domain/models/DatasetType' diff --git a/src/datasets/infra/repositories/DatasetsRepository.ts b/src/datasets/infra/repositories/DatasetsRepository.ts index 2040f763..645d6c51 100644 --- a/src/datasets/infra/repositories/DatasetsRepository.ts +++ b/src/datasets/infra/repositories/DatasetsRepository.ts @@ -24,6 +24,7 @@ import { DatasetLinkedCollection } from '../../domain/models/DatasetLinkedCollec import { CitationFormat } from '../../domain/models/CitationFormat' import { transformDatasetLinkedCollectionsResponseToDatasetLinkedCollection } from './transformers/datasetLinkedCollectionsTransformers' import { FormattedCitation } from '../../domain/models/FormattedCitation' +import { DatasetType } from '../../domain/models/DatasetType' export interface GetAllDatasetPreviewsQueryParams { per_page?: number @@ -357,4 +358,12 @@ export class DatasetsRepository extends ApiRepository implements IDatasetsReposi throw error }) } + + public async getDatasetAvailableDatasetTypes(): Promise { + return this.doGet(this.buildApiEndpoint(this.datasetsResourceName, 'datasetTypes')) + .then((response) => response.data.data) + .catch((error) => { + throw error + }) + } } diff --git a/test/functional/datasets/GetDatasetAvailableDatasetTypes.test.ts b/test/functional/datasets/GetDatasetAvailableDatasetTypes.test.ts new file mode 100644 index 00000000..14a1a2fd --- /dev/null +++ b/test/functional/datasets/GetDatasetAvailableDatasetTypes.test.ts @@ -0,0 +1,29 @@ +import { ApiConfig, DatasetType, getDatasetAvailableDatasetTypes } from '../../../src' +import { DataverseApiAuthMechanism } from '../../../src/core/infra/repositories/ApiConfig' +import { TestConstants } from '../../testHelpers/TestConstants' + +describe('getDatasetAvailableDatasetTypes', () => { + describe('execute', () => { + beforeAll(async () => { + ApiConfig.init( + TestConstants.TEST_API_URL, + DataverseApiAuthMechanism.API_KEY, + process.env.TEST_API_KEY + ) + }) + + test('should return available dataset types', async () => { + const actualDatasetTypes: DatasetType[] = await getDatasetAvailableDatasetTypes.execute() + const expectedDatasetTypes = [ + { + id: 1, + name: 'dataset', + linkedMetadataBlocks: [], + availableLicenses: [] + } + ] + + expect(actualDatasetTypes).toEqual(expectedDatasetTypes) + }) + }) +}) diff --git a/test/unit/datasets/GetDatasetAvailableDatasetTypes.test.ts b/test/unit/datasets/GetDatasetAvailableDatasetTypes.test.ts new file mode 100644 index 00000000..b8768f92 --- /dev/null +++ b/test/unit/datasets/GetDatasetAvailableDatasetTypes.test.ts @@ -0,0 +1,49 @@ +import { ReadError } from '../../../src' +import { DatasetType } from '../../../src' +import { IDatasetsRepository } from '../../../src/datasets/domain/repositories/IDatasetsRepository' +import { GetDatasetAvailableDatasetTypes } from '../../../src/datasets/domain/useCases/GetDatasetAvailableDatasetTypes' + +describe('GetDatasetAvailableDatasetTypes', () => { + describe('execute', () => { + test('should return datasetTypes array on repository success', async () => { + const datasetTypesRepositoryStub: IDatasetsRepository = {} as IDatasetsRepository + + const testDatasetTypes: DatasetType[] = [ + { + id: 1, + name: 'dataset', + linkedMetadataBlocks: [], + availableLicenses: [] + }, + { + id: 2, + name: 'software', + linkedMetadataBlocks: ['codeMeta20'], + availableLicenses: ['MIT', 'Apache-2.0'] + } + ] + + datasetTypesRepositoryStub.getDatasetAvailableDatasetTypes = jest + .fn() + .mockResolvedValue(testDatasetTypes) + const sut = new GetDatasetAvailableDatasetTypes(datasetTypesRepositoryStub) + + const actual = await sut.execute() + + expect(actual).toEqual(testDatasetTypes) + expect(datasetTypesRepositoryStub.getDatasetAvailableDatasetTypes).toHaveBeenCalledTimes(1) + }) + + test('should return error result on repository error', async () => { + const datasetsRepositoryStub: IDatasetsRepository = {} as IDatasetsRepository + const expectedError = new ReadError('Failed to fetch dataset types') + datasetsRepositoryStub.getDatasetAvailableDatasetTypes = jest + .fn() + .mockRejectedValue(expectedError) + const sut = new GetDatasetAvailableDatasetTypes(datasetsRepositoryStub) + + await expect(sut.execute()).rejects.toThrow(ReadError) + expect(datasetsRepositoryStub.getDatasetAvailableDatasetTypes).toHaveBeenCalledTimes(1) + }) + }) +}) From e4f09f955d1a7a06545251d4ec128a13b45be28e Mon Sep 17 00:00:00 2001 From: Philip Durbin Date: Wed, 10 Sep 2025 11:59:21 -0400 Subject: [PATCH 2/4] fix docs (copy/paste error) #363 --- docs/useCases.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/useCases.md b/docs/useCases.md index fd97b80a..e15785cf 100644 --- a/docs/useCases.md +++ b/docs/useCases.md @@ -1125,7 +1125,7 @@ import { getDatasetAvailableDatasetTypes } from '@iqss/dataverse-client-javascri /* ... */ -getDatasetAvailableDatasetTypes.execute().then((categories: String[]) => { +getDatasetAvailableDatasetTypes.execute().then((datasetTypes: DatasetType[]) => { /* ... */ }) ``` From a49c004814003cf3e0dcd7b952712496e75c6359 Mon Sep 17 00:00:00 2001 From: Philip Durbin Date: Wed, 10 Sep 2025 15:28:10 -0400 Subject: [PATCH 3/4] add integration test #363 --- .../datasets/DatasetsRepository.test.ts | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/test/integration/datasets/DatasetsRepository.test.ts b/test/integration/datasets/DatasetsRepository.test.ts index 7962b465..84a85656 100644 --- a/test/integration/datasets/DatasetsRepository.test.ts +++ b/test/integration/datasets/DatasetsRepository.test.ts @@ -20,7 +20,9 @@ import { CreatedDatasetIdentifiers, DatasetDTO, DatasetDeaccessionDTO, - publishDataset + publishDataset, + DatasetType, + getDatasetAvailableDatasetTypes } from '../../../src/datasets' import { ApiConfig, WriteError } from '../../../src' import { DataverseApiAuthMechanism } from '../../../src/core/infra/repositories/ApiConfig' @@ -1649,4 +1651,20 @@ describe('DatasetsRepository', () => { await expect(sut.getDatasetAvailableCategories(nonExistentTestDatasetId)).rejects.toThrow() }) }) + + describe('getDatasetAvailableDatasetTypes', () => { + test('should return available dataset types', async () => { + const actualDatasetTypes: DatasetType[] = await getDatasetAvailableDatasetTypes.execute() + const expectedDatasetTypes = [ + { + id: 1, + name: 'dataset', + linkedMetadataBlocks: [], + availableLicenses: [] + } + ] + + expect(actualDatasetTypes).toEqual(expectedDatasetTypes) + }) + }) }) From aaf41cc689441681fcaabd4707d1060bd88baa05 Mon Sep 17 00:00:00 2001 From: Philip Durbin Date: Wed, 10 Sep 2025 16:15:37 -0400 Subject: [PATCH 4/4] docs: move use case to correct section (read instead of write) #363 --- docs/useCases.md | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/docs/useCases.md b/docs/useCases.md index 6af837b3..db6feccc 100644 --- a/docs/useCases.md +++ b/docs/useCases.md @@ -810,6 +810,24 @@ getDatasetLinkedCollections _See [use case](../src/datasets/domain/useCases/GetDatasetLinkedCollections.ts) implementation_. +#### Get Dataset Available Dataset Types + +Returns a list of available dataset types that can be used at dataset creation. By default, only the type "dataset" is returned. + +###### Example call: + +```typescript +import { getDatasetAvailableDatasetTypes } from '@iqss/dataverse-client-javascript' + +/* ... */ + +getDatasetAvailableDatasetTypes.execute().then((datasetTypes: DatasetType[]) => { + /* ... */ +}) +``` + +_See [use case](../src/datasets/domain/useCases/GetDatasetAvailableDatasetTypes.ts) implementation_. + ### Datasets Write Use Cases #### Create a Dataset @@ -1133,24 +1151,6 @@ getDatasetTemplates.execute(collectionIdOrAlias).then((datasetTemplates: Dataset _See [use case](../src/datasets/domain/useCases/GetDatasetTemplates.ts)_ definition. -#### Get Dataset Available Dataset Types - -Returns a list of available dataset types that can be used at dataset creation. By default, only the type "dataset" is returned. - -###### Example call: - -```typescript -import { getDatasetAvailableDatasetTypes } from '@iqss/dataverse-client-javascript' - -/* ... */ - -getDatasetAvailableDatasetTypes.execute().then((datasetTypes: DatasetType[]) => { - /* ... */ -}) -``` - -_See [use case](../src/datasets/domain/useCases/GetDatasetAvailableDatasetTypes.ts) implementation_. - ## Files ### Files read use cases