Skip to content

Commit 38d68b7

Browse files
authored
Merge pull request #205 from IQSS/feat/203-extra-param-html-to-markdown
Add extra parameter to transform or not html to markdown
2 parents 1913993 + f907dbb commit 38d68b7

File tree

11 files changed

+211
-45
lines changed

11 files changed

+211
-45
lines changed

docs/useCases.md

+4
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,8 @@ The optional `datasetVersionId` parameter can correspond to a numeric version id
287287

288288
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`.
289289

290+
There is an optional fourth parameter called `keepRawFields`, which indicates whether or not to keep the metadata fields as they are and avoid the transformation to Markdown. The default value is `false`.
291+
290292
#### Get Dataset By Private URL Token
291293

292294
Returns a [Dataset](../src/datasets/domain/models/Dataset.ts) instance, given an associated Private URL Token.
@@ -307,6 +309,8 @@ getPrivateUrlDataset.execute(token).then((dataset: Dataset) => {
307309

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

312+
There is an optional second parameter called `keepRawFields`, which indicates whether or not to keep the metadata fields as they are and avoid the transformation to Markdown. The default value is `false`.
313+
310314
#### Get Dataset Citation Text
311315

312316
Returns the Dataset citation text.

src/datasets/domain/repositories/IDatasetsRepository.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,16 @@ export interface IDatasetsRepository {
1010
getDataset(
1111
datasetId: number | string,
1212
datasetVersionId: string,
13-
includeDeaccessioned: boolean
13+
includeDeaccessioned: boolean,
14+
keepRawFields: boolean
1415
): Promise<Dataset>
1516
getDatasetLocks(datasetId: number | string): Promise<DatasetLock[]>
1617
getDatasetCitation(
1718
datasetId: number,
1819
datasetVersionId: string,
1920
includeDeaccessioned: boolean
2021
): Promise<string>
21-
getPrivateUrlDataset(token: string): Promise<Dataset>
22+
getPrivateUrlDataset(token: string, keepRawFields: boolean): Promise<Dataset>
2223
getAllDatasetPreviews(
2324
limit?: number,
2425
offset?: number,

src/datasets/domain/useCases/GetDataset.ts

+5-2
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,20 @@ export class GetDataset implements UseCase<Dataset> {
1616
* @param {number | string} [datasetId] - The dataset identifier, which can be a string (for persistent identifiers), or a number (for numeric identifiers).
1717
* @param {string | DatasetNotNumberedVersion} [datasetVersionId=DatasetNotNumberedVersion.LATEST] - The dataset version identifier, which can be a version-specific numeric string (for example, 1.0) or a DatasetNotNumberedVersion enum value. If this parameter is not set, the default value is: DatasetNotNumberedVersion.LATEST
1818
* @param {boolean} [includeDeaccessioned=false] - Indicates whether to consider deaccessioned versions in the dataset search or not. The default value is false
19+
* @param {boolean} [keepRawFields=false] - Indicates whether or not the use case should keep the metadata fields as they are and avoid the transformation to markdown. The default value is false.
1920
* @returns {Promise<Dataset>}
2021
*/
2122
async execute(
2223
datasetId: number | string,
2324
datasetVersionId: string | DatasetNotNumberedVersion = DatasetNotNumberedVersion.LATEST,
24-
includeDeaccessioned = false
25+
includeDeaccessioned = false,
26+
keepRawFields = false
2527
): Promise<Dataset> {
2628
return await this.datasetsRepository.getDataset(
2729
datasetId,
2830
datasetVersionId,
29-
includeDeaccessioned
31+
includeDeaccessioned,
32+
keepRawFields
3033
)
3134
}
3235
}

src/datasets/domain/useCases/GetPrivateUrlDataset.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,10 @@ export class GetPrivateUrlDataset implements UseCase<Dataset> {
1313
* Returns a Dataset instance, given an associated Private URL Token.
1414
*
1515
* @param {string} [token] - A Private URL token.
16+
* @param {boolean} [keepRawFields=false] - Indicates whether or not the use case should keep the metadata fields as they are and avoid the transformation to markdown. The default value is false.
1617
* @returns {Promise<Dataset>}
1718
*/
18-
async execute(token: string): Promise<Dataset> {
19-
return await this.datasetsRepository.getPrivateUrlDataset(token)
19+
async execute(token: string, keepRawFields = false): Promise<Dataset> {
20+
return await this.datasetsRepository.getPrivateUrlDataset(token, keepRawFields)
2021
}
2122
}

src/datasets/infra/repositories/DatasetsRepository.ts

+5-4
Original file line numberDiff line numberDiff line change
@@ -33,15 +33,15 @@ export class DatasetsRepository extends ApiRepository implements IDatasetsReposi
3333
})
3434
}
3535

36-
public async getPrivateUrlDataset(token: string): Promise<Dataset> {
36+
public async getPrivateUrlDataset(token: string, keepRawFields: boolean): Promise<Dataset> {
3737
return this.doGet(
3838
this.buildApiEndpoint(this.datasetsResourceName, `privateUrlDatasetVersion/${token}`),
3939
false,
4040
{
4141
returnOwners: true
4242
}
4343
)
44-
.then((response) => transformVersionResponseToDataset(response))
44+
.then((response) => transformVersionResponseToDataset(response, keepRawFields))
4545
.catch((error) => {
4646
throw error
4747
})
@@ -50,7 +50,8 @@ export class DatasetsRepository extends ApiRepository implements IDatasetsReposi
5050
public async getDataset(
5151
datasetId: number | string,
5252
datasetVersionId: string,
53-
includeDeaccessioned: boolean
53+
includeDeaccessioned: boolean,
54+
keepRawFields: boolean
5455
): Promise<Dataset> {
5556
return this.doGet(
5657
this.buildApiEndpoint(this.datasetsResourceName, `versions/${datasetVersionId}`, datasetId),
@@ -61,7 +62,7 @@ export class DatasetsRepository extends ApiRepository implements IDatasetsReposi
6162
returnOwners: true
6263
}
6364
)
64-
.then((response) => transformVersionResponseToDataset(response))
65+
.then((response) => transformVersionResponseToDataset(response, keepRawFields))
6566
.catch((error) => {
6667
throw error
6768
})

src/datasets/infra/repositories/transformers/datasetTransformers.ts

+34-13
Original file line numberDiff line numberDiff line change
@@ -209,12 +209,18 @@ export const transformMetadataChildFieldValueToRequestPayload = (
209209
return metadataChildFieldRequestPayload
210210
}
211211

212-
export const transformVersionResponseToDataset = (response: AxiosResponse): Dataset => {
212+
export const transformVersionResponseToDataset = (
213+
response: AxiosResponse,
214+
keepRawFields: boolean
215+
): Dataset => {
213216
const versionPayload = response.data.data
214-
return transformVersionPayloadToDataset(versionPayload)
217+
return transformVersionPayloadToDataset(versionPayload, keepRawFields)
215218
}
216219

217-
export const transformVersionPayloadToDataset = (versionPayload: DatasetPayload): Dataset => {
220+
export const transformVersionPayloadToDataset = (
221+
versionPayload: DatasetPayload,
222+
keepRawFields: boolean
223+
): Dataset => {
218224
const datasetModel: Dataset = {
219225
id: versionPayload.datasetId,
220226
versionId: versionPayload.id,
@@ -227,7 +233,10 @@ export const transformVersionPayloadToDataset = (versionPayload: DatasetPayload)
227233
lastUpdateTime: new Date(versionPayload.lastUpdateTime),
228234
releaseTime: new Date(versionPayload.releaseTime)
229235
},
230-
metadataBlocks: transformPayloadToDatasetMetadataBlocks(versionPayload.metadataBlocks),
236+
metadataBlocks: transformPayloadToDatasetMetadataBlocks(
237+
versionPayload.metadataBlocks,
238+
keepRawFields
239+
),
231240
...(versionPayload.isPartOf && {
232241
isPartOf: transformPayloadToOwnerNode(versionPayload.isPartOf)
233242
})
@@ -260,25 +269,28 @@ const transformPayloadToDatasetLicense = (licensePayload: LicensePayload): Datas
260269
}
261270

262271
const transformPayloadToDatasetMetadataBlocks = (
263-
metadataBlocksPayload: MetadataBlocksPayload
272+
metadataBlocksPayload: MetadataBlocksPayload,
273+
keepRawFields: boolean
264274
): DatasetMetadataBlocks => {
265275
return Object.keys(metadataBlocksPayload).map((metadataBlockKey) => {
266276
const metadataBlock = metadataBlocksPayload[metadataBlockKey]
267277
return {
268278
name: metadataBlock.name,
269-
fields: transformPayloadToDatasetMetadataFields(metadataBlock.fields)
279+
fields: transformPayloadToDatasetMetadataFields(metadataBlock.fields, keepRawFields)
270280
}
271281
}) as DatasetMetadataBlocks
272282
}
273283

274284
const transformPayloadToDatasetMetadataFields = (
275-
metadataFieldsPayload: MetadataFieldPayload[]
285+
metadataFieldsPayload: MetadataFieldPayload[],
286+
keepRawFields: boolean
276287
): DatasetMetadataFields => {
277288
return metadataFieldsPayload.reduce(
278289
(datasetMetadataFieldsMap: DatasetMetadataFields, field: MetadataFieldPayload) => {
279290
datasetMetadataFieldsMap[field.typeName] = transformPayloadToDatasetMetadataFieldValue(
280291
field.value,
281-
field.typeClass
292+
field.typeClass,
293+
keepRawFields
282294
)
283295
return datasetMetadataFieldsMap
284296
},
@@ -288,7 +300,8 @@ const transformPayloadToDatasetMetadataFields = (
288300

289301
const transformPayloadToDatasetMetadataFieldValue = (
290302
metadataFieldValuePayload: MetadataFieldValuePayload,
291-
typeClass: string
303+
typeClass: string,
304+
keepRawFields: boolean
292305
): DatasetMetadataFieldValue => {
293306
function isArrayOfSubfieldValue(
294307
array: (string | MetadataSubfieldValuePayload)[]
@@ -301,29 +314,37 @@ const transformPayloadToDatasetMetadataFieldValue = (
301314
}
302315

303316
if (typeof metadataFieldValuePayload === 'string') {
317+
if (keepRawFields) {
318+
return metadataFieldValuePayload
319+
}
304320
return transformHtmlToMarkdown(metadataFieldValuePayload)
305321
} else if (Array.isArray(metadataFieldValuePayload)) {
306322
if (isArrayOfSubfieldValue(metadataFieldValuePayload)) {
307323
return metadataFieldValuePayload.map((metadataSubfieldValuePayload) =>
308-
transformPayloadToDatasetMetadataSubfieldValue(metadataSubfieldValuePayload)
324+
transformPayloadToDatasetMetadataSubfieldValue(metadataSubfieldValuePayload, keepRawFields)
309325
)
310326
} else {
327+
if (keepRawFields) {
328+
return metadataFieldValuePayload
329+
}
311330
return metadataFieldValuePayload.map(transformHtmlToMarkdown)
312331
}
313332
} else {
314333
return transformPayloadToDatasetMetadataSubfieldValue(
315-
metadataFieldValuePayload as MetadataSubfieldValuePayload
334+
metadataFieldValuePayload as MetadataSubfieldValuePayload,
335+
keepRawFields
316336
)
317337
}
318338
}
319339

320340
const transformPayloadToDatasetMetadataSubfieldValue = (
321-
metadataSubfieldValuePayload: MetadataSubfieldValuePayload
341+
metadataSubfieldValuePayload: MetadataSubfieldValuePayload,
342+
keepRawFields: boolean
322343
): DatasetMetadataSubField => {
323344
const result: DatasetMetadataSubField = {}
324345
Object.keys(metadataSubfieldValuePayload).forEach((key) => {
325346
const subFieldValue = metadataSubfieldValuePayload[key].value
326-
result[key] = transformHtmlToMarkdown(subFieldValue)
347+
result[key] = keepRawFields ? subFieldValue : transformHtmlToMarkdown(subFieldValue)
327348
})
328349
return result
329350
}

src/files/infra/repositories/transformers/fileTransformers.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ export const transformFileResponseToFile = (
2727
if (returnDatasetVersion) {
2828
return [
2929
transformFilePayloadToFile(filePayload),
30-
transformVersionPayloadToDataset(filePayload.datasetVersion)
30+
transformVersionPayloadToDataset(filePayload.datasetVersion, false)
3131
]
3232
}
3333
return transformFilePayloadToFile(filePayload)
+109
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
import { ApiConfig, createDataset, getDataset, ReadError } from '../../../src'
2+
import { DataverseApiAuthMechanism } from '../../../src/core/infra/repositories/ApiConfig'
3+
import { DatasetDescription } from '../../../src/datasets/domain/models/Dataset'
4+
import { deleteUnpublishedDatasetViaApi } from '../../testHelpers/datasets/datasetHelper'
5+
import { TestConstants } from '../../testHelpers/TestConstants'
6+
7+
const testNewDataset = {
8+
metadataBlockValues: [
9+
{
10+
name: 'citation',
11+
fields: {
12+
title: 'Dataset created using the createDataset use case',
13+
author: [
14+
{
15+
authorName: 'Admin, Dataverse',
16+
authorAffiliation: 'Dataverse.org'
17+
},
18+
{
19+
authorName: 'Owner, Dataverse',
20+
authorAffiliation: 'Dataversedemo.org'
21+
}
22+
],
23+
datasetContact: [
24+
{
25+
datasetContactEmail: '[email protected]',
26+
datasetContactName: 'Finch, Fiona'
27+
}
28+
],
29+
dsDescription: [
30+
{
31+
dsDescriptionValue: 'Hello <b>world</b>'
32+
}
33+
],
34+
subject: ['Medicine, Health and Life Sciences']
35+
}
36+
}
37+
]
38+
}
39+
40+
describe('execute', () => {
41+
beforeEach(async () => {
42+
ApiConfig.init(
43+
TestConstants.TEST_API_URL,
44+
DataverseApiAuthMechanism.API_KEY,
45+
process.env.TEST_API_KEY
46+
)
47+
})
48+
49+
test('should successfully get a dataset when a valid id is sent', async () => {
50+
const createdDatasetIdentifiers = await createDataset.execute(testNewDataset)
51+
52+
const dataset = await getDataset.execute(createdDatasetIdentifiers.numericId)
53+
expect(dataset).not.toBeNull()
54+
expect(dataset.id).toBe(createdDatasetIdentifiers.numericId)
55+
56+
await deleteUnpublishedDatasetViaApi(createdDatasetIdentifiers.numericId)
57+
})
58+
59+
test('should successfully get a dataset when a valid persistent id is sent', async () => {
60+
const createdDatasetIdentifiers = await createDataset.execute(testNewDataset)
61+
62+
const dataset = await getDataset.execute(createdDatasetIdentifiers.persistentId)
63+
expect(dataset).not.toBeNull()
64+
expect(dataset.id).toBe(createdDatasetIdentifiers.numericId)
65+
66+
await deleteUnpublishedDatasetViaApi(createdDatasetIdentifiers.numericId)
67+
})
68+
69+
test('should throw an error when an invalid id is sent', async () => {
70+
const nonExistentTestDatasetId = 'non-existent-dataset'
71+
const expectedError = new ReadError(`[400] Bad dataset ID number: ${nonExistentTestDatasetId}.`)
72+
73+
await expect(getDataset.execute(nonExistentTestDatasetId)).rejects.toThrow(expectedError)
74+
})
75+
76+
test('should return metadata fields in markdown format when keepRawFields is false', async () => {
77+
const createdDatasetIdentifiers = await createDataset.execute(testNewDataset)
78+
79+
const dataset = await getDataset.execute(
80+
createdDatasetIdentifiers.numericId,
81+
undefined,
82+
false,
83+
false
84+
)
85+
86+
expect(
87+
(dataset.metadataBlocks[0].fields.dsDescription[0] as DatasetDescription).dsDescriptionValue
88+
).toBe('Hello **world**')
89+
90+
await deleteUnpublishedDatasetViaApi(createdDatasetIdentifiers.numericId)
91+
})
92+
93+
test('should not return metadata fields in markdown format when keepRawFields is true', async () => {
94+
const createdDatasetIdentifiers = await createDataset.execute(testNewDataset)
95+
96+
const dataset = await getDataset.execute(
97+
createdDatasetIdentifiers.numericId,
98+
undefined,
99+
false,
100+
true
101+
)
102+
103+
expect(
104+
(dataset.metadataBlocks[0].fields.dsDescription[0] as DatasetDescription).dsDescriptionValue
105+
).toBe('Hello <b>world</b>')
106+
107+
await deleteUnpublishedDatasetViaApi(createdDatasetIdentifiers.numericId)
108+
})
109+
})

0 commit comments

Comments
 (0)