From 1da9ccb73749c15cbdafcd4ee21c5bfa400b6b8a Mon Sep 17 00:00:00 2001 From: Cheng Shi Date: Wed, 8 Jul 2026 13:33:42 -0400 Subject: [PATCH 1/4] feat: export metadata use case --- CHANGELOG.md | 1 + docs/useCases.md | 31 +++++++++++++ .../domain/models/ExportedDatasetMetadata.ts | 9 ++++ .../repositories/IDatasetsRepository.ts | 7 +++ .../domain/useCases/ExportDatasetMetadata.ts | 28 +++++++++++ src/datasets/index.ts | 9 +++- .../infra/repositories/DatasetsRepository.ts | 36 +++++++++++++++ .../datasets/DatasetsRepository.test.ts | 40 +++++++++++++++- .../datasets/ExportDatasetMetadata.test.ts | 46 +++++++++++++++++++ 9 files changed, 205 insertions(+), 2 deletions(-) create mode 100644 src/datasets/domain/models/ExportedDatasetMetadata.ts create mode 100644 src/datasets/domain/useCases/ExportDatasetMetadata.ts create mode 100644 test/unit/datasets/ExportDatasetMetadata.test.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e6861af..544261cd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ This changelog follows the principles of [Keep a Changelog](https://keepachangel - Guestbooks: Added optional `includeStats` support to `getGuestbooksByCollectionId`, returning `usageCount` and `responseCount` when requested. - Files: Added `getFileCitationByFormat` use case, repository method, and `FileCitationFormat` enum to support Dataverse file citation exports in `EndNote`, `RIS`, `BibTeX`, `CSL`, and `Internal` formats. - Datasets: Added `getDatasetReviews` use case and repository method to support Dataverse endpoint `GET /datasets/{identifier}/reviews`, for retrieving review datasets associated with a dataset by persistent id or numeric id. +- Datasets: Added `exportDatasetMetadata` use case, repository method, `ExportedDatasetMetadata` response type, and `DatasetMetadataExportVersion` enum to support exporting dataset metadata by numeric id or persistent id through Dataverse endpoint `GET /datasets/export`. - Collections: Added `allowedDatasetTypes` field to the [Collection](./src/collections/domain/models/Collection.ts) model. This field is optional and only populated the feature is enabled on the installation and configured on the collection. - Collections: Added theme information when retrieving a collection using `getCollection`. diff --git a/docs/useCases.md b/docs/useCases.md index 969a6240..87b49f74 100644 --- a/docs/useCases.md +++ b/docs/useCases.md @@ -46,6 +46,8 @@ The different use cases currently available in the package are classified below, - [Get a Dataset](#get-a-dataset) - [Get Dataset By Private URL Token](#get-dataset-by-private-url-token) - [Get Dataset Citation Text](#get-dataset-citation-text) + - [Get Dataset Citation In Other Formats](#get-dataset-citation-in-other-formats) + - [Export Dataset Metadata](#export-dataset-metadata) - [Get Dataset Citation Text By Private URL Token](#get-dataset-citation-text-by-private-url-token) - [Get Dataset Locks](#get-dataset-locks) - [Get Dataset Summary Field Names](#get-dataset-summary-field-names) @@ -1053,6 +1055,35 @@ The `datasetId` parameter can be a string, for persistent identifiers, or a numb There is an optional third parameter called `includeDeaccessioned`, which indicates whether to consider deaccessioned versions or not in the dataset search. If not set, the default value is `false`. +#### Export Dataset Metadata + +Exports dataset metadata in a specified metadata export format. + +##### Example call: + +```typescript +import { + exportDatasetMetadata, + DatasetMetadataExportVersion, + ExportedDatasetMetadata +} from '@iqss/dataverse-client-javascript' + +/* ... */ + +const datasetId = 'doi:10.77777/FK2/AAAAAA' +const exporter = 'ddi' + +exportDatasetMetadata + .execute(datasetId, exporter, DatasetMetadataExportVersion.DRAFT) + .then((metadata: ExportedDatasetMetadata) => { + /* ... */ + }) + +/* ... */ +``` + +_See [use case](../src/datasets/domain/useCases/ExportDatasetMetadata.ts) implementation_. + #### Get Dataset Citation Text By Private URL Token Returns the Dataset citation text, given an associated Private URL Token. diff --git a/src/datasets/domain/models/ExportedDatasetMetadata.ts b/src/datasets/domain/models/ExportedDatasetMetadata.ts new file mode 100644 index 00000000..a78a964a --- /dev/null +++ b/src/datasets/domain/models/ExportedDatasetMetadata.ts @@ -0,0 +1,9 @@ +export type ExportedDatasetMetadata = { + content: string + contentType: string +} + +export enum DatasetMetadataExportVersion { + LATEST_PUBLISHED = ':latest-published', + DRAFT = ':draft' +} diff --git a/src/datasets/domain/repositories/IDatasetsRepository.ts b/src/datasets/domain/repositories/IDatasetsRepository.ts index b3a20d73..aeb37960 100644 --- a/src/datasets/domain/repositories/IDatasetsRepository.ts +++ b/src/datasets/domain/repositories/IDatasetsRepository.ts @@ -19,6 +19,8 @@ import { DatasetTypeDTO } from '../dtos/DatasetTypeDTO' import { StorageDriver } from '../../../core/domain/models/StorageDriver' import { DatasetUploadLimits } from '../models/DatasetUploadLimits' import { DatasetReview } from '../models/DatasetReview' +import { ExportedDatasetMetadata } from '../models/ExportedDatasetMetadata' +import { DatasetMetadataExportVersion } from '../models/ExportedDatasetMetadata' export interface IDatasetsRepository { getDataset( @@ -86,6 +88,11 @@ export interface IDatasetsRepository { format: CitationFormat, includeDeaccessioned?: boolean ): Promise + exportDatasetMetadata( + datasetId: number | string, + exporter: string, + version?: DatasetMetadataExportVersion + ): Promise getDatasetAvailableDatasetTypes(): Promise getDatasetAvailableDatasetType(datasetTypeId: number | string): Promise addDatasetType(datasetType: DatasetTypeDTO): Promise diff --git a/src/datasets/domain/useCases/ExportDatasetMetadata.ts b/src/datasets/domain/useCases/ExportDatasetMetadata.ts new file mode 100644 index 00000000..946dd062 --- /dev/null +++ b/src/datasets/domain/useCases/ExportDatasetMetadata.ts @@ -0,0 +1,28 @@ +import { UseCase } from '../../../core/domain/useCases/UseCase' +import { DatasetMetadataExportVersion } from '../models/ExportedDatasetMetadata' +import { ExportedDatasetMetadata } from '../models/ExportedDatasetMetadata' +import { IDatasetsRepository } from '../repositories/IDatasetsRepository' + +export class ExportDatasetMetadata implements UseCase { + private datasetsRepository: IDatasetsRepository + + constructor(datasetsRepository: IDatasetsRepository) { + this.datasetsRepository = datasetsRepository + } + + /** + * Exports dataset metadata in the specified metadata export format. + * + * @param {number | string} datasetId - The dataset identifier, which can be a string for persistent identifiers or a number for numeric identifiers. + * @param {string} exporter - The metadata exporter format name. + * @param {DatasetMetadataExportVersion} [version] - The dataset version to export. If omitted, Dataverse defaults to :latest-published. + * @returns {Promise} The exported metadata content and content type. + */ + async execute( + datasetId: number | string, + exporter: string, + version?: DatasetMetadataExportVersion + ): Promise { + return await this.datasetsRepository.exportDatasetMetadata(datasetId, exporter, version) + } +} diff --git a/src/datasets/index.ts b/src/datasets/index.ts index 37d09bc1..0b598f8b 100644 --- a/src/datasets/index.ts +++ b/src/datasets/index.ts @@ -36,6 +36,7 @@ import { UpdateDatasetLicense } from './domain/useCases/UpdateDatasetLicense' import { GetDatasetStorageDriver } from './domain/useCases/GetDatasetStorageDriver' import { GetDatasetUploadLimits } from './domain/useCases/GetDatasetUploadLimits' import { GetDatasetReviews } from './domain/useCases/GetDatasetReviews' +import { ExportDatasetMetadata } from './domain/useCases/ExportDatasetMetadata' const datasetsRepository = new DatasetsRepository() @@ -88,6 +89,7 @@ const updateDatasetLicense = new UpdateDatasetLicense(datasetsRepository) const getDatasetStorageDriver = new GetDatasetStorageDriver(datasetsRepository) const getDatasetUploadLimits = new GetDatasetUploadLimits(datasetsRepository) const getDatasetReviews = new GetDatasetReviews(datasetsRepository) +const exportDatasetMetadata = new ExportDatasetMetadata(datasetsRepository) export { getDataset, @@ -121,9 +123,14 @@ export { updateDatasetLicense, getDatasetStorageDriver, getDatasetUploadLimits, - getDatasetReviews + getDatasetReviews, + exportDatasetMetadata } export { DatasetNotNumberedVersion } from './domain/models/DatasetNotNumberedVersion' +export { + DatasetMetadataExportVersion, + ExportedDatasetMetadata +} from './domain/models/ExportedDatasetMetadata' export { DatasetUserPermissions } from './domain/models/DatasetUserPermissions' export { DatasetLock, DatasetLockType } from './domain/models/DatasetLock' export { diff --git a/src/datasets/infra/repositories/DatasetsRepository.ts b/src/datasets/infra/repositories/DatasetsRepository.ts index e004aa8d..118c8edf 100644 --- a/src/datasets/infra/repositories/DatasetsRepository.ts +++ b/src/datasets/infra/repositories/DatasetsRepository.ts @@ -26,6 +26,7 @@ import { transformDatasetLinkedCollectionsResponseToDatasetLinkedCollection } fr import { FormattedCitation } from '../../domain/models/FormattedCitation' import { DatasetType } from '../../domain/models/DatasetType' import { TermsOfAccess } from '../../domain/models/Dataset' +import { DatasetNotNumberedVersion } from '../../domain/models/DatasetNotNumberedVersion' import { transformTermsOfAccessToUpdatePayload } from './transformers/termsOfAccessTransformers' import { DatasetLicenseUpdateRequest } from '../../domain/dtos/DatasetLicenseUpdateRequest' import { DatasetTypeDTO } from '../../domain/dtos/DatasetTypeDTO' @@ -33,6 +34,8 @@ import { StorageDriver } from '../../../core/domain/models/StorageDriver' import { DatasetUploadLimits } from '../../domain/models/DatasetUploadLimits' import { DatasetReview } from '../../domain/models/DatasetReview' import { transformDatasetReviewsResponseToDatasetReviews } from './transformers/datasetReviewTransformers' +import { ExportedDatasetMetadata } from '../../domain/models/ExportedDatasetMetadata' +import { DatasetMetadataExportVersion } from '../../domain/models/ExportedDatasetMetadata' export interface GetAllDatasetPreviewsQueryParams { per_page?: number @@ -133,6 +136,39 @@ export class DatasetsRepository extends ApiRepository implements IDatasetsReposi } } + public async exportDatasetMetadata( + datasetId: number | string, + exporter: string, + version?: DatasetMetadataExportVersion + ): Promise { + const persistentId = + typeof datasetId === 'number' + ? ( + await this.getDataset( + datasetId, + version ?? DatasetNotNumberedVersion.LATEST_PUBLISHED, + false, + false + ) + ).persistentId + : datasetId + + const response = await this.doGet('/datasets/export', true, { + exporter, + persistentId, + ...(version && { version }) + }) + + const contentType = response.headers['content-type'] + const content = + typeof response.data === 'string' ? response.data : JSON.stringify(response.data) + + return { + content, + contentType + } + } + public async getPrivateUrlDatasetCitation(token: string): Promise { return this.doGet( this.buildApiEndpoint(this.datasetsResourceName, `privateUrlDatasetVersion/${token}/citation`) diff --git a/test/integration/datasets/DatasetsRepository.test.ts b/test/integration/datasets/DatasetsRepository.test.ts index 3edf2315..79d6a66b 100644 --- a/test/integration/datasets/DatasetsRepository.test.ts +++ b/test/integration/datasets/DatasetsRepository.test.ts @@ -35,7 +35,8 @@ import { updateTermsOfAccess, DatasetLicenseUpdateRequest, getDatasetReviews, - DatasetReview + DatasetReview, + DatasetMetadataExportVersion } from '../../../src/datasets' import { ApiConfig, WriteError } from '../../../src' import { DataverseApiAuthMechanism } from '../../../src/core/infra/repositories/ApiConfig' @@ -772,6 +773,43 @@ describe('DatasetsRepository', () => { }) }) + describe('exportDatasetMetadata', () => { + let draftDatasetIds: CreatedDatasetIdentifiers + let publishedDatasetIds: CreatedDatasetIdentifiers + + beforeAll(async () => { + draftDatasetIds = await createDataset.execute(TestConstants.TEST_NEW_DATASET_DTO) + publishedDatasetIds = await createDataset.execute(TestConstants.TEST_NEW_DATASET_DTO) + await publishDatasetViaApi(publishedDatasetIds.numericId) + await waitForNoLocks(publishedDatasetIds.numericId, 10) + }) + + afterAll(async () => { + await deleteUnpublishedDatasetViaApi(draftDatasetIds.numericId) + await deletePublishedDatasetViaApi(publishedDatasetIds.persistentId) + }) + + test('should export latest published dataset metadata in DDI format by default', async () => { + const metadata = await sut.exportDatasetMetadata(publishedDatasetIds.persistentId, 'ddi') + + expect(typeof metadata.content).toBe('string') + expect(metadata.content.length).toBeGreaterThan(0) + expect(metadata.contentType).toMatch(/xml/) + }) + + test('should export draft dataset metadata in DDI format', async () => { + const metadata = await sut.exportDatasetMetadata( + draftDatasetIds.numericId, + 'ddi', + DatasetMetadataExportVersion.DRAFT + ) + + expect(typeof metadata.content).toBe('string') + expect(metadata.content.length).toBeGreaterThan(0) + expect(metadata.contentType).toMatch(/xml/) + }) + }) + describe('getDatasetVersionDiff', () => { let testDatasetIds: CreatedDatasetIdentifiers diff --git a/test/unit/datasets/ExportDatasetMetadata.test.ts b/test/unit/datasets/ExportDatasetMetadata.test.ts new file mode 100644 index 00000000..cc663784 --- /dev/null +++ b/test/unit/datasets/ExportDatasetMetadata.test.ts @@ -0,0 +1,46 @@ +import { ExportDatasetMetadata } from '../../../src/datasets/domain/useCases/ExportDatasetMetadata' +import { IDatasetsRepository } from '../../../src/datasets/domain/repositories/IDatasetsRepository' +import { ReadError } from '../../../src/core/domain/repositories/ReadError' +import { ExportedDatasetMetadata } from '../../../src/datasets/domain/models/ExportedDatasetMetadata' +import { DatasetMetadataExportVersion } from '../../../src/datasets/domain/models/ExportedDatasetMetadata' + +describe('ExportDatasetMetadata.execute', () => { + const testDatasetId = 1 + const testExporter = 'ddi' + + test('should return exported dataset metadata on repository success', async () => { + const expectedMetadata: ExportedDatasetMetadata = { + content: '', + contentType: 'application/xml' + } + + const datasetsRepositoryStub: IDatasetsRepository = { + exportDatasetMetadata: jest.fn().mockResolvedValue(expectedMetadata) + } as unknown as IDatasetsRepository + + const sut = new ExportDatasetMetadata(datasetsRepositoryStub) + + const actual = await sut.execute( + testDatasetId, + testExporter, + DatasetMetadataExportVersion.DRAFT + ) + + expect(actual).toEqual(expectedMetadata) + expect(datasetsRepositoryStub.exportDatasetMetadata).toHaveBeenCalledWith( + testDatasetId, + testExporter, + DatasetMetadataExportVersion.DRAFT + ) + }) + + test('should throw ReadError on repository failure', async () => { + const datasetsRepositoryStub: IDatasetsRepository = { + exportDatasetMetadata: jest.fn().mockRejectedValue(new ReadError()) + } as unknown as IDatasetsRepository + + const sut = new ExportDatasetMetadata(datasetsRepositoryStub) + + await expect(sut.execute(testDatasetId, testExporter)).rejects.toThrow(ReadError) + }) +}) From 15a8e31531c8df10ffb7f8aeb0c22174db965a8b Mon Sep 17 00:00:00 2001 From: Cheng Shi Date: Wed, 8 Jul 2026 17:16:02 -0400 Subject: [PATCH 2/4] fix: unlink test error --- .../collections/CollectionsRepository.test.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/test/integration/collections/CollectionsRepository.test.ts b/test/integration/collections/CollectionsRepository.test.ts index 2f563403..72a46165 100644 --- a/test/integration/collections/CollectionsRepository.test.ts +++ b/test/integration/collections/CollectionsRepository.test.ts @@ -2143,12 +2143,16 @@ describe('CollectionsRepository', () => { const firstCollection = await sut.getCollection(firstCollectionAlias) const secondCollection = await sut.getCollection(secondCollectionAlias) + const collectionLinksBefore = await sut.getCollectionLinks(firstCollection.id) + expect( + collectionLinksBefore.linkedCollections.map((collection) => collection.alias) + ).toContain(secondCollection.alias) + await sut.unlinkCollection(secondCollection.id, firstCollection.id) - await new Promise((res) => setTimeout(res, 2000)) await sut.getCollection(secondCollectionAlias) - const collectionItemSubset = await sut.getCollectionItems(firstCollection.alias) - expect(collectionItemSubset.items).toStrictEqual([]) + const collectionLinksAfter = await sut.getCollectionLinks(firstCollection.id) + expect(collectionLinksAfter.linkedCollections).toStrictEqual([]) }) test('should throw error when unlinking a non-existent collection', async () => { From 03f62808d9f7944ec986bdfcb26bf5c740411ab7 Mon Sep 17 00:00:00 2001 From: Cheng Shi Date: Wed, 8 Jul 2026 17:29:29 -0400 Subject: [PATCH 3/4] fix: update version param --- CHANGELOG.md | 2 +- docs/useCases.md | 6 ++++-- src/datasets/domain/models/ExportedDatasetMetadata.ts | 5 ----- .../domain/repositories/IDatasetsRepository.ts | 4 ++-- src/datasets/domain/useCases/ExportDatasetMetadata.ts | 6 +++--- src/datasets/index.ts | 5 +---- src/datasets/infra/repositories/DatasetsRepository.ts | 3 +-- test/functional/collections/UnlinkCollection.test.ts | 11 +++++++---- test/integration/datasets/DatasetsRepository.test.ts | 5 ++--- test/unit/datasets/ExportDatasetMetadata.test.ts | 10 +++------- 10 files changed, 24 insertions(+), 33 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 544261cd..ad4a912c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,7 +14,7 @@ This changelog follows the principles of [Keep a Changelog](https://keepachangel - Guestbooks: Added optional `includeStats` support to `getGuestbooksByCollectionId`, returning `usageCount` and `responseCount` when requested. - Files: Added `getFileCitationByFormat` use case, repository method, and `FileCitationFormat` enum to support Dataverse file citation exports in `EndNote`, `RIS`, `BibTeX`, `CSL`, and `Internal` formats. - Datasets: Added `getDatasetReviews` use case and repository method to support Dataverse endpoint `GET /datasets/{identifier}/reviews`, for retrieving review datasets associated with a dataset by persistent id or numeric id. -- Datasets: Added `exportDatasetMetadata` use case, repository method, `ExportedDatasetMetadata` response type, and `DatasetMetadataExportVersion` enum to support exporting dataset metadata by numeric id or persistent id through Dataverse endpoint `GET /datasets/export`. +- Datasets: Added `exportDatasetMetadata` use case, repository method, and `ExportedDatasetMetadata` response type to support exporting dataset metadata by numeric id or persistent id through Dataverse endpoint `GET /datasets/export`. - Collections: Added `allowedDatasetTypes` field to the [Collection](./src/collections/domain/models/Collection.ts) model. This field is optional and only populated the feature is enabled on the installation and configured on the collection. - Collections: Added theme information when retrieving a collection using `getCollection`. diff --git a/docs/useCases.md b/docs/useCases.md index 87b49f74..2df0b987 100644 --- a/docs/useCases.md +++ b/docs/useCases.md @@ -1064,7 +1064,7 @@ Exports dataset metadata in a specified metadata export format. ```typescript import { exportDatasetMetadata, - DatasetMetadataExportVersion, + DatasetNotNumberedVersion, ExportedDatasetMetadata } from '@iqss/dataverse-client-javascript' @@ -1074,7 +1074,7 @@ const datasetId = 'doi:10.77777/FK2/AAAAAA' const exporter = 'ddi' exportDatasetMetadata - .execute(datasetId, exporter, DatasetMetadataExportVersion.DRAFT) + .execute(datasetId, exporter, DatasetNotNumberedVersion.DRAFT) .then((metadata: ExportedDatasetMetadata) => { /* ... */ }) @@ -1084,6 +1084,8 @@ exportDatasetMetadata _See [use case](../src/datasets/domain/useCases/ExportDatasetMetadata.ts) implementation_. +The `datasetId` parameter can be a string for persistent identifiers or a number for numeric identifiers. The optional `version` parameter accepts `DatasetNotNumberedVersion.LATEST_PUBLISHED` or `DatasetNotNumberedVersion.DRAFT`. If not set, Dataverse defaults to `DatasetNotNumberedVersion.LATEST_PUBLISHED`. Draft exports require configured authentication with access to the draft. + #### Get Dataset Citation Text By Private URL Token Returns the Dataset citation text, given an associated Private URL Token. diff --git a/src/datasets/domain/models/ExportedDatasetMetadata.ts b/src/datasets/domain/models/ExportedDatasetMetadata.ts index a78a964a..e6d259e7 100644 --- a/src/datasets/domain/models/ExportedDatasetMetadata.ts +++ b/src/datasets/domain/models/ExportedDatasetMetadata.ts @@ -2,8 +2,3 @@ export type ExportedDatasetMetadata = { content: string contentType: string } - -export enum DatasetMetadataExportVersion { - LATEST_PUBLISHED = ':latest-published', - DRAFT = ':draft' -} diff --git a/src/datasets/domain/repositories/IDatasetsRepository.ts b/src/datasets/domain/repositories/IDatasetsRepository.ts index aeb37960..a50ad2ff 100644 --- a/src/datasets/domain/repositories/IDatasetsRepository.ts +++ b/src/datasets/domain/repositories/IDatasetsRepository.ts @@ -20,7 +20,7 @@ import { StorageDriver } from '../../../core/domain/models/StorageDriver' import { DatasetUploadLimits } from '../models/DatasetUploadLimits' import { DatasetReview } from '../models/DatasetReview' import { ExportedDatasetMetadata } from '../models/ExportedDatasetMetadata' -import { DatasetMetadataExportVersion } from '../models/ExportedDatasetMetadata' +import { DatasetNotNumberedVersion } from '../models/DatasetNotNumberedVersion' export interface IDatasetsRepository { getDataset( @@ -91,7 +91,7 @@ export interface IDatasetsRepository { exportDatasetMetadata( datasetId: number | string, exporter: string, - version?: DatasetMetadataExportVersion + version?: DatasetNotNumberedVersion.LATEST_PUBLISHED | DatasetNotNumberedVersion.DRAFT ): Promise getDatasetAvailableDatasetTypes(): Promise getDatasetAvailableDatasetType(datasetTypeId: number | string): Promise diff --git a/src/datasets/domain/useCases/ExportDatasetMetadata.ts b/src/datasets/domain/useCases/ExportDatasetMetadata.ts index 946dd062..15fd8b02 100644 --- a/src/datasets/domain/useCases/ExportDatasetMetadata.ts +++ b/src/datasets/domain/useCases/ExportDatasetMetadata.ts @@ -1,5 +1,5 @@ import { UseCase } from '../../../core/domain/useCases/UseCase' -import { DatasetMetadataExportVersion } from '../models/ExportedDatasetMetadata' +import { DatasetNotNumberedVersion } from '../models/DatasetNotNumberedVersion' import { ExportedDatasetMetadata } from '../models/ExportedDatasetMetadata' import { IDatasetsRepository } from '../repositories/IDatasetsRepository' @@ -15,13 +15,13 @@ export class ExportDatasetMetadata implements UseCase { * * @param {number | string} datasetId - The dataset identifier, which can be a string for persistent identifiers or a number for numeric identifiers. * @param {string} exporter - The metadata exporter format name. - * @param {DatasetMetadataExportVersion} [version] - The dataset version to export. If omitted, Dataverse defaults to :latest-published. + * @param {DatasetNotNumberedVersion.LATEST_PUBLISHED | DatasetNotNumberedVersion.DRAFT} [version] - The dataset version to export. If omitted, Dataverse defaults to :latest-published. * @returns {Promise} The exported metadata content and content type. */ async execute( datasetId: number | string, exporter: string, - version?: DatasetMetadataExportVersion + version?: DatasetNotNumberedVersion.LATEST_PUBLISHED | DatasetNotNumberedVersion.DRAFT ): Promise { return await this.datasetsRepository.exportDatasetMetadata(datasetId, exporter, version) } diff --git a/src/datasets/index.ts b/src/datasets/index.ts index 0b598f8b..de7a32b4 100644 --- a/src/datasets/index.ts +++ b/src/datasets/index.ts @@ -127,10 +127,7 @@ export { exportDatasetMetadata } export { DatasetNotNumberedVersion } from './domain/models/DatasetNotNumberedVersion' -export { - DatasetMetadataExportVersion, - ExportedDatasetMetadata -} from './domain/models/ExportedDatasetMetadata' +export { ExportedDatasetMetadata } from './domain/models/ExportedDatasetMetadata' export { DatasetUserPermissions } from './domain/models/DatasetUserPermissions' export { DatasetLock, DatasetLockType } from './domain/models/DatasetLock' export { diff --git a/src/datasets/infra/repositories/DatasetsRepository.ts b/src/datasets/infra/repositories/DatasetsRepository.ts index 118c8edf..7c6b720c 100644 --- a/src/datasets/infra/repositories/DatasetsRepository.ts +++ b/src/datasets/infra/repositories/DatasetsRepository.ts @@ -35,7 +35,6 @@ import { DatasetUploadLimits } from '../../domain/models/DatasetUploadLimits' import { DatasetReview } from '../../domain/models/DatasetReview' import { transformDatasetReviewsResponseToDatasetReviews } from './transformers/datasetReviewTransformers' import { ExportedDatasetMetadata } from '../../domain/models/ExportedDatasetMetadata' -import { DatasetMetadataExportVersion } from '../../domain/models/ExportedDatasetMetadata' export interface GetAllDatasetPreviewsQueryParams { per_page?: number @@ -139,7 +138,7 @@ export class DatasetsRepository extends ApiRepository implements IDatasetsReposi public async exportDatasetMetadata( datasetId: number | string, exporter: string, - version?: DatasetMetadataExportVersion + version?: DatasetNotNumberedVersion.LATEST_PUBLISHED | DatasetNotNumberedVersion.DRAFT ): Promise { const persistentId = typeof datasetId === 'number' diff --git a/test/functional/collections/UnlinkCollection.test.ts b/test/functional/collections/UnlinkCollection.test.ts index 0b20b455..badf54ce 100644 --- a/test/functional/collections/UnlinkCollection.test.ts +++ b/test/functional/collections/UnlinkCollection.test.ts @@ -5,6 +5,7 @@ import { linkCollection, deleteCollection, getCollectionItems, + getCollectionLinks, unlinkCollection } from '../../../src' import { TestConstants } from '../../testHelpers/TestConstants' @@ -43,12 +44,14 @@ describe('execute', () => { // Verify that the collections are linked const collectionItemSubset = await getCollectionItems.execute(firstCollectionAlias) expect(collectionItemSubset.items.length).toBe(1) + const collectionLinksBefore = await getCollectionLinks.execute(firstCollectionId) + expect(collectionLinksBefore.linkedCollections.map((collection) => collection.alias)).toContain( + secondCollectionAlias + ) await unlinkCollection.execute(secondCollectionAlias, firstCollectionAlias) - // Wait for the unlinking to be processed by Solr - await new Promise((resolve) => setTimeout(resolve, 5000)) - const collectionItemSubset2 = await getCollectionItems.execute(firstCollectionAlias) - expect(collectionItemSubset2.items.length).toBe(0) + const collectionLinksAfter = await getCollectionLinks.execute(firstCollectionId) + expect(collectionLinksAfter.linkedCollections).toStrictEqual([]) }) test('should throw an error when unlinking a non-existent collection', async () => { diff --git a/test/integration/datasets/DatasetsRepository.test.ts b/test/integration/datasets/DatasetsRepository.test.ts index 79d6a66b..6a67299e 100644 --- a/test/integration/datasets/DatasetsRepository.test.ts +++ b/test/integration/datasets/DatasetsRepository.test.ts @@ -35,8 +35,7 @@ import { updateTermsOfAccess, DatasetLicenseUpdateRequest, getDatasetReviews, - DatasetReview, - DatasetMetadataExportVersion + DatasetReview } from '../../../src/datasets' import { ApiConfig, WriteError } from '../../../src' import { DataverseApiAuthMechanism } from '../../../src/core/infra/repositories/ApiConfig' @@ -801,7 +800,7 @@ describe('DatasetsRepository', () => { const metadata = await sut.exportDatasetMetadata( draftDatasetIds.numericId, 'ddi', - DatasetMetadataExportVersion.DRAFT + DatasetNotNumberedVersion.DRAFT ) expect(typeof metadata.content).toBe('string') diff --git a/test/unit/datasets/ExportDatasetMetadata.test.ts b/test/unit/datasets/ExportDatasetMetadata.test.ts index cc663784..6791859f 100644 --- a/test/unit/datasets/ExportDatasetMetadata.test.ts +++ b/test/unit/datasets/ExportDatasetMetadata.test.ts @@ -2,7 +2,7 @@ import { ExportDatasetMetadata } from '../../../src/datasets/domain/useCases/Exp import { IDatasetsRepository } from '../../../src/datasets/domain/repositories/IDatasetsRepository' import { ReadError } from '../../../src/core/domain/repositories/ReadError' import { ExportedDatasetMetadata } from '../../../src/datasets/domain/models/ExportedDatasetMetadata' -import { DatasetMetadataExportVersion } from '../../../src/datasets/domain/models/ExportedDatasetMetadata' +import { DatasetNotNumberedVersion } from '../../../src/datasets/domain/models/DatasetNotNumberedVersion' describe('ExportDatasetMetadata.execute', () => { const testDatasetId = 1 @@ -20,17 +20,13 @@ describe('ExportDatasetMetadata.execute', () => { const sut = new ExportDatasetMetadata(datasetsRepositoryStub) - const actual = await sut.execute( - testDatasetId, - testExporter, - DatasetMetadataExportVersion.DRAFT - ) + const actual = await sut.execute(testDatasetId, testExporter, DatasetNotNumberedVersion.DRAFT) expect(actual).toEqual(expectedMetadata) expect(datasetsRepositoryStub.exportDatasetMetadata).toHaveBeenCalledWith( testDatasetId, testExporter, - DatasetMetadataExportVersion.DRAFT + DatasetNotNumberedVersion.DRAFT ) }) From 799c2e18b815d65d7033705252186fc4b66814e4 Mon Sep 17 00:00:00 2001 From: Cheng Shi <91049239+ChengShi-1@users.noreply.github.com> Date: Thu, 9 Jul 2026 08:35:27 -0400 Subject: [PATCH 4/4] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- src/datasets/infra/repositories/DatasetsRepository.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/datasets/infra/repositories/DatasetsRepository.ts b/src/datasets/infra/repositories/DatasetsRepository.ts index 7c6b720c..1eba3fa4 100644 --- a/src/datasets/infra/repositories/DatasetsRepository.ts +++ b/src/datasets/infra/repositories/DatasetsRepository.ts @@ -158,7 +158,7 @@ export class DatasetsRepository extends ApiRepository implements IDatasetsReposi ...(version && { version }) }) - const contentType = response.headers['content-type'] + const contentType = String(response.headers['content-type'] ?? '') const content = typeof response.data === 'string' ? response.data : JSON.stringify(response.data)