mirror of
https://github.com/sasjs/adapter.git
synced 2025-12-11 01:14:36 +00:00
Compare commits
37 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
33a202fa1c | ||
|
|
ff5463a84c | ||
|
|
aa7c3ae4a9 | ||
|
|
2e66bfde4b | ||
|
|
16e21adb20 | ||
|
|
01c5682c3d | ||
|
|
cfc8ff2837 | ||
|
|
edf25b471a | ||
|
|
bb894e6107 | ||
|
|
7bf53858f0 | ||
|
|
02780d0bcd | ||
|
|
6356aed06b | ||
|
|
69fd7b2cb5 | ||
|
|
5d1eed1494 | ||
|
|
e2e2824f37 | ||
|
|
d461135980 | ||
|
|
65fbae7610 | ||
|
|
761428502a | ||
|
|
6eb2ceaf53 | ||
|
|
66813b9824 | ||
|
|
140d8e4eac | ||
|
|
0d730e0576 | ||
|
|
ca18fcecf0 | ||
|
|
009069169f | ||
|
|
6d166efd11 | ||
|
|
1b117a67aa | ||
|
|
9037160362 | ||
|
|
505d85c256 | ||
|
|
71a3fe04a0 | ||
|
|
79bb27524c | ||
|
|
9651b7adb4 | ||
|
|
59e5bec731 | ||
|
|
182e66216f | ||
|
|
2408fd091e | ||
|
|
0e38a24664 | ||
|
|
aa643d1782 | ||
|
|
cdc91e9cda |
2
.env.example
Normal file
2
.env.example
Normal file
@@ -0,0 +1,2 @@
|
||||
SERVER_URL=https://server.com
|
||||
DEFAULT_COMPUTE_CONTEXT=SAS Job Execution compute context
|
||||
9
.github/reviewer-lottery.yml
vendored
Normal file
9
.github/reviewer-lottery.yml
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
groups:
|
||||
- name: SASjs Devs # name of the group
|
||||
reviewers: 1 # how many reviewers do you want to assign?
|
||||
usernames: # github usernames of the reviewers
|
||||
- krishna-acondy
|
||||
- YuryShkoda
|
||||
- saadjutt01
|
||||
- medjedovicm
|
||||
- allanbowe
|
||||
13
.github/workflows/assign-reviewer.yml
vendored
Normal file
13
.github/workflows/assign-reviewer.yml
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
name: 'Assign Reviewer'
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened]
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: uesteibar/reviewer-lottery@v1
|
||||
with:
|
||||
repo-token: ${{ secrets.GH_TOKEN }}
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,2 +1,4 @@
|
||||
node_modules
|
||||
build
|
||||
|
||||
.env
|
||||
@@ -14,5 +14,5 @@ What code changes have been made to achieve the intent.
|
||||
|
||||
- [ ] Code is formatted correctly (`npm run lint:fix`).
|
||||
- [ ] All unit tests are passing (`npm test`).
|
||||
- [ ] All `sasjs-tests` unit tests are passing (`npm test`).
|
||||
- [ ] All `sasjs-cli` unit tests are passing (`npm test`).
|
||||
- [ ] All `sasjs-tests` are passing (instructions available [here](https://github.com/sasjs/adapter/blob/master/sasjs-tests/README.md)).
|
||||
|
||||
File diff suppressed because one or more lines are too long
231
docs/classes/reflection-804.reflection-219.fileuploader.html
Normal file
231
docs/classes/reflection-804.reflection-219.fileuploader.html
Normal file
File diff suppressed because one or more lines are too long
312
docs/classes/reflection-804.reflection-219.sas9apiclient.html
Normal file
312
docs/classes/reflection-804.reflection-219.sas9apiclient.html
Normal file
File diff suppressed because one or more lines are too long
1670
docs/classes/reflection-804.reflection-219.sasjs.html
Normal file
1670
docs/classes/reflection-804.reflection-219.sasjs.html
Normal file
File diff suppressed because one or more lines are too long
1471
docs/classes/reflection-804.reflection-219.sasviyaapiclient.html
Normal file
1471
docs/classes/reflection-804.reflection-219.sasviyaapiclient.html
Normal file
File diff suppressed because one or more lines are too long
323
docs/classes/reflection-804.reflection-219.sessionmanager.html
Normal file
323
docs/classes/reflection-804.reflection-219.sessionmanager.html
Normal file
File diff suppressed because one or more lines are too long
228
docs/classes/root.fileuploader.html
Normal file
228
docs/classes/root.fileuploader.html
Normal file
File diff suppressed because one or more lines are too long
309
docs/classes/root.sas9apiclient.html
Normal file
309
docs/classes/root.sas9apiclient.html
Normal file
File diff suppressed because one or more lines are too long
1673
docs/classes/root.sasjs.html
Normal file
1673
docs/classes/root.sasjs.html
Normal file
File diff suppressed because one or more lines are too long
1480
docs/classes/root.sasviyaapiclient.html
Normal file
1480
docs/classes/root.sasviyaapiclient.html
Normal file
File diff suppressed because one or more lines are too long
357
docs/classes/root.sessionmanager.html
Normal file
357
docs/classes/root.sessionmanager.html
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
215
docs/interfaces/types.polloptions.html
Normal file
215
docs/interfaces/types.polloptions.html
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
197
docs/interfaces/types.sessionvariable.html
Normal file
197
docs/interfaces/types.sessionvariable.html
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
106
docs/modules/reflection-804.html
Normal file
106
docs/modules/reflection-804.html
Normal file
File diff suppressed because one or more lines are too long
128
docs/modules/reflection-804.reflection-219.html
Normal file
128
docs/modules/reflection-804.reflection-219.html
Normal file
File diff suppressed because one or more lines are too long
125
docs/modules/root.html
Normal file
125
docs/modules/root.html
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
4711
package-lock.json
generated
4711
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -2,7 +2,7 @@
|
||||
"name": "@sasjs/adapter",
|
||||
"description": "JavaScript adapter for SAS",
|
||||
"scripts": {
|
||||
"build": "rimraf build && webpack",
|
||||
"build": "rimraf build && rimraf node && mkdir node && cp -r src/* node && webpack && rimraf build/src && rimraf node",
|
||||
"package:lib": "npm run build && cp ./package.json build && cd build && npm version \"5.0.0\" && npm pack",
|
||||
"publish:lib": "npm run build && cd build && npm publish",
|
||||
"lint:fix": "npx prettier --write 'src/**/*.{ts,tsx,js,jsx,html,css,sass,less,json,yml,md,graphql}'",
|
||||
@@ -39,10 +39,11 @@
|
||||
"@types/isomorphic-fetch": "0.0.35",
|
||||
"@types/jest": "^26.0.15",
|
||||
"cp": "^0.2.0",
|
||||
"dotenv": "^8.2.0",
|
||||
"jest": "^25.5.4",
|
||||
"path": "^0.12.7",
|
||||
"rimraf": "^3.0.2",
|
||||
"semantic-release": "^17.2.3",
|
||||
"semantic-release": "^17.3.0",
|
||||
"terser-webpack-plugin": "^4.2.3",
|
||||
"ts-jest": "^25.5.1",
|
||||
"ts-loader": "^8.0.11",
|
||||
@@ -57,6 +58,7 @@
|
||||
},
|
||||
"main": "index.js",
|
||||
"dependencies": {
|
||||
"@sasjs/utils": "^1.5.0",
|
||||
"es6-promise": "^4.2.8",
|
||||
"form-data": "^3.0.0",
|
||||
"isomorphic-fetch": "^2.2.1"
|
||||
|
||||
@@ -25,17 +25,71 @@ export const computeTests = (adapter: SASjs): TestSuite => ({
|
||||
},
|
||||
assertion: (res: any) => {
|
||||
const expectedProperties = ["id", "state", "creationTimeStamp", "jobConditionCode"]
|
||||
return validate(expectedProperties, res);
|
||||
return validate(expectedProperties, res.result);
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "Execute Script Viya - complete job",
|
||||
description: "Should execute sas file and return log",
|
||||
test: () => {
|
||||
const fileLines = [
|
||||
`data;`,
|
||||
`do x=1 to 100;`,
|
||||
`output;`,
|
||||
`end;`,
|
||||
`run;`
|
||||
]
|
||||
|
||||
return adapter.executeScriptSASViya(
|
||||
'sasCode.sas',
|
||||
fileLines,
|
||||
'SAS Studio compute context',
|
||||
undefined,
|
||||
true
|
||||
)
|
||||
},
|
||||
assertion: (res: any) => {
|
||||
const expectedLogContent = `1 data;\\n2 do x=1 to 100;\\n3 output;\\n4 end;\\n5 run;\\n\\n`
|
||||
|
||||
return validateLog(expectedLogContent, res.log);
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "Execute Script Viya - failed job",
|
||||
description: "Should execute sas file and return log",
|
||||
test: () => {
|
||||
const fileLines = [
|
||||
`%abort;`
|
||||
]
|
||||
|
||||
return adapter.executeScriptSASViya(
|
||||
'sasCode.sas',
|
||||
fileLines,
|
||||
'SAS Studio compute context',
|
||||
undefined,
|
||||
true
|
||||
).catch((err: any) => err )
|
||||
},
|
||||
assertion: (res: any) => {
|
||||
const expectedLogContent = `1 %abort;\\nERROR: The %ABORT statement is not valid in open code.\\n`
|
||||
|
||||
return validateLog(expectedLogContent, res.log);
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
const validateLog = (text: string, log: string): boolean => {
|
||||
const isValid = JSON.stringify(log).includes(text)
|
||||
|
||||
return isValid
|
||||
}
|
||||
|
||||
const validate = (expectedProperties: string[], data: any): boolean => {
|
||||
const actualProperties = Object.keys(data);
|
||||
|
||||
const isValid = expectedProperties.every(
|
||||
(property) => actualProperties.includes(property)
|
||||
);
|
||||
return isValid
|
||||
const isValid = expectedProperties.every(
|
||||
(property) => actualProperties.includes(property)
|
||||
);
|
||||
return isValid
|
||||
}
|
||||
@@ -16,11 +16,13 @@ import {
|
||||
Folder,
|
||||
CsrfToken,
|
||||
EditContextInput,
|
||||
ErrorResponse,
|
||||
JobDefinition
|
||||
JobDefinition,
|
||||
PollOptions
|
||||
} from './types'
|
||||
import { formatDataForRequest } from './utils/formatDataForRequest'
|
||||
import { SessionManager } from './SessionManager'
|
||||
import { timestampToYYYYMMDDHHMMSS } from '@sasjs/utils/time'
|
||||
import { Logger, LogLevel } from '@sasjs/utils/logger'
|
||||
|
||||
/**
|
||||
* A client for interfacing with the SAS Viya REST API.
|
||||
@@ -154,6 +156,7 @@ export class SASViyaApiClient {
|
||||
context.name,
|
||||
accessToken,
|
||||
null,
|
||||
false,
|
||||
true,
|
||||
true
|
||||
).catch((err) => err)
|
||||
@@ -164,30 +167,27 @@ export class SASViyaApiClient {
|
||||
for (const promise of promises) results.push(await promise())
|
||||
|
||||
results.forEach((result: any, index: number) => {
|
||||
if (result && result.error && result.error.details) {
|
||||
if (result && result.log) {
|
||||
try {
|
||||
const resultParsed = result.error.details
|
||||
const resultParsed = result.log
|
||||
let sysUserId = ''
|
||||
|
||||
if (resultParsed && resultParsed.body) {
|
||||
let sysUserId = ''
|
||||
const sysUserIdLog = resultParsed
|
||||
.split('\n')
|
||||
.find((line: string) => line.startsWith('SYSUSERID='))
|
||||
|
||||
const sysUserIdLog = resultParsed.body
|
||||
.split('\n')
|
||||
.find((line: string) => line.startsWith('SYSUSERID='))
|
||||
if (sysUserIdLog) {
|
||||
sysUserId = sysUserIdLog.replace('SYSUSERID=', '')
|
||||
|
||||
if (sysUserIdLog) {
|
||||
sysUserId = sysUserIdLog.replace('SYSUSERID=', '')
|
||||
|
||||
executableContexts.push({
|
||||
createdBy: contextsList[index].createdBy,
|
||||
id: contextsList[index].id,
|
||||
name: contextsList[index].name,
|
||||
version: contextsList[index].version,
|
||||
attributes: {
|
||||
sysUserId
|
||||
}
|
||||
})
|
||||
}
|
||||
executableContexts.push({
|
||||
createdBy: contextsList[index].createdBy,
|
||||
id: contextsList[index].id,
|
||||
name: contextsList[index].name,
|
||||
version: contextsList[index].version,
|
||||
attributes: {
|
||||
sysUserId
|
||||
}
|
||||
})
|
||||
}
|
||||
} catch (error) {
|
||||
throw error
|
||||
@@ -430,6 +430,8 @@ export class SASViyaApiClient {
|
||||
* @param debug - when set to true, the log will be returned.
|
||||
* @param expectWebout - when set to true, the automatic _webout fileref will be checked for content, and that content returned. This fileref is used when the Job contains a SASjs web request (as opposed to executing arbitrary SAS code).
|
||||
* @param waitForResult - when set to true, function will return the session
|
||||
* @param pollOptions - an object that represents poll interval(milliseconds) and maximum amount of attempts. Object example: { MAX_POLL_COUNT: 24 * 60 * 60, POLL_INTERVAL: 1000 }.
|
||||
* @param printPid - a boolean that indicates whether the function should print (PID) of the started job.
|
||||
*/
|
||||
public async executeScript(
|
||||
jobPath: string,
|
||||
@@ -439,7 +441,9 @@ export class SASViyaApiClient {
|
||||
data = null,
|
||||
debug: boolean = false,
|
||||
expectWebout = false,
|
||||
waitForResult = true
|
||||
waitForResult = true,
|
||||
pollOptions?: PollOptions,
|
||||
printPid = false
|
||||
): Promise<any> {
|
||||
try {
|
||||
const headers: any = {
|
||||
@@ -459,6 +463,28 @@ export class SASViyaApiClient {
|
||||
|
||||
executionSessionId = session!.id
|
||||
|
||||
if (printPid) {
|
||||
const { result: jobIdVariable } = await this.sessionManager.getVariable(
|
||||
executionSessionId,
|
||||
'SYSJOBID',
|
||||
accessToken
|
||||
)
|
||||
|
||||
if (jobIdVariable && jobIdVariable.value) {
|
||||
const relativeJobPath = this.rootFolderName
|
||||
? jobPath.split(this.rootFolderName).join('').replace(/^\//, '')
|
||||
: jobPath
|
||||
|
||||
const logger = new Logger(debug ? LogLevel.Debug : LogLevel.Info)
|
||||
|
||||
logger.info(
|
||||
`Triggered '${relativeJobPath}' with PID ${
|
||||
jobIdVariable.value
|
||||
} at ${timestampToYYYYMMDDHHMMSS()}`
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const jobArguments: { [key: string]: any } = {
|
||||
_contextName: contextName,
|
||||
_OMITJSONLISTING: true,
|
||||
@@ -545,7 +571,12 @@ export class SASViyaApiClient {
|
||||
)
|
||||
}
|
||||
|
||||
const jobStatus = await this.pollJobState(postedJob, etag, accessToken)
|
||||
const jobStatus = await this.pollJobState(
|
||||
postedJob,
|
||||
etag,
|
||||
accessToken,
|
||||
pollOptions
|
||||
)
|
||||
|
||||
const { result: currentJob } = await this.request<Job>(
|
||||
`${this.serverUrl}/compute/sessions/${executionSessionId}/jobs/${postedJob.id}`,
|
||||
@@ -583,7 +614,7 @@ export class SASViyaApiClient {
|
||||
if (expectWebout) {
|
||||
resultLink = `/compute/sessions/${executionSessionId}/filerefs/_webout/content`
|
||||
} else {
|
||||
return currentJob
|
||||
return { job: currentJob, log }
|
||||
}
|
||||
|
||||
if (resultLink) {
|
||||
@@ -951,6 +982,8 @@ export class SASViyaApiClient {
|
||||
* @param accessToken - an optional access token for an authorized user.
|
||||
* @param waitForResult - a boolean indicating if the function should wait for a result.
|
||||
* @param expectWebout - a boolean indicating whether to expect a _webout response.
|
||||
* @param pollOptions - an object that represents poll interval(milliseconds) and maximum amount of attempts. Object example: { MAX_POLL_COUNT: 24 * 60 * 60, POLL_INTERVAL: 1000 }.
|
||||
* @param printPid - a boolean that indicates whether the function should print (PID) of the started job.
|
||||
*/
|
||||
public async executeComputeJob(
|
||||
sasJob: string,
|
||||
@@ -959,7 +992,9 @@ export class SASViyaApiClient {
|
||||
data?: any,
|
||||
accessToken?: string,
|
||||
waitForResult = true,
|
||||
expectWebout = false
|
||||
expectWebout = false,
|
||||
pollOptions?: PollOptions,
|
||||
printPid = false
|
||||
) {
|
||||
if (isRelativePath(sasJob) && !this.rootFolderName) {
|
||||
throw new Error(
|
||||
@@ -1044,7 +1079,9 @@ export class SASViyaApiClient {
|
||||
data,
|
||||
debug,
|
||||
expectWebout,
|
||||
waitForResult
|
||||
waitForResult,
|
||||
pollOptions,
|
||||
printPid
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1229,7 +1266,7 @@ export class SASViyaApiClient {
|
||||
throw new Error(`The path ${path} does not exist on ${this.serverUrl}`)
|
||||
}
|
||||
const { result: members } = await this.request<{ items: any[] }>(
|
||||
`${this.serverUrl}/folders/folders/${folder.id}/members`,
|
||||
`${this.serverUrl}/folders/folders/${folder.id}/members?limit=${folder.memberCount}`,
|
||||
requestInfo
|
||||
)
|
||||
|
||||
@@ -1237,13 +1274,21 @@ export class SASViyaApiClient {
|
||||
this.folderMap.set(path, itemsAtRoot)
|
||||
}
|
||||
|
||||
// REFACTOR: set default value for 'pollOptions' attribute
|
||||
private async pollJobState(
|
||||
postedJob: any,
|
||||
etag: string | null,
|
||||
accessToken?: string
|
||||
accessToken?: string,
|
||||
pollOptions?: PollOptions
|
||||
) {
|
||||
const MAX_POLL_COUNT = 1000
|
||||
const POLL_INTERVAL = 100
|
||||
let POLL_INTERVAL = 100
|
||||
let MAX_POLL_COUNT = 1000
|
||||
|
||||
if (pollOptions) {
|
||||
POLL_INTERVAL = pollOptions.POLL_INTERVAL || POLL_INTERVAL
|
||||
MAX_POLL_COUNT = pollOptions.MAX_POLL_COUNT || MAX_POLL_COUNT
|
||||
}
|
||||
|
||||
let postedJobState = ''
|
||||
let pollCount = 0
|
||||
const headers: any = {
|
||||
|
||||
27
src/SASjs.ts
27
src/SASjs.ts
@@ -32,7 +32,8 @@ import {
|
||||
CsrfToken,
|
||||
UploadFile,
|
||||
EditContextInput,
|
||||
ErrorResponse
|
||||
ErrorResponse,
|
||||
PollOptions
|
||||
} from './types'
|
||||
import { SASViyaApiClient } from './SASViyaApiClient'
|
||||
import { SAS9ApiClient } from './SAS9ApiClient'
|
||||
@@ -205,11 +206,20 @@ export default class SASjs {
|
||||
return await this.sasViyaApiClient!.createSession(contextName, accessToken)
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the sas code against given sas server
|
||||
* @param fileName - name of the file to run. It will be converted to path to the file being submitted for execution.
|
||||
* @param linesOfCode - lines of sas code from the file to run.
|
||||
* @param contextName - context name on which code will be run on the server.
|
||||
* @param accessToken - (optional) the access token for authorizing the request.
|
||||
* @param debug - (optional) if true, global debug config will be overriden
|
||||
*/
|
||||
public async executeScriptSASViya(
|
||||
fileName: string,
|
||||
linesOfCode: string[],
|
||||
contextName: string,
|
||||
accessToken?: string
|
||||
accessToken?: string,
|
||||
debug?: boolean
|
||||
) {
|
||||
this.isMethodSupported('executeScriptSASViya', ServerType.SASViya)
|
||||
|
||||
@@ -218,7 +228,8 @@ export default class SASjs {
|
||||
linesOfCode,
|
||||
contextName,
|
||||
accessToken,
|
||||
null
|
||||
null,
|
||||
debug ? debug : this.sasjsConfig.debug
|
||||
)
|
||||
}
|
||||
|
||||
@@ -711,13 +722,17 @@ export default class SASjs {
|
||||
* @param accessToken - a valid access token that is authorised to execute compute jobs.
|
||||
* The access token is not required when the user is authenticated via the browser.
|
||||
* @param waitForResult - a boolean that indicates whether the function needs to wait for execution to complete.
|
||||
* @param pollOptions - an object that represents poll interval(milliseconds) and maximum amount of attempts. Object example: { MAX_POLL_COUNT: 24 * 60 * 60, POLL_INTERVAL: 1000 }.
|
||||
* @param printPid - a boolean that indicates whether the function should print (PID) of the started job.
|
||||
*/
|
||||
public async startComputeJob(
|
||||
sasJob: string,
|
||||
data: any,
|
||||
config: any = {},
|
||||
accessToken?: string,
|
||||
waitForResult?: boolean
|
||||
waitForResult?: boolean,
|
||||
pollOptions?: PollOptions,
|
||||
printPid = false
|
||||
) {
|
||||
config = {
|
||||
...this.sasjsConfig,
|
||||
@@ -738,7 +753,9 @@ export default class SASjs {
|
||||
data,
|
||||
accessToken,
|
||||
!!waitForResult,
|
||||
false
|
||||
false,
|
||||
pollOptions,
|
||||
printPid
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { Session, Context, CsrfToken } from './types'
|
||||
import { Session, Context, CsrfToken, SessionVariable } from './types'
|
||||
import { asyncForEach, makeRequest, isUrl } from './utils'
|
||||
import { prefixMessage } from '@sasjs/utils/error'
|
||||
|
||||
const MAX_SESSION_COUNT = 1
|
||||
const RETRY_LIMIT: number = 3
|
||||
@@ -168,7 +169,11 @@ export class SessionManager {
|
||||
const stateLink = session.links.find((l: any) => l.rel === 'state')
|
||||
|
||||
return new Promise(async (resolve, _) => {
|
||||
if (sessionState === 'pending') {
|
||||
if (
|
||||
sessionState === 'pending' ||
|
||||
sessionState === 'running' ||
|
||||
sessionState === ''
|
||||
) {
|
||||
if (stateLink) {
|
||||
if (this.debug) {
|
||||
console.log('Polling session status... \n') // ?
|
||||
@@ -261,4 +266,21 @@ export class SessionManager {
|
||||
throw err
|
||||
})
|
||||
}
|
||||
|
||||
async getVariable(sessionId: string, variable: string, accessToken?: string) {
|
||||
const getSessionVariable = {
|
||||
method: 'GET',
|
||||
headers: this.getHeaders(accessToken)
|
||||
}
|
||||
|
||||
return await this.request<SessionVariable>(
|
||||
`${this.serverUrl}/compute/sessions/${sessionId}/variables/${variable}`,
|
||||
getSessionVariable
|
||||
).catch((err) => {
|
||||
throw prefixMessage(
|
||||
err,
|
||||
`Error while fetching session variable '${variable}'.`
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
53
src/test/SessionManager.spec.ts
Normal file
53
src/test/SessionManager.spec.ts
Normal file
@@ -0,0 +1,53 @@
|
||||
import { SessionManager } from '../SessionManager'
|
||||
import * as dotenv from 'dotenv'
|
||||
|
||||
describe('SessionManager', () => {
|
||||
dotenv.config()
|
||||
|
||||
let originalFetch: any
|
||||
|
||||
const sessionManager = new SessionManager(
|
||||
process.env.SERVER_URL as string,
|
||||
process.env.DEFAULT_COMPUTE_CONTEXT as string,
|
||||
() => {}
|
||||
)
|
||||
|
||||
beforeAll(() => {
|
||||
originalFetch = (global as any).fetch
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
;(global as any).fetch = originalFetch
|
||||
})
|
||||
|
||||
describe('getVariable', () => {
|
||||
it('should fetch session variable', async () => {
|
||||
const sampleResponse = {
|
||||
ok: true,
|
||||
links: [],
|
||||
name: 'SYSJOBID',
|
||||
scope: 'GLOBAL',
|
||||
value: '25218',
|
||||
version: 1
|
||||
}
|
||||
|
||||
;(global as any).fetch = jest.fn().mockImplementation(() =>
|
||||
Promise.resolve({
|
||||
ok: true,
|
||||
headers: { get: () => '' },
|
||||
json: () => Promise.resolve(sampleResponse)
|
||||
})
|
||||
)
|
||||
|
||||
const expectedResponse = { etag: '', result: sampleResponse }
|
||||
|
||||
await expect(
|
||||
sessionManager.getVariable(
|
||||
'fakeSessionId',
|
||||
'SYSJOBID',
|
||||
'fakeAccessToken'
|
||||
)
|
||||
).resolves.toEqual(expectedResponse)
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -4,4 +4,5 @@ export interface Folder {
|
||||
id: string
|
||||
uri: string
|
||||
links: Link[]
|
||||
memberCount: number
|
||||
}
|
||||
|
||||
4
src/types/PollOptions.ts
Normal file
4
src/types/PollOptions.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export interface PollOptions {
|
||||
MAX_POLL_COUNT?: number
|
||||
POLL_INTERVAL?: number
|
||||
}
|
||||
@@ -9,3 +9,7 @@ export interface Session {
|
||||
}
|
||||
creationTimeStamp: string
|
||||
}
|
||||
|
||||
export interface SessionVariable {
|
||||
value: string
|
||||
}
|
||||
|
||||
@@ -12,3 +12,4 @@ export * from './SASjsWaitingRequest'
|
||||
export * from './ServerType'
|
||||
export * from './Session'
|
||||
export * from './UploadFile'
|
||||
export * from './PollOptions'
|
||||
|
||||
@@ -47,6 +47,7 @@ const browserConfig = {
|
||||
const nodeConfig = {
|
||||
...browserConfig,
|
||||
target: 'node',
|
||||
entry: './node/index.ts',
|
||||
output: {
|
||||
...browserConfig.output,
|
||||
path: path.resolve(__dirname, 'build', 'node')
|
||||
|
||||
Reference in New Issue
Block a user