Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ This changelog follows the principles of [Keep a Changelog](https://keepachangel
- New Use Case: [Get a Template](./docs/useCases.md#get-a-template) under Templates.
- New Use Case: [Delete a Template](./docs/useCases.md#delete-a-template) under Templates.
- New Use Case: [Update Terms of Access](./docs/useCases.md#update-terms-of-access).
- Guestbooks: Added use cases and repository support for guestbook creation, listing, and enabling/disabling.
- Access: Added a dedicated `access` module for guestbook-at-request and download terms/guestbook submission endpoints.

### Changed

Expand Down
216 changes: 216 additions & 0 deletions docs/useCases.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,19 @@ The different use cases currently available in the package are classified below,
- [Get External Tools](#get-external-tools)
- [Get Dataset External Tool Resolved](#get-dataset-external-tool-resolved)
- [Get File External Tool Resolved](#get-file-external-tool-resolved)
- [Guestbooks](#Guestbooks)
- [Guestbooks read use cases](#guestbooks-read-use-cases)
- [Get a Guestbook](#get-a-guestbook)
- [Get Guestbooks By Collection Id](#get-guestbooks-by-collection-id)
- [Guestbooks write use cases](#guestbooks-write-use-cases)
- [Create a Guestbook](#create-a-guestbook)
- [Set Guestbook Enabled](#set-guestbook-enabled)
- [Access](#Access)
- [Access write use cases](#access-write-use-cases)
- [Submit Guestbook For Datafile Download](#submit-guestbook-for-datafile-download)
- [Submit Guestbook For Datafiles Download](#submit-guestbook-for-datafiles-download)
- [Submit Guestbook For Dataset Download](#submit-guestbook-for-dataset-download)
- [Submit Guestbook For Dataset Version Download](#submit-guestbook-for-dataset-version-download)

## Collections

Expand Down Expand Up @@ -2767,3 +2780,206 @@ getFileExternalToolResolved
```

_See [use case](../src/externalTools/domain/useCases/GetfileExternalToolResolved.ts) implementation_.

## Guestbooks

### Guestbooks Read Use Cases

#### Get a Guestbook

Returns a [Guestbook](../src/guestbooks/domain/models/Guestbook.ts) by its id.

##### Example call:

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

const guestbookId = 123

getGuestbook.execute(guestbookId).then((guestbook: Guestbook) => {
/* ... */
})
```

_See [use case](../src/guestbooks/domain/useCases/GetGuestbook.ts) implementation_.

#### Get Guestbooks By Collection Id

Returns all [Guestbook](../src/guestbooks/domain/models/Guestbook.ts) entries available for a collection.

##### Example call:

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

const collectionIdOrAlias = 'root'

getGuestbooksByCollectionId.execute(collectionIdOrAlias).then((guestbooks: Guestbook[]) => {
/* ... */
})
```

_See [use case](../src/guestbooks/domain/useCases/GetGuestbooksByCollectionId.ts) implementation_.

### Guestbooks Write Use Cases

#### Create a Guestbook

Creates a guestbook on a collection using [CreateGuestbookDTO](../src/guestbooks/domain/dtos/CreateGuestbookDTO.ts).

##### Example call:

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

const collectionIdOrAlias = 'root'
const guestbook: CreateGuestbookDTO = {
name: 'my test guestbook',
enabled: true,
emailRequired: true,
nameRequired: true,
institutionRequired: false,
positionRequired: false,
customQuestions: [
{
question: 'Describe yourself',
required: false,
displayOrder: 1,
type: 'textarea',
hidden: false
}
]
}

createGuestbook.execute(guestbook, collectionIdOrAlias).then(() => {
/* ... */
})
```

_See [use case](../src/guestbooks/domain/useCases/CreateGuestbook.ts) implementation_.

#### Set Guestbook Enabled

Enables or disables a guestbook in a collection.

##### Example call:

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

const collectionIdOrAlias = 'root'
const guestbookId = 123

setGuestbookEnabled.execute(collectionIdOrAlias, guestbookId, false).then(() => {
/* ... */
})
```

_See [use case](../src/guestbooks/domain/useCases/SetGuestbookEnabled.ts) implementation_.

## Access

### Access Write Use Cases

#### Submit Guestbook For Datafile Download

Submits guestbook answers for a datafile and returns a signed URL.

##### Example call:

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

submitGuestbookForDatafileDownload
.execute(10, {
guestbookResponse: {
answers: [
{ id: 123, value: 'Good' },
{ id: 124, value: ['Multi', 'Line'] }
]
}
})
.then((signedUrl: string) => {
/* ... */
})
```

_See [use case](../src/access/domain/useCases/SubmitGuestbookForDatafileDownload.ts) implementation_.

#### Submit Guestbook For Datafiles Download

Submits guestbook answers for multiple files and returns a signed URL.

##### Example call:

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

submitGuestbookForDatafilesDownload
.execute([10, 11], {
guestbookResponse: {
answers: [
{ id: 123, value: 'Good' },
{ id: 124, value: ['Multi', 'Line'] },
{ id: 125, value: 'Yellow' }
]
}
})
.then((signedUrl: string) => {
/* ... */
})
```

_See [use case](../src/access/domain/useCases/SubmitGuestbookForDatafilesDownload.ts) implementation_.

#### Submit Guestbook For Dataset Download

Submits guestbook answers for dataset download and returns a signed URL.

##### Example call:

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

submitGuestbookForDatasetDownload
.execute('doi:10.5072/FK2/XXXXXX', {
guestbookResponse: {
answers: [
{ id: 123, value: 'Good' },
{ id: 124, value: ['Multi', 'Line'] },
{ id: 125, value: 'Yellow' }
]
}
})
.then((signedUrl: string) => {
/* ... */
})
```

_See [use case](../src/access/domain/useCases/SubmitGuestbookForDatasetDownload.ts) implementation_.

#### Submit Guestbook For Dataset Version Download

Submits guestbook answers for a specific dataset version and returns a signed URL.

##### Example call:

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

submitGuestbookForDatasetVersionDownload
.execute(10, ':latest', {
guestbookResponse: {
answers: [
{ id: 123, value: 'Good' },
{ id: 124, value: ['Multi', 'Line'] },
{ id: 125, value: 'Yellow' }
]
}
})
Comment on lines 2970 to 2979
Copy link

Copilot AI Feb 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This example also omits the required guestbookResponse nesting (GuestbookResponseDTO expects { guestbookResponse: { answers: [...] } }). Align it with the DTO and the working “Datafile Download” example above.

Copilot uses AI. Check for mistakes.
.then((signedUrl: string) => {
/* ... */
})
```

_See [use case](../src/access/domain/useCases/SubmitGuestbookForDatasetVersionDownload.ts) implementation_.
10 changes: 10 additions & 0 deletions src/access/domain/dtos/GuestbookResponseDTO.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
export interface GuestbookAnswerDTO {
id: number | string
value: string | string[]
}

export interface GuestbookResponseDTO {
guestbookResponse: {
answers: GuestbookAnswerDTO[]
}
}
24 changes: 24 additions & 0 deletions src/access/domain/repositories/IAccessRepository.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { GuestbookResponseDTO } from '../dtos/GuestbookResponseDTO'

export interface IAccessRepository {
submitGuestbookForDatafileDownload(
fileId: number | string,
guestbookResponse: GuestbookResponseDTO
): Promise<string>

submitGuestbookForDatafilesDownload(
fileIds: string | Array<number | string>,
guestbookResponse: GuestbookResponseDTO
): Promise<string>

submitGuestbookForDatasetDownload(
datasetId: number | string,
guestbookResponse: GuestbookResponseDTO
): Promise<string>

submitGuestbookForDatasetVersionDownload(
datasetId: number | string,
versionId: string,
guestbookResponse: GuestbookResponseDTO
): Promise<string>
}
18 changes: 18 additions & 0 deletions src/access/domain/useCases/SubmitGuestbookForDatafileDownload.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { UseCase } from '../../../core/domain/useCases/UseCase'
import { GuestbookResponseDTO } from '../dtos/GuestbookResponseDTO'
import { IAccessRepository } from '../repositories/IAccessRepository'

export class SubmitGuestbookForDatafileDownload implements UseCase<string> {
constructor(private readonly accessRepository: IAccessRepository) {}

/**
* Submits a guestbook response for a single datafile download request and returns a signed URL.
*
* @param {number | string} fileId - Datafile identifier (numeric id or persistent id).
* @param {GuestbookResponseDTO} guestbookResponse - Guestbook response payload.
* @returns {Promise<string>} - Signed URL for the download.
*/
async execute(fileId: number | string, guestbookResponse: GuestbookResponseDTO): Promise<string> {
return await this.accessRepository.submitGuestbookForDatafileDownload(fileId, guestbookResponse)
}
}
24 changes: 24 additions & 0 deletions src/access/domain/useCases/SubmitGuestbookForDatafilesDownload.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { UseCase } from '../../../core/domain/useCases/UseCase'
import { GuestbookResponseDTO } from '../dtos/GuestbookResponseDTO'
import { IAccessRepository } from '../repositories/IAccessRepository'

export class SubmitGuestbookForDatafilesDownload implements UseCase<string> {
constructor(private readonly accessRepository: IAccessRepository) {}

/**
* Submits a guestbook response for multiple datafiles download request and returns a signed URL.
*
* @param {string | Array<number | string>} fileIds - Comma-separated string or array of file ids.
* @param {GuestbookResponseDTO} guestbookResponse - Guestbook response payload.
* @returns {Promise<string>} - Signed URL for the download.
*/
async execute(
fileIds: string | Array<number | string>,
guestbookResponse: GuestbookResponseDTO
): Promise<string> {
return await this.accessRepository.submitGuestbookForDatafilesDownload(
fileIds,
guestbookResponse
)
}
}
24 changes: 24 additions & 0 deletions src/access/domain/useCases/SubmitGuestbookForDatasetDownload.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { UseCase } from '../../../core/domain/useCases/UseCase'
import { GuestbookResponseDTO } from '../dtos/GuestbookResponseDTO'
import { IAccessRepository } from '../repositories/IAccessRepository'

export class SubmitGuestbookForDatasetDownload implements UseCase<string> {
constructor(private readonly accessRepository: IAccessRepository) {}

/**
* Submits a guestbook response for dataset download request and returns a signed URL.
*
* @param {number | string} datasetId - Dataset identifier (numeric id or persistent id).
* @param {GuestbookResponseDTO} guestbookResponse - Guestbook response payload.
* @returns {Promise<string>} - Signed URL for the download.
*/
async execute(
datasetId: number | string,
guestbookResponse: GuestbookResponseDTO
): Promise<string> {
return await this.accessRepository.submitGuestbookForDatasetDownload(
datasetId,
guestbookResponse
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { UseCase } from '../../../core/domain/useCases/UseCase'
import { GuestbookResponseDTO } from '../dtos/GuestbookResponseDTO'
import { IAccessRepository } from '../repositories/IAccessRepository'

export class SubmitGuestbookForDatasetVersionDownload implements UseCase<string> {
constructor(private readonly accessRepository: IAccessRepository) {}

/**
* Submits a guestbook response for a specific dataset version download request and returns a signed URL.
*
* @param {number | string} datasetId - Dataset identifier (numeric id or persistent id).
* @param {string} versionId - Dataset version identifier (for example, ':latest' or '1.0').
* @param {GuestbookResponseDTO} guestbookResponse - Guestbook response payload.
* @returns {Promise<string>} - Signed URL for the download.
*/
async execute(
datasetId: number | string,
versionId: string,
guestbookResponse: GuestbookResponseDTO
): Promise<string> {
return await this.accessRepository.submitGuestbookForDatasetVersionDownload(
datasetId,
versionId,
guestbookResponse
)
}
}
25 changes: 25 additions & 0 deletions src/access/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { AccessRepository } from './infra/repositories/AccessRepository'
import { SubmitGuestbookForDatafileDownload } from './domain/useCases/SubmitGuestbookForDatafileDownload'
import { SubmitGuestbookForDatafilesDownload } from './domain/useCases/SubmitGuestbookForDatafilesDownload'
import { SubmitGuestbookForDatasetDownload } from './domain/useCases/SubmitGuestbookForDatasetDownload'
import { SubmitGuestbookForDatasetVersionDownload } from './domain/useCases/SubmitGuestbookForDatasetVersionDownload'

const accessRepository = new AccessRepository()

const submitGuestbookForDatafileDownload = new SubmitGuestbookForDatafileDownload(accessRepository)
const submitGuestbookForDatafilesDownload = new SubmitGuestbookForDatafilesDownload(
accessRepository
)
const submitGuestbookForDatasetDownload = new SubmitGuestbookForDatasetDownload(accessRepository)
const submitGuestbookForDatasetVersionDownload = new SubmitGuestbookForDatasetVersionDownload(
accessRepository
)

export {
submitGuestbookForDatafileDownload,
submitGuestbookForDatafilesDownload,
submitGuestbookForDatasetDownload,
submitGuestbookForDatasetVersionDownload
}

export { GuestbookResponseDTO } from './domain/dtos/GuestbookResponseDTO'
Loading