mirror of
https://github.com/sasjs/adapter.git
synced 2025-12-10 17:04:36 +00:00
feat: added methods to GET and UPDATE file content on viya
This commit is contained in:
@@ -28,6 +28,7 @@ import { uploadTables } from './api/viya/uploadTables'
|
||||
import { executeOnComputeApi } from './api/viya/executeOnComputeApi'
|
||||
import { getAccessTokenForViya } from './auth/getAccessTokenForViya'
|
||||
import { refreshTokensForViya } from './auth/refreshTokensForViya'
|
||||
import { FileContentUpdate } from './types/FileContentUpdate'
|
||||
|
||||
interface JobExecutionResult {
|
||||
result?: { result: object }
|
||||
@@ -311,6 +312,72 @@ export class SASViyaApiClient {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the file content for a file in the specified folder.
|
||||
*
|
||||
* @param folderPath - the full path to the folder containing the file. eg: /Public/folder1/folder2
|
||||
* @param fileName - the name of the file in the `folderPath`
|
||||
* @param accessToken - an access token for authorizing the request
|
||||
*/
|
||||
public async getFileContent(
|
||||
folderPath: string,
|
||||
fileName: string,
|
||||
accessToken?: string
|
||||
) {
|
||||
const { fileUri } = await this.getFileUri(
|
||||
folderPath,
|
||||
fileName,
|
||||
accessToken
|
||||
).catch((err) => {
|
||||
throw prefixMessage(
|
||||
err,
|
||||
`Error while getting file URI for: ${fileName} in folder: ${folderPath}. `
|
||||
)
|
||||
})
|
||||
|
||||
return await this.requestClient
|
||||
.get<string>(`${this.serverUrl}${fileUri}/content`, accessToken)
|
||||
.then((res) => res.result)
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the file content for a file in the specified folder.
|
||||
*
|
||||
* @param folderPath - the full path to the folder containing the file. eg: /Public/folder1/folder2
|
||||
* @param fileName - the name of the file in the `folderPath`
|
||||
* @param content - the new content to be written to the file
|
||||
* @param accessToken - an access token for authorizing the request
|
||||
*/
|
||||
public async updateFileContent(
|
||||
folderPath: string,
|
||||
fileName: string,
|
||||
content: string,
|
||||
accessToken?: string
|
||||
) {
|
||||
const { fileUri, etag } = await this.getFileUri(
|
||||
folderPath,
|
||||
fileName,
|
||||
accessToken
|
||||
).catch((err) => {
|
||||
throw prefixMessage(
|
||||
err,
|
||||
`Error while getting file URI for: ${fileName} in folder: ${folderPath}. `
|
||||
)
|
||||
})
|
||||
|
||||
return await this.requestClient
|
||||
.put<FileContentUpdate>(
|
||||
`${this.serverUrl}${fileUri}/content`,
|
||||
content,
|
||||
accessToken,
|
||||
{
|
||||
'If-Match': etag,
|
||||
'Content-Type': 'text/plain'
|
||||
}
|
||||
)
|
||||
.then((res) => res.result)
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches a folder. Path to the folder is required.
|
||||
* @param folderPath - the absolute path to the folder.
|
||||
@@ -941,6 +1008,7 @@ export class SASViyaApiClient {
|
||||
})
|
||||
|
||||
if (!folder) return undefined
|
||||
|
||||
return folder
|
||||
}
|
||||
|
||||
@@ -952,6 +1020,47 @@ export class SASViyaApiClient {
|
||||
return `/folders/folders/${folderDetails.id}`
|
||||
}
|
||||
|
||||
private async getFileUri(
|
||||
folderPath: string,
|
||||
fileName: string,
|
||||
accessToken?: string
|
||||
): Promise<{
|
||||
fileUri: string
|
||||
etag: string
|
||||
}> {
|
||||
const folderMembers = await this.listFolder(folderPath, accessToken, 1000, {
|
||||
returnDetails: true
|
||||
}).catch((err) => {
|
||||
throw prefixMessage(err, `Error while listing folder: ${folderPath}. `)
|
||||
})
|
||||
|
||||
if (!folderMembers || !folderMembers.length)
|
||||
throw new Error(`No members found in folder: ${folderPath}`)
|
||||
|
||||
const fileUri = folderMembers.find(
|
||||
(member) => member.name === fileName
|
||||
)?.uri
|
||||
|
||||
if (!fileUri)
|
||||
throw new Error(`File ${fileName} not found in folder: ${folderPath}`)
|
||||
|
||||
// Fetch the file details to get the resource ETag
|
||||
const { etag } = await this.requestClient.get<File>(
|
||||
`${this.serverUrl}${fileUri}`,
|
||||
accessToken
|
||||
)
|
||||
|
||||
if (!etag)
|
||||
throw new Error(
|
||||
`File ${fileName} does not have an ETag, or request failed.`
|
||||
)
|
||||
|
||||
return {
|
||||
fileUri,
|
||||
etag: etag || ''
|
||||
}
|
||||
}
|
||||
|
||||
private async getRecycleBinUri(accessToken?: string) {
|
||||
const url = '/folders/folders/@myRecycleBin'
|
||||
|
||||
@@ -999,14 +1108,19 @@ export class SASViyaApiClient {
|
||||
}
|
||||
|
||||
/**
|
||||
* Lists children folders for given Viya folder.
|
||||
* Lists children folders/files for given Viya folder.
|
||||
* @param sourceFolder - the full path (eg `/Public/example/myFolder`) or URI of the source folder listed. Providing URI instead of path will save one extra request.
|
||||
* @param accessToken - an access token for authorizing the request.
|
||||
* @param {Object} [options] - Additional options.
|
||||
* @param {boolean} [options.returnDetails=false] - when set to true, the function will return an array of objects with member details, otherwise it will return an array of member names.
|
||||
*/
|
||||
public async listFolder(
|
||||
sourceFolder: string,
|
||||
accessToken?: string,
|
||||
limit: number = 20
|
||||
limit: number = 20,
|
||||
options?: {
|
||||
returnDetails?: boolean
|
||||
}
|
||||
) {
|
||||
// checks if 'sourceFolder' is already a URI
|
||||
const sourceFolderUri = isUri(sourceFolder)
|
||||
@@ -1018,11 +1132,20 @@ export class SASViyaApiClient {
|
||||
accessToken
|
||||
)
|
||||
|
||||
let membersToReturn = []
|
||||
|
||||
if (members && members.items) {
|
||||
return members.items.map((item: any) => item.name)
|
||||
} else {
|
||||
return []
|
||||
// If returnDetails is true, return full member details
|
||||
if (options?.returnDetails) {
|
||||
membersToReturn = members.items
|
||||
} else {
|
||||
// If returnDetails is false, return only member names
|
||||
membersToReturn = members.items.map((item: any) => item.name)
|
||||
}
|
||||
}
|
||||
|
||||
// Return members without Etag
|
||||
return membersToReturn
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
39
src/SASjs.ts
39
src/SASjs.ts
@@ -411,6 +411,36 @@ export default class SASjs {
|
||||
)
|
||||
}
|
||||
|
||||
public async getFileContent(
|
||||
folderPath: string,
|
||||
fileName: string,
|
||||
accessToken?: string
|
||||
) {
|
||||
this.isMethodSupported('getFileContent', [ServerType.SasViya])
|
||||
|
||||
return await this.sasViyaApiClient!.getFileContent(
|
||||
folderPath,
|
||||
fileName,
|
||||
accessToken
|
||||
)
|
||||
}
|
||||
|
||||
public async updateFileContent(
|
||||
folderPath: string,
|
||||
fileName: string,
|
||||
content: string,
|
||||
accessToken?: string
|
||||
) {
|
||||
this.isMethodSupported('updateFileContent', [ServerType.SasViya])
|
||||
|
||||
return await this.sasViyaApiClient!.updateFileContent(
|
||||
folderPath,
|
||||
fileName,
|
||||
content,
|
||||
accessToken
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches a folder from the SAS file system.
|
||||
* @param folderPath - path of the folder to be fetched.
|
||||
@@ -436,18 +466,23 @@ export default class SASjs {
|
||||
* Lists children folders for given Viya folder.
|
||||
* @param sourceFolder - the full path (eg `/Public/example/myFolder`) or URI of the source folder listed. Providing URI instead of path will save one extra request.
|
||||
* @param accessToken - an access token for authorizing the request.
|
||||
* @param returnDetails - when set to true, the function will return an array of objects with member details, otherwise it will return an array of member names.
|
||||
*/
|
||||
public async listFolder(
|
||||
sourceFolder: string,
|
||||
accessToken?: string,
|
||||
limit?: number
|
||||
limit?: number,
|
||||
returnDetails = false
|
||||
) {
|
||||
this.isMethodSupported('listFolder', [ServerType.SasViya])
|
||||
|
||||
return await this.sasViyaApiClient?.listFolder(
|
||||
sourceFolder,
|
||||
accessToken,
|
||||
limit
|
||||
limit,
|
||||
{
|
||||
returnDetails
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
33
src/types/FileContentUpdate.ts
Normal file
33
src/types/FileContentUpdate.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
export interface FileContentUpdate {
|
||||
creationTimeStamp: string
|
||||
modifiedTimeStamp: string
|
||||
createdBy: string
|
||||
modifiedBy: string
|
||||
id: string
|
||||
properties: Properties
|
||||
contentDisposition: string
|
||||
contentType: string
|
||||
encoding: string
|
||||
links: Link[]
|
||||
name: string
|
||||
size: number
|
||||
searchable: boolean
|
||||
fileStatus: string
|
||||
fileVersion: number
|
||||
typeDefName: string
|
||||
version: number
|
||||
virusDetected: boolean
|
||||
urlDetected: boolean
|
||||
quarantine: boolean
|
||||
}
|
||||
|
||||
export interface Link {
|
||||
method: string
|
||||
rel: string
|
||||
href: string
|
||||
uri: string
|
||||
type?: string
|
||||
responseType?: string
|
||||
}
|
||||
|
||||
export interface Properties {}
|
||||
Reference in New Issue
Block a user