mirror of
https://github.com/sasjs/adapter.git
synced 2025-12-11 01:14: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 { executeOnComputeApi } from './api/viya/executeOnComputeApi'
|
||||||
import { getAccessTokenForViya } from './auth/getAccessTokenForViya'
|
import { getAccessTokenForViya } from './auth/getAccessTokenForViya'
|
||||||
import { refreshTokensForViya } from './auth/refreshTokensForViya'
|
import { refreshTokensForViya } from './auth/refreshTokensForViya'
|
||||||
|
import { FileContentUpdate } from './types/FileContentUpdate'
|
||||||
|
|
||||||
interface JobExecutionResult {
|
interface JobExecutionResult {
|
||||||
result?: { result: object }
|
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.
|
* Fetches a folder. Path to the folder is required.
|
||||||
* @param folderPath - the absolute path to the folder.
|
* @param folderPath - the absolute path to the folder.
|
||||||
@@ -941,6 +1008,7 @@ export class SASViyaApiClient {
|
|||||||
})
|
})
|
||||||
|
|
||||||
if (!folder) return undefined
|
if (!folder) return undefined
|
||||||
|
|
||||||
return folder
|
return folder
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -952,6 +1020,47 @@ export class SASViyaApiClient {
|
|||||||
return `/folders/folders/${folderDetails.id}`
|
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) {
|
private async getRecycleBinUri(accessToken?: string) {
|
||||||
const url = '/folders/folders/@myRecycleBin'
|
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 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 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(
|
public async listFolder(
|
||||||
sourceFolder: string,
|
sourceFolder: string,
|
||||||
accessToken?: string,
|
accessToken?: string,
|
||||||
limit: number = 20
|
limit: number = 20,
|
||||||
|
options?: {
|
||||||
|
returnDetails?: boolean
|
||||||
|
}
|
||||||
) {
|
) {
|
||||||
// checks if 'sourceFolder' is already a URI
|
// checks if 'sourceFolder' is already a URI
|
||||||
const sourceFolderUri = isUri(sourceFolder)
|
const sourceFolderUri = isUri(sourceFolder)
|
||||||
@@ -1018,11 +1132,20 @@ export class SASViyaApiClient {
|
|||||||
accessToken
|
accessToken
|
||||||
)
|
)
|
||||||
|
|
||||||
|
let membersToReturn = []
|
||||||
|
|
||||||
if (members && members.items) {
|
if (members && members.items) {
|
||||||
return members.items.map((item: any) => item.name)
|
// If returnDetails is true, return full member details
|
||||||
} else {
|
if (options?.returnDetails) {
|
||||||
return []
|
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.
|
* Fetches a folder from the SAS file system.
|
||||||
* @param folderPath - path of the folder to be fetched.
|
* @param folderPath - path of the folder to be fetched.
|
||||||
@@ -436,18 +466,23 @@ export default class SASjs {
|
|||||||
* Lists children folders for given Viya folder.
|
* 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 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 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(
|
public async listFolder(
|
||||||
sourceFolder: string,
|
sourceFolder: string,
|
||||||
accessToken?: string,
|
accessToken?: string,
|
||||||
limit?: number
|
limit?: number,
|
||||||
|
returnDetails = false
|
||||||
) {
|
) {
|
||||||
this.isMethodSupported('listFolder', [ServerType.SasViya])
|
this.isMethodSupported('listFolder', [ServerType.SasViya])
|
||||||
|
|
||||||
return await this.sasViyaApiClient?.listFolder(
|
return await this.sasViyaApiClient?.listFolder(
|
||||||
sourceFolder,
|
sourceFolder,
|
||||||
accessToken,
|
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