Skip to content

Commit

Permalink
Merge pull request #238 from IQSS/feat/236-strict-ts-config
Browse files Browse the repository at this point in the history
Typescript strict config
  • Loading branch information
ofahimIQSS authored Jan 27, 2025
2 parents 397bceb + e82bb0f commit c789d0f
Show file tree
Hide file tree
Showing 29 changed files with 166 additions and 150 deletions.
8 changes: 4 additions & 4 deletions src/collections/infra/repositories/CollectionsRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ export interface NewCollectionContactRequestPayload {
}

export interface NewCollectionMetadataBlocksRequestPayload {
metadataBlockNames: string[]
facetIds: string[]
inputLevels: NewCollectionInputLevelRequestPayload[]
metadataBlockNames?: string[]
facetIds?: string[]
inputLevels?: NewCollectionInputLevelRequestPayload[]
}

export interface NewCollectionInputLevelRequestPayload {
Expand Down Expand Up @@ -179,7 +179,7 @@ export class CollectionsRepository extends ApiRepository implements ICollections
})
)

const inputLevelsRequestBody: NewCollectionInputLevelRequestPayload[] =
const inputLevelsRequestBody: NewCollectionInputLevelRequestPayload[] | undefined =
collectionDTO.inputLevels?.map((inputLevel) => ({
datasetFieldTypeName: inputLevel.datasetFieldName,
include: inputLevel.include,
Expand Down
2 changes: 1 addition & 1 deletion src/core/infra/repositories/ApiRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export abstract class ApiRepository {
protected buildApiEndpoint(
resourceName: string,
operation: string,
resourceId: number | string = undefined
resourceId: number | string | undefined = undefined
) {
return typeof resourceId === 'number'
? `/${resourceName}/${resourceId}/${operation}`
Expand Down
2 changes: 1 addition & 1 deletion src/core/infra/repositories/apiConfigBuilders.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export const buildRequestConfig = (
contentType: string = ApiConstants.CONTENT_TYPE_APPLICATION_JSON,
abortSignal?: AbortSignal
): AxiosRequestConfig => {
const requestConfig: AxiosRequestConfig = {
const requestConfig: AxiosRequestConfig & { headers: Record<string, unknown> } = {
params: queryParams,
headers: {
'Content-Type': contentType
Expand Down
2 changes: 1 addition & 1 deletion src/datasets/domain/models/Dataset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ export type DatasetMetadataFieldValue =
| DatasetMetadataSubField[]
| AnonymizedField

export type DatasetMetadataSubField = Record<string, string>
export type DatasetMetadataSubField = Record<string, string | undefined>

export interface CitationMetadataBlock extends DatasetMetadataBlock {
name: 'citation'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@ export class DatasetResourceValidator implements ResourceValidator {
metadataBlocks: MetadataBlock[]
) {
const metadataBlockName = metadataBlockValues.name
const metadataBlock: MetadataBlock = metadataBlocks.find(
const metadataBlock = metadataBlocks.find(
(metadataBlock) => metadataBlock.name === metadataBlockName
)
) as MetadataBlock

for (const metadataFieldKey of Object.keys(metadataBlock.metadataFields)) {
this.metadataFieldValidator.validate({
metadataFieldInfo: metadataBlock.metadataFields[metadataFieldKey],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { MetadataFieldValidator } from './MetadataFieldValidator'
import { DatasetMetadataChildFieldValueDTO } from '../../dtos/DatasetDTO'
import { MultipleMetadataFieldValidator } from './MultipleMetadataFieldValidator'
import {
MetadataFieldInfo,
MetadataFieldType,
MetadataFieldWatermark
} from '../../../../metadataBlocks/domain/models/MetadataBlock'
Expand Down Expand Up @@ -62,7 +63,7 @@ export class SingleMetadataFieldValidator extends BaseMetadataFieldValidator {
datasetMetadataFieldAndValueInfo: DatasetMetadataFieldAndValueInfo
) {
if (
!datasetMetadataFieldAndValueInfo.metadataFieldInfo.controlledVocabularyValues.includes(
!datasetMetadataFieldAndValueInfo.metadataFieldInfo.controlledVocabularyValues?.includes(
datasetMetadataFieldAndValueInfo.metadataFieldValue as string
)
) {
Expand Down Expand Up @@ -120,13 +121,21 @@ export class SingleMetadataFieldValidator extends BaseMetadataFieldValidator {
datasetMetadataFieldAndValueInfo: DatasetMetadataFieldAndValueInfo
) {
const metadataFieldInfo = datasetMetadataFieldAndValueInfo.metadataFieldInfo
const childMetadataFieldKeys = Object.keys(metadataFieldInfo.childMetadataFields)

const childMetadataFieldKeys = Object.keys(
metadataFieldInfo.childMetadataFields as Record<string, MetadataFieldInfo>
)

const metadataFieldValidator = new MetadataFieldValidator(
this,
new MultipleMetadataFieldValidator(this)
)

for (const childMetadataFieldKey of childMetadataFieldKeys) {
const childMetadataFieldInfo = metadataFieldInfo.childMetadataFields[childMetadataFieldKey]
const childMetadataFieldInfo = (
metadataFieldInfo.childMetadataFields as Record<string, MetadataFieldInfo>
)[childMetadataFieldKey]

metadataFieldValidator.validate({
metadataFieldInfo: childMetadataFieldInfo,
metadataFieldKey: childMetadataFieldKey,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,9 @@ export const transformDatasetModelToUpdateDatasetRequestPayload = (
datasetMetadataBlocksValues.forEach(function (
newDatasetMetadataBlockValues: DatasetMetadataBlockValuesDTO
) {
const metadataBlock: MetadataBlock = metadataBlocks.find(
const metadataBlock = metadataBlocks.find(
(metadataBlock) => metadataBlock.name == newDatasetMetadataBlockValues.name
)
) as MetadataBlock
const metadataBlockFieldsPayload: MetadataFieldRequestPayload[] = []
const metadataBlockFields = metadataBlock.metadataFields
const datasetMetadataFields = newDatasetMetadataBlockValues.fields
Expand Down Expand Up @@ -119,7 +119,7 @@ export const transformMetadataBlockModelsToRequestPayload = (
) {
const metadataBlock: MetadataBlock = metadataBlocks.find(
(metadataBlock) => metadataBlock.name == newDatasetMetadataBlockValues.name
)
) as MetadataBlock
metadataBlocksRequestPayload[newDatasetMetadataBlockValues.name] = {
fields: transformMetadataFieldModelsToRequestPayload(
newDatasetMetadataBlockValues.fields,
Expand Down Expand Up @@ -195,8 +195,9 @@ export const transformMetadataChildFieldValueToRequestPayload = (
): Record<string, MetadataFieldRequestPayload> => {
const metadataChildFieldRequestPayload: Record<string, MetadataFieldRequestPayload> = {}
for (const metadataChildFieldKey of Object.keys(datasetMetadataChildFieldValue)) {
const childMetadataFieldInfo: MetadataFieldInfo =
metadataBlockFieldInfo.childMetadataFields[metadataChildFieldKey]
const childMetadataFieldInfo: MetadataFieldInfo = (
metadataBlockFieldInfo.childMetadataFields as Record<string, MetadataFieldInfo>
)[metadataChildFieldKey]
const value: string = datasetMetadataChildFieldValue[metadataChildFieldKey] as unknown as string
metadataChildFieldRequestPayload[metadataChildFieldKey] = {
value: value,
Expand Down Expand Up @@ -252,7 +253,9 @@ export const transformVersionPayloadToDataset = (
})
}
if ('license' in versionPayload) {
datasetModel.license = transformPayloadToDatasetLicense(versionPayload.license)
datasetModel.license = transformPayloadToDatasetLicense(
versionPayload.license as LicensePayload
)
}
if ('alternativePersistentId' in versionPayload) {
datasetModel.alternativePersistentId = versionPayload.alternativePersistentId
Expand Down
17 changes: 11 additions & 6 deletions src/files/infra/clients/DirectUploadClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,8 @@ export class DirectUploadClient implements IDirectUploadClient {
if (axios.isCancel(error)) {
throw new FileUploadCancelError(file.name, datasetId)
}
throw new FileUploadError(file.name, datasetId, error.message)
const errorMessage = error instanceof Error ? error.message : 'Upload singlepart file failed'
throw new FileUploadError(file.name, datasetId, errorMessage)
}
}

Expand Down Expand Up @@ -114,16 +115,20 @@ export class DirectUploadClient implements IDirectUploadClient {
eTags[`${index + 1}`] = eTag
} catch (error) {
if (axios.isCancel(error)) {
await this.abortMultipartUpload(file.name, datasetId, destination.abortEndpoint)
await this.abortMultipartUpload(file.name, datasetId, destination.abortEndpoint as string)
throw new FileUploadCancelError(file.name, datasetId)
}
if (retries < maxRetries) {
const backoffDelay = Math.pow(2, retries) * 1000
await new Promise((resolve) => setTimeout(resolve, backoffDelay))
await uploadPart(destinationUrl, index, retries + 1)
} else {
await this.abortMultipartUpload(file.name, datasetId, destination.abortEndpoint)
throw new FilePartUploadError(file.name, datasetId, error.message, index + 1)
await this.abortMultipartUpload(file.name, datasetId, destination.abortEndpoint as string)

const errorMessage =
error instanceof Error ? error.message : 'Upload part of multipart file failed'

throw new FilePartUploadError(file.name, datasetId, errorMessage, index + 1)
}
}
}
Expand Down Expand Up @@ -165,7 +170,7 @@ export class DirectUploadClient implements IDirectUploadClient {
): Promise<void> {
return await axios
.put(
buildRequestUrl(destination.completeEndpoint),
buildRequestUrl(destination.completeEndpoint as string),
eTags,
buildRequestConfig(
true,
Expand All @@ -177,7 +182,7 @@ export class DirectUploadClient implements IDirectUploadClient {
.then(() => undefined)
.catch(async (error) => {
if (axios.isCancel(error)) {
await this.abortMultipartUpload(fileName, datasetId, destination.abortEndpoint)
await this.abortMultipartUpload(fileName, datasetId, destination.abortEndpoint as string)
throw new FileUploadCancelError(fileName, datasetId)
}
throw new MultipartCompletionError(fileName, datasetId, error.message)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,15 +64,19 @@ const transformMetadataBlockPayloadToMetadataBlock = (

const getChildFieldKeys = (metadataBlockFieldsPayload: Record<string, unknown>): Set<string> => {
const childFieldKeys = new Set<string>()
Object.values(metadataBlockFieldsPayload).forEach(
(fieldInfo: { childFields?: Record<string, unknown> }) => {
if (fieldInfo.childFields) {
Object.keys(fieldInfo.childFields).forEach((childKey) => {
childFieldKeys.add(childKey)
})
}
Object.values(metadataBlockFieldsPayload).forEach((fieldInfo) => {
if (
fieldInfo &&
typeof fieldInfo === 'object' &&
'childFields' in fieldInfo &&
typeof fieldInfo.childFields === 'object' &&
(fieldInfo?.childFields as Record<string, unknown>)
) {
Object.keys(fieldInfo.childFields as Record<string, unknown>).forEach((childKey) => {
childFieldKeys.add(childKey)
})
}
)
})
return childFieldKeys
}

Expand Down
6 changes: 3 additions & 3 deletions test/functional/collections/CreateCollection.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,15 @@ describe('execute', () => {
test('should throw an error when the parent collection does not exist', async () => {
const testNewCollection = createCollectionDTO()
expect.assertions(2)
let writeError: WriteError
let writeError: WriteError | undefined = undefined
try {
await createCollection.execute(testNewCollection, TestConstants.TEST_DUMMY_COLLECTION_ID)
throw new Error('Use case should throw an error')
} catch (error) {
writeError = error
writeError = error as WriteError
} finally {
expect(writeError).toBeInstanceOf(WriteError)
expect(writeError.message).toEqual(
expect(writeError?.message).toEqual(
`There was an error when writing the resource. Reason was: [404] Can't find dataverse with identifier='${TestConstants.TEST_DUMMY_COLLECTION_ID}'`
)
}
Expand Down
6 changes: 3 additions & 3 deletions test/functional/collections/GetCollectionFacets.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,15 @@ describe('execute', () => {

test('should throw an error when collection does not exist', async () => {
expect.assertions(2)
let readError: ReadError
let readError: ReadError | undefined = undefined
try {
await getCollectionFacets.execute(TestConstants.TEST_DUMMY_COLLECTION_ID)
throw new Error('Use case should throw an error')
} catch (error) {
readError = error
readError = error as ReadError
} finally {
expect(readError).toBeInstanceOf(ReadError)
expect(readError.message).toEqual(
expect(readError?.message).toEqual(
`There was an error when reading the resource. Reason was: [404] Can't find dataverse with identifier='${TestConstants.TEST_DUMMY_COLLECTION_ID}'`
)
}
Expand Down
16 changes: 7 additions & 9 deletions test/functional/collections/GetCollectionItems.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import {
} from '../../testHelpers/collections/collectionHelper'
import { uploadFileViaApi } from '../../testHelpers/files/filesHelper'
import { deleteUnpublishedDatasetViaApi } from '../../testHelpers/datasets/datasetHelper'
import { CollectionItemSubset } from '../../../src/collections/domain/models/CollectionItemSubset'

describe('execute', () => {
const testCollectionAlias = 'collectionsRepositoryFunctionalTestCollection'
Expand Down Expand Up @@ -59,33 +58,32 @@ describe('execute', () => {
// Give enough time to Solr for indexing
await new Promise((resolve) => setTimeout(resolve, 5000))

let actual: CollectionItemSubset
try {
actual = await getCollectionItems.execute(testCollectionAlias)
} catch (error) {
throw new Error('Item subset should be retrieved')
} finally {
const actual = await getCollectionItems.execute(testCollectionAlias)

const actualFilePreview = actual.items[0] as FilePreview
const actualDatasetPreview = actual.items[1] as DatasetPreview

expect(actualFilePreview.name).toBe('test-file-1.txt')
expect(actualDatasetPreview.title).toBe('Dataset created using the createDataset use case')

expect(actual.totalItemCount).toBe(2)
} catch (error) {
throw new Error('Item subset should be retrieved')
}
})

test('should throw an error when collection does not exist', async () => {
expect.assertions(2)
let readError: ReadError
let readError: ReadError | undefined = undefined
try {
await getCollectionItems.execute(TestConstants.TEST_DUMMY_COLLECTION_ALIAS)
throw new Error('Use case should throw an error')
} catch (error) {
readError = error
readError = error as ReadError
} finally {
expect(readError).toBeInstanceOf(ReadError)
expect(readError.message).toEqual(
expect(readError?.message).toEqual(
`There was an error when reading the resource. Reason was: [400] Could not find dataverse with alias ${TestConstants.TEST_DUMMY_COLLECTION_ALIAS}`
)
}
Expand Down
51 changes: 22 additions & 29 deletions test/functional/collections/GetCollectionUserPermissions.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
import {
ApiConfig,
CollectionUserPermissions,
ReadError,
getCollectionUserPermissions
} from '../../../src'
import { ApiConfig, ReadError, getCollectionUserPermissions } from '../../../src'
import { TestConstants } from '../../testHelpers/TestConstants'
import { DataverseApiAuthMechanism } from '../../../src/core/infra/repositories/ApiConfig'

Expand All @@ -19,49 +14,47 @@ describe('execute', () => {
})

test('should return user permissions for the default collection', async () => {
let actual: CollectionUserPermissions
try {
actual = await getCollectionUserPermissions.execute()
const permissions = await getCollectionUserPermissions.execute()

expect(permissions.canAddDataset).toBe(true)
expect(permissions.canAddCollection).toBe(true)
expect(permissions.canDeleteCollection).toBe(true)
expect(permissions.canEditCollection).toBe(true)
expect(permissions.canManageCollectionPermissions).toBe(true)
expect(permissions.canPublishCollection).toBe(true)
expect(permissions.canViewUnpublishedCollection).toBe(true)
} catch (error) {
throw new Error('Permissions should be retrieved')
} finally {
expect(actual.canAddDataset).toBe(true)
expect(actual.canAddCollection).toBe(true)
expect(actual.canDeleteCollection).toBe(true)
expect(actual.canEditCollection).toBe(true)
expect(actual.canManageCollectionPermissions).toBe(true)
expect(actual.canPublishCollection).toBe(true)
expect(actual.canViewUnpublishedCollection).toBe(true)
}
})
test('should return user permissions when a valid collection alias is provided', async () => {
let actual: CollectionUserPermissions
try {
actual = await getCollectionUserPermissions.execute(ROOT_COLLECTION_ALIAS)
const permissions = await getCollectionUserPermissions.execute(ROOT_COLLECTION_ALIAS)

expect(permissions.canAddDataset).toBe(true)
expect(permissions.canAddCollection).toBe(true)
expect(permissions.canDeleteCollection).toBe(true)
expect(permissions.canEditCollection).toBe(true)
expect(permissions.canManageCollectionPermissions).toBe(true)
expect(permissions.canPublishCollection).toBe(true)
expect(permissions.canViewUnpublishedCollection).toBe(true)
} catch (error) {
throw new Error('Permissions should be retrieved')
} finally {
expect(actual.canAddDataset).toBe(true)
expect(actual.canAddCollection).toBe(true)
expect(actual.canDeleteCollection).toBe(true)
expect(actual.canEditCollection).toBe(true)
expect(actual.canManageCollectionPermissions).toBe(true)
expect(actual.canPublishCollection).toBe(true)
expect(actual.canViewUnpublishedCollection).toBe(true)
}
})

test('should throw an error when collection does not exist', async () => {
expect.assertions(2)
let readError: ReadError
let readError: ReadError | undefined = undefined
try {
await getCollectionUserPermissions.execute(TestConstants.TEST_DUMMY_COLLECTION_ID)
throw new Error('Use case should throw an error')
} catch (error) {
readError = error
readError = error as ReadError
} finally {
expect(readError).toBeInstanceOf(ReadError)
expect(readError.message).toEqual(
expect(readError?.message).toEqual(
`There was an error when reading the resource. Reason was: [404] Can't find dataverse with identifier='${TestConstants.TEST_DUMMY_COLLECTION_ID}'`
)
}
Expand Down
Loading

0 comments on commit c789d0f

Please sign in to comment.