mirror of
https://github.com/sasjs/adapter.git
synced 2026-01-03 10:40:06 +00:00
Compare commits
1 Commits
v3.9.2
...
snyk-upgra
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
28e0e3a147 |
28
package-lock.json
generated
28
package-lock.json
generated
@@ -8,8 +8,8 @@
|
|||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@sasjs/utils": "2.44.0",
|
"@sasjs/utils": "2.40.0",
|
||||||
"axios": "0.26.0",
|
"axios": "^0.26.1",
|
||||||
"axios-cookiejar-support": "1.0.1",
|
"axios-cookiejar-support": "1.0.1",
|
||||||
"form-data": "4.0.0",
|
"form-data": "4.0.0",
|
||||||
"https": "1.0.0",
|
"https": "1.0.0",
|
||||||
@@ -1142,9 +1142,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@sasjs/utils": {
|
"node_modules/@sasjs/utils": {
|
||||||
"version": "2.44.0",
|
"version": "2.40.0",
|
||||||
"resolved": "https://registry.npmjs.org/@sasjs/utils/-/utils-2.44.0.tgz",
|
"resolved": "https://registry.npmjs.org/@sasjs/utils/-/utils-2.40.0.tgz",
|
||||||
"integrity": "sha512-hpC4erHYA8Mcb38mzxFEP0cXehfa0iKeqSW2d9MmxZ9g2qpy0BU6xyZJohN9kOiafXo5H359ndNKsg4DOq5YgA==",
|
"integrity": "sha512-U0y/eqRlvfkMHmKDlr1xmeN+Rask7TnJPuRpOz71P8QpGYTw1M9AyZvzRSk503p4KCJb8ysdcqXyGVLfhuoM+A==",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/fs-extra": "9.0.13",
|
"@types/fs-extra": "9.0.13",
|
||||||
@@ -2189,9 +2189,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/axios": {
|
"node_modules/axios": {
|
||||||
"version": "0.26.0",
|
"version": "0.26.1",
|
||||||
"resolved": "https://registry.npmjs.org/axios/-/axios-0.26.0.tgz",
|
"resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz",
|
||||||
"integrity": "sha512-lKoGLMYtHvFrPVt3r+RBMp9nh34N0M8zEfCWqdWZx6phynIEhQqAdydpyBAAG211zlhX9Rgu08cOamy6XjE5Og==",
|
"integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"follow-redirects": "^1.14.8"
|
"follow-redirects": "^1.14.8"
|
||||||
}
|
}
|
||||||
@@ -13870,9 +13870,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@sasjs/utils": {
|
"@sasjs/utils": {
|
||||||
"version": "2.44.0",
|
"version": "2.40.0",
|
||||||
"resolved": "https://registry.npmjs.org/@sasjs/utils/-/utils-2.44.0.tgz",
|
"resolved": "https://registry.npmjs.org/@sasjs/utils/-/utils-2.40.0.tgz",
|
||||||
"integrity": "sha512-hpC4erHYA8Mcb38mzxFEP0cXehfa0iKeqSW2d9MmxZ9g2qpy0BU6xyZJohN9kOiafXo5H359ndNKsg4DOq5YgA==",
|
"integrity": "sha512-U0y/eqRlvfkMHmKDlr1xmeN+Rask7TnJPuRpOz71P8QpGYTw1M9AyZvzRSk503p4KCJb8ysdcqXyGVLfhuoM+A==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@types/fs-extra": "9.0.13",
|
"@types/fs-extra": "9.0.13",
|
||||||
"@types/prompts": "2.0.13",
|
"@types/prompts": "2.0.13",
|
||||||
@@ -14787,9 +14787,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"axios": {
|
"axios": {
|
||||||
"version": "0.26.0",
|
"version": "0.26.1",
|
||||||
"resolved": "https://registry.npmjs.org/axios/-/axios-0.26.0.tgz",
|
"resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz",
|
||||||
"integrity": "sha512-lKoGLMYtHvFrPVt3r+RBMp9nh34N0M8zEfCWqdWZx6phynIEhQqAdydpyBAAG211zlhX9Rgu08cOamy6XjE5Og==",
|
"integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"follow-redirects": "^1.14.8"
|
"follow-redirects": "^1.14.8"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,8 +72,8 @@
|
|||||||
},
|
},
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@sasjs/utils": "2.44.0",
|
"@sasjs/utils": "2.40.0",
|
||||||
"axios": "0.26.0",
|
"axios": "0.26.1",
|
||||||
"axios-cookiejar-support": "1.0.1",
|
"axios-cookiejar-support": "1.0.1",
|
||||||
"form-data": "4.0.0",
|
"form-data": "4.0.0",
|
||||||
"https": "1.0.0",
|
"https": "1.0.0",
|
||||||
|
|||||||
@@ -84,15 +84,6 @@ parmcards4;
|
|||||||
%webout(CLOSE)
|
%webout(CLOSE)
|
||||||
;;;;
|
;;;;
|
||||||
%mm_createwebservice(path=/Public/app/common,name=sendArr)
|
%mm_createwebservice(path=/Public/app/common,name=sendArr)
|
||||||
parmcards4;
|
|
||||||
data work.macvars;
|
|
||||||
set sashelp.vmacro;
|
|
||||||
run;
|
|
||||||
%webout(OPEN)
|
|
||||||
%webout(OBJ,macvars)
|
|
||||||
%webout(CLOSE)
|
|
||||||
;;;;
|
|
||||||
%mm_createwebservice(path=/Public/app/common,name=sendMacVars)
|
|
||||||
parmcards4;
|
parmcards4;
|
||||||
let he who hath understanding, reckon the number of the beast
|
let he who hath understanding, reckon the number of the beast
|
||||||
;;;;
|
;;;;
|
||||||
@@ -127,6 +118,7 @@ parmcards4;
|
|||||||
%webout(CLOSE)
|
%webout(CLOSE)
|
||||||
;;;;
|
;;;;
|
||||||
%mp_createwebservice(path=/Public/app/common,name=sendObj)
|
%mp_createwebservice(path=/Public/app/common,name=sendObj)
|
||||||
|
filename ft15f001 temp;
|
||||||
parmcards4;
|
parmcards4;
|
||||||
%webout(FETCH)
|
%webout(FETCH)
|
||||||
%webout(OPEN)
|
%webout(OPEN)
|
||||||
@@ -140,15 +132,7 @@ parmcards4;
|
|||||||
%webout(CLOSE)
|
%webout(CLOSE)
|
||||||
;;;;
|
;;;;
|
||||||
%mp_createwebservice(path=/Public/app/common,name=sendArr)
|
%mp_createwebservice(path=/Public/app/common,name=sendArr)
|
||||||
parmcards4;
|
filename ft15f001 temp;
|
||||||
data work.macvars;
|
|
||||||
set sashelp.vmacro;
|
|
||||||
run;
|
|
||||||
%webout(OPEN)
|
|
||||||
%webout(OBJ,macvars)
|
|
||||||
%webout(CLOSE)
|
|
||||||
;;;;
|
|
||||||
%mp_createwebservice(path=/Public/app/common,name=sendMacVars)
|
|
||||||
parmcards4;
|
parmcards4;
|
||||||
If you can keep your head when all about you
|
If you can keep your head when all about you
|
||||||
Are losing theirs and blaming it on you,
|
Are losing theirs and blaming it on you,
|
||||||
|
|||||||
20
sasjs-tests/package-lock.json
generated
20
sasjs-tests/package-lock.json
generated
@@ -2388,11 +2388,11 @@
|
|||||||
"node_modules/@sasjs/adapter": {
|
"node_modules/@sasjs/adapter": {
|
||||||
"version": "5.0.0",
|
"version": "5.0.0",
|
||||||
"resolved": "file:../build/sasjs-adapter-5.0.0.tgz",
|
"resolved": "file:../build/sasjs-adapter-5.0.0.tgz",
|
||||||
"integrity": "sha512-5qtEs9yFuZ4v2UrFGNHeCIr/yZTp7D9He+e+N333qW9mdLJJ8fzRifuur/rFE6bNPqC2bdCjicYkO/yrHR4LQw==",
|
"integrity": "sha512-lbDWueAEnfNlu4OGrc9hBEzT0aoLfAy7eLd2nLHArrF6zukcSGBNhUgOqxIhlz4WeBdf1gt3nk1G7p5X1mrWYQ==",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@sasjs/utils": "2.40.1",
|
"@sasjs/utils": "2.36.1",
|
||||||
"axios": "0.26.0",
|
"axios": "0.26.0",
|
||||||
"axios-cookiejar-support": "1.0.1",
|
"axios-cookiejar-support": "1.0.1",
|
||||||
"form-data": "4.0.0",
|
"form-data": "4.0.0",
|
||||||
@@ -2422,9 +2422,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@sasjs/utils": {
|
"node_modules/@sasjs/utils": {
|
||||||
"version": "2.40.1",
|
"version": "2.36.1",
|
||||||
"resolved": "https://registry.npmjs.org/@sasjs/utils/-/utils-2.40.1.tgz",
|
"resolved": "https://registry.npmjs.org/@sasjs/utils/-/utils-2.36.1.tgz",
|
||||||
"integrity": "sha512-wWYElDH71bSZTdZ5V38743vAnw2EPDhzH7+1s7zxINHpaQWK/qrDldI0vgVFLeGpxVU0D7WPZ/ltG6MoE2obeg==",
|
"integrity": "sha512-JkGUpLOODsvkeU+S25jb9k2WnvzyD2w6cEk7YyQ/byuqKL8xawH91PPWegrVcJlDY8WmqKE4CPcA3d1mM3B3LA==",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/fs-extra": "9.0.13",
|
"@types/fs-extra": "9.0.13",
|
||||||
@@ -20998,9 +20998,9 @@
|
|||||||
},
|
},
|
||||||
"@sasjs/adapter": {
|
"@sasjs/adapter": {
|
||||||
"version": "file:../build/sasjs-adapter-5.0.0.tgz",
|
"version": "file:../build/sasjs-adapter-5.0.0.tgz",
|
||||||
"integrity": "sha512-5qtEs9yFuZ4v2UrFGNHeCIr/yZTp7D9He+e+N333qW9mdLJJ8fzRifuur/rFE6bNPqC2bdCjicYkO/yrHR4LQw==",
|
"integrity": "sha512-lbDWueAEnfNlu4OGrc9hBEzT0aoLfAy7eLd2nLHArrF6zukcSGBNhUgOqxIhlz4WeBdf1gt3nk1G7p5X1mrWYQ==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@sasjs/utils": "2.40.1",
|
"@sasjs/utils": "2.36.1",
|
||||||
"axios": "0.26.0",
|
"axios": "0.26.0",
|
||||||
"axios-cookiejar-support": "1.0.1",
|
"axios-cookiejar-support": "1.0.1",
|
||||||
"form-data": "4.0.0",
|
"form-data": "4.0.0",
|
||||||
@@ -21022,9 +21022,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@sasjs/utils": {
|
"@sasjs/utils": {
|
||||||
"version": "2.40.1",
|
"version": "2.36.1",
|
||||||
"resolved": "https://registry.npmjs.org/@sasjs/utils/-/utils-2.40.1.tgz",
|
"resolved": "https://registry.npmjs.org/@sasjs/utils/-/utils-2.36.1.tgz",
|
||||||
"integrity": "sha512-wWYElDH71bSZTdZ5V38743vAnw2EPDhzH7+1s7zxINHpaQWK/qrDldI0vgVFLeGpxVU0D7WPZ/ltG6MoE2obeg==",
|
"integrity": "sha512-JkGUpLOODsvkeU+S25jb9k2WnvzyD2w6cEk7YyQ/byuqKL8xawH91PPWegrVcJlDY8WmqKE4CPcA3d1mM3B3LA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@types/fs-extra": "9.0.13",
|
"@types/fs-extra": "9.0.13",
|
||||||
"@types/prompts": "2.0.13",
|
"@types/prompts": "2.0.13",
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import { specialCaseTests } from './testSuites/SpecialCases'
|
|||||||
import { sasjsRequestTests } from './testSuites/SasjsRequests'
|
import { sasjsRequestTests } from './testSuites/SasjsRequests'
|
||||||
import '@sasjs/test-framework/dist/index.css'
|
import '@sasjs/test-framework/dist/index.css'
|
||||||
import { computeTests } from './testSuites/Compute'
|
import { computeTests } from './testSuites/Compute'
|
||||||
import { fileUploadTests } from './testSuites/FileUpload'
|
|
||||||
|
|
||||||
const App = (): ReactElement<{}> => {
|
const App = (): ReactElement<{}> => {
|
||||||
const { adapter, config } = useContext(AppContext)
|
const { adapter, config } = useContext(AppContext)
|
||||||
@@ -19,8 +18,7 @@ const App = (): ReactElement<{}> => {
|
|||||||
sendArrTests(adapter),
|
sendArrTests(adapter),
|
||||||
sendObjTests(adapter),
|
sendObjTests(adapter),
|
||||||
specialCaseTests(adapter),
|
specialCaseTests(adapter),
|
||||||
sasjsRequestTests(adapter),
|
sasjsRequestTests(adapter)
|
||||||
fileUploadTests(adapter)
|
|
||||||
]
|
]
|
||||||
|
|
||||||
if (adapter.getSasjsConfig().serverType === 'SASVIYA') {
|
if (adapter.getSasjsConfig().serverType === 'SASVIYA') {
|
||||||
|
|||||||
@@ -1,35 +0,0 @@
|
|||||||
import SASjs from '@sasjs/adapter'
|
|
||||||
import { TestSuite } from '@sasjs/test-framework'
|
|
||||||
|
|
||||||
export const fileUploadTests = (adapter: SASjs): TestSuite => ({
|
|
||||||
name: 'File Upload Tests',
|
|
||||||
tests: [
|
|
||||||
{
|
|
||||||
title: 'Upload File',
|
|
||||||
description: 'Should upload the file to VIYA',
|
|
||||||
test: async () => {
|
|
||||||
let blob: any = new Blob(['test'], { type: 'text/html' })
|
|
||||||
blob['lastModifiedDate'] = ''
|
|
||||||
blob['name'] = 'macvars_testfile'
|
|
||||||
let file = blob
|
|
||||||
|
|
||||||
const filesToUpload = [
|
|
||||||
{
|
|
||||||
file: file,
|
|
||||||
fileName: file.name
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
return adapter.uploadFile('common/sendMacVars', filesToUpload, null)
|
|
||||||
},
|
|
||||||
assertion: (response: any) =>
|
|
||||||
(response.macvars as any[]).findIndex(
|
|
||||||
(el: any) => el.NAME === '_WEBIN_FILE_COUNT' && el.VALUE === '1'
|
|
||||||
) > -1 &&
|
|
||||||
(response.macvars as any[]).findIndex(
|
|
||||||
(el: any) =>
|
|
||||||
el.NAME === '_WEBIN_FILENAME' && el.VALUE === 'macvars_testfile'
|
|
||||||
) > -1
|
|
||||||
}
|
|
||||||
]
|
|
||||||
})
|
|
||||||
@@ -218,7 +218,6 @@ export const sendObjTests = (adapter: SASjs): TestSuite => ({
|
|||||||
const invalidData: any = {
|
const invalidData: any = {
|
||||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: [{ col1: 42 }]
|
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: [{ col1: 42 }]
|
||||||
}
|
}
|
||||||
|
|
||||||
return adapter.request('common/sendObj', invalidData).catch((e) => e)
|
return adapter.request('common/sendObj', invalidData).catch((e) => e)
|
||||||
},
|
},
|
||||||
assertion: (error: any) =>
|
assertion: (error: any) =>
|
||||||
|
|||||||
@@ -11,11 +11,7 @@ import {
|
|||||||
JobDefinition,
|
JobDefinition,
|
||||||
PollOptions
|
PollOptions
|
||||||
} from './types'
|
} from './types'
|
||||||
import {
|
import { JobExecutionError, RootFolderNotFoundError } from './types/errors'
|
||||||
CertificateError,
|
|
||||||
JobExecutionError,
|
|
||||||
RootFolderNotFoundError
|
|
||||||
} from './types/errors'
|
|
||||||
import { SessionManager } from './SessionManager'
|
import { SessionManager } from './SessionManager'
|
||||||
import { ContextManager } from './ContextManager'
|
import { ContextManager } from './ContextManager'
|
||||||
import { SasAuthResponse, MacroVar, AuthConfig } from '@sasjs/utils/types'
|
import { SasAuthResponse, MacroVar, AuthConfig } from '@sasjs/utils/types'
|
||||||
@@ -882,8 +878,7 @@ export class SASViyaApiClient {
|
|||||||
|
|
||||||
const { result: folder } = await this.requestClient
|
const { result: folder } = await this.requestClient
|
||||||
.get<Folder>(`${this.serverUrl}${url}`, accessToken)
|
.get<Folder>(`${this.serverUrl}${url}`, accessToken)
|
||||||
.catch((err) => {
|
.catch(() => {
|
||||||
if (err instanceof CertificateError) throw err
|
|
||||||
return { result: null }
|
return { result: null }
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -904,8 +899,7 @@ export class SASViyaApiClient {
|
|||||||
|
|
||||||
const { result: folder } = await this.requestClient
|
const { result: folder } = await this.requestClient
|
||||||
.get<Folder>(`${this.serverUrl}${url}`, accessToken)
|
.get<Folder>(`${this.serverUrl}${url}`, accessToken)
|
||||||
.catch((err) => {
|
.catch(() => {
|
||||||
if (err instanceof CertificateError) throw err
|
|
||||||
return { result: null }
|
return { result: null }
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
47
src/SASjs.ts
47
src/SASjs.ts
@@ -5,7 +5,8 @@ import {
|
|||||||
EditContextInput,
|
EditContextInput,
|
||||||
PollOptions,
|
PollOptions,
|
||||||
LoginMechanism,
|
LoginMechanism,
|
||||||
ExecutionQuery
|
ExecutionQuery,
|
||||||
|
FileTree
|
||||||
} from './types'
|
} from './types'
|
||||||
import { SASViyaApiClient } from './SASViyaApiClient'
|
import { SASViyaApiClient } from './SASViyaApiClient'
|
||||||
import { SAS9ApiClient } from './SAS9ApiClient'
|
import { SAS9ApiClient } from './SAS9ApiClient'
|
||||||
@@ -17,7 +18,7 @@ import {
|
|||||||
AuthConfig,
|
AuthConfig,
|
||||||
ExtraResponseAttributes,
|
ExtraResponseAttributes,
|
||||||
SasAuthResponse,
|
SasAuthResponse,
|
||||||
ServicePackSASjs
|
StreamConfig
|
||||||
} from '@sasjs/utils/types'
|
} from '@sasjs/utils/types'
|
||||||
import { RequestClient } from './request/RequestClient'
|
import { RequestClient } from './request/RequestClient'
|
||||||
import { SasjsRequestClient } from './request/SasjsRequestClient'
|
import { SasjsRequestClient } from './request/SasjsRequestClient'
|
||||||
@@ -77,7 +78,7 @@ export default class SASjs {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Executes SAS code on a SAS 9 server. Requires a runner to be present in
|
* Executes code against a SAS 9 server. Requires a runner to be present in
|
||||||
* the users home directory in metadata.
|
* the users home directory in metadata.
|
||||||
* @param linesOfCode - lines of sas code from the file to run.
|
* @param linesOfCode - lines of sas code from the file to run.
|
||||||
* @param username - a string representing the username.
|
* @param username - a string representing the username.
|
||||||
@@ -97,17 +98,6 @@ export default class SASjs {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Executes SAS code on a SASJS server
|
|
||||||
* @param code - a string of code from the file to run.
|
|
||||||
* @param authConfig - (optional) a valid client, secret, refresh and access tokens that are authorised to execute scripts.
|
|
||||||
*/
|
|
||||||
public async executeScriptSASjs(code: string, authConfig?: AuthConfig) {
|
|
||||||
this.isMethodSupported('executeScriptSASJS', [ServerType.Sasjs])
|
|
||||||
|
|
||||||
return await this.sasJSApiClient?.executeScript(code, authConfig)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Executes sas code in a SAS Viya compute session.
|
* Executes sas code in a SAS Viya compute session.
|
||||||
* @param fileName - name of the file to run. It will be converted to path to the file being submitted for execution.
|
* @param fileName - name of the file to run. It will be converted to path to the file being submitted for execution.
|
||||||
@@ -899,21 +889,27 @@ export default class SASjs {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates the folders and services at the given location `appLoc` on the given server `serverUrl`.
|
* Creates the folders and services at the given location `appLoc` on the given server `serverUrl`.
|
||||||
* @param dataJson - the JSON specifying the folders and files to be created, can also includes
|
* @param members - the JSON specifying the folders and services to be created.
|
||||||
* appLoc, streamServiceName, streamWebFolder, streamLogo
|
* @param appLoc - the base folder in which to create the new folders and
|
||||||
* @param appLoc - (optional) the base folder in which to create the new folders and
|
* services. If not provided, is taken from SASjsConfig.
|
||||||
* services. If not provided, is taken from SASjsConfig. Precedence will be of appLoc present in dataJson.
|
* @param streamConfig - optional configuration object of StreamConfig for deploying streaming app.
|
||||||
* @param authConfig - (optional) a valid client, secret, refresh and access tokens that are authorised to execute compute jobs.
|
* @param authConfig - a valid client, secret, refresh and access tokens that are authorised to execute compute jobs.
|
||||||
*/
|
*/
|
||||||
public async deployToSASjs(
|
public async deployToSASjs(
|
||||||
dataJson: ServicePackSASjs,
|
members: FileTree,
|
||||||
appLoc?: string,
|
appLoc?: string,
|
||||||
|
streamConfig?: StreamConfig,
|
||||||
authConfig?: AuthConfig
|
authConfig?: AuthConfig
|
||||||
) {
|
) {
|
||||||
if (!appLoc) {
|
if (!appLoc) {
|
||||||
appLoc = this.sasjsConfig.appLoc
|
appLoc = this.sasjsConfig.appLoc
|
||||||
}
|
}
|
||||||
return await this.sasJSApiClient?.deploy(dataJson, appLoc, authConfig)
|
return await this.sasJSApiClient?.deploy(
|
||||||
|
members,
|
||||||
|
appLoc,
|
||||||
|
streamConfig,
|
||||||
|
authConfig
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
public async executeJobSASjs(query: ExecutionQuery) {
|
public async executeJobSASjs(query: ExecutionQuery) {
|
||||||
@@ -1106,8 +1102,13 @@ export default class SASjs {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (this.sasjsConfig.serverType === ServerType.Sasjs) {
|
if (this.sasjsConfig.serverType === ServerType.Sasjs) {
|
||||||
if (!this.sasJSApiClient) {
|
if (this.sasJSApiClient) {
|
||||||
this.sasJSApiClient = new SASjsApiClient(this.requestClient)
|
this.sasJSApiClient.setConfig(this.sasjsConfig.serverUrl)
|
||||||
|
} else {
|
||||||
|
this.sasJSApiClient = new SASjsApiClient(
|
||||||
|
this.sasjsConfig.serverUrl,
|
||||||
|
this.requestClient
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { AuthConfig, ServerType, ServicePackSASjs } from '@sasjs/utils/types'
|
import { AuthConfig, ServerType, StreamConfig } from '@sasjs/utils/types'
|
||||||
import { ExecutionQuery } from './types'
|
import { FileTree, ExecutionQuery } from './types'
|
||||||
import { RequestClient } from './request/RequestClient'
|
import { RequestClient } from './request/RequestClient'
|
||||||
import { getAccessTokenForSasjs } from './auth/getAccessTokenForSasjs'
|
import { getAccessTokenForSasjs } from './auth/getAccessTokenForSasjs'
|
||||||
import { refreshTokensForSasjs } from './auth/refreshTokensForSasjs'
|
import { refreshTokensForSasjs } from './auth/refreshTokensForSasjs'
|
||||||
@@ -8,11 +8,19 @@ import { parseWeboutResponse } from './utils'
|
|||||||
import { getTokens } from './auth/getTokens'
|
import { getTokens } from './auth/getTokens'
|
||||||
|
|
||||||
export class SASjsApiClient {
|
export class SASjsApiClient {
|
||||||
constructor(private requestClient: RequestClient) {}
|
constructor(
|
||||||
|
private serverUrl: string,
|
||||||
|
private requestClient: RequestClient
|
||||||
|
) {}
|
||||||
|
|
||||||
|
public setConfig(serverUrl: string) {
|
||||||
|
if (serverUrl) this.serverUrl = serverUrl
|
||||||
|
}
|
||||||
|
|
||||||
public async deploy(
|
public async deploy(
|
||||||
dataJson: ServicePackSASjs,
|
members: FileTree,
|
||||||
appLoc: string,
|
appLoc: string,
|
||||||
|
streamConfig?: StreamConfig,
|
||||||
authConfig?: AuthConfig
|
authConfig?: AuthConfig
|
||||||
) {
|
) {
|
||||||
let access_token = (authConfig || {}).access_token
|
let access_token = (authConfig || {}).access_token
|
||||||
@@ -23,9 +31,6 @@ export class SASjsApiClient {
|
|||||||
ServerType.Sasjs
|
ServerType.Sasjs
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
dataJson.appLoc = dataJson.appLoc || appLoc
|
|
||||||
|
|
||||||
const { result } = await this.requestClient.post<{
|
const { result } = await this.requestClient.post<{
|
||||||
status: string
|
status: string
|
||||||
message: string
|
message: string
|
||||||
@@ -33,7 +38,13 @@ export class SASjsApiClient {
|
|||||||
example?: {}
|
example?: {}
|
||||||
}>(
|
}>(
|
||||||
'SASjsApi/drive/deploy',
|
'SASjsApi/drive/deploy',
|
||||||
dataJson,
|
{
|
||||||
|
fileTree: members,
|
||||||
|
appLoc: appLoc,
|
||||||
|
streamServiceName: streamConfig?.streamServiceName,
|
||||||
|
streamWebFolder: streamConfig?.streamWebFolder,
|
||||||
|
streamLogo: streamConfig?.streamLogo
|
||||||
|
},
|
||||||
access_token,
|
access_token,
|
||||||
undefined,
|
undefined,
|
||||||
{},
|
{},
|
||||||
@@ -60,39 +71,6 @@ export class SASjsApiClient {
|
|||||||
return Promise.resolve(result)
|
return Promise.resolve(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Executes code on a SASJS server.
|
|
||||||
* @param code - a string of code to execute.
|
|
||||||
* @param authConfig - an object for authentication.
|
|
||||||
*/
|
|
||||||
public async executeScript(code: string, authConfig?: AuthConfig) {
|
|
||||||
let access_token = (authConfig || {}).access_token
|
|
||||||
if (authConfig) {
|
|
||||||
;({ access_token } = await getTokens(
|
|
||||||
this.requestClient,
|
|
||||||
authConfig,
|
|
||||||
ServerType.Sasjs
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
let parsedSasjsServerLog = ''
|
|
||||||
|
|
||||||
await this.requestClient
|
|
||||||
.post('SASjsApi/code/execute', { code }, access_token)
|
|
||||||
.then((res: any) => {
|
|
||||||
if (res.result?.log) {
|
|
||||||
parsedSasjsServerLog = res.result.log
|
|
||||||
.map((logLine: any) => logLine.line)
|
|
||||||
.join('\n')
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
parsedSasjsServerLog = err
|
|
||||||
})
|
|
||||||
|
|
||||||
return parsedSasjsServerLog
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exchanges the auth code for an access token for the given client.
|
* Exchanges the auth code for an access token for the given client.
|
||||||
* @param clientId - the client ID to authenticate with.
|
* @param clientId - the client ID to authenticate with.
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { SasAuthResponse } from '@sasjs/utils/types'
|
import { SasAuthResponse } from '@sasjs/utils/types'
|
||||||
import { prefixMessage } from '@sasjs/utils/error'
|
import { prefixMessage } from '@sasjs/utils/error'
|
||||||
import { RequestClient } from '../request/RequestClient'
|
import { RequestClient } from '../request/RequestClient'
|
||||||
import { CertificateError } from '../types/errors'
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exchanges the auth code for an access token for the given client.
|
* Exchanges the auth code for an access token for the given client.
|
||||||
@@ -37,7 +36,6 @@ export async function getAccessTokenForViya(
|
|||||||
.post(url, data, undefined, 'application/x-www-form-urlencoded', headers)
|
.post(url, data, undefined, 'application/x-www-form-urlencoded', headers)
|
||||||
.then((res) => res.result as SasAuthResponse)
|
.then((res) => res.result as SasAuthResponse)
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
if (err instanceof CertificateError) throw err
|
|
||||||
throw prefixMessage(err, 'Error while getting access token. ')
|
throw prefixMessage(err, 'Error while getting access token. ')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -99,20 +99,7 @@ export class FileUploader extends BaseJobExecutor {
|
|||||||
? parseWeboutResponse(res.result, uploadUrl)
|
? parseWeboutResponse(res.result, uploadUrl)
|
||||||
: res.result
|
: res.result
|
||||||
break
|
break
|
||||||
case ServerType.Sasjs:
|
|
||||||
if (typeof res.result._webout === 'object') {
|
|
||||||
jsonResponse = res.result._webout
|
|
||||||
} else {
|
|
||||||
const webout = parseWeboutResponse(
|
|
||||||
res.result._webout,
|
|
||||||
uploadUrl
|
|
||||||
)
|
|
||||||
jsonResponse = getValidJson(webout)
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
} else if (this.serverType === ServerType.Sasjs) {
|
|
||||||
jsonResponse = getValidJson(res.result._webout)
|
|
||||||
} else {
|
} else {
|
||||||
jsonResponse =
|
jsonResponse =
|
||||||
typeof res.result === 'string'
|
typeof res.result === 'string'
|
||||||
|
|||||||
@@ -7,8 +7,7 @@ import {
|
|||||||
LoginRequiredError,
|
LoginRequiredError,
|
||||||
NotFoundError,
|
NotFoundError,
|
||||||
InternalServerError,
|
InternalServerError,
|
||||||
JobExecutionError,
|
JobExecutionError
|
||||||
CertificateError
|
|
||||||
} from '../types/errors'
|
} from '../types/errors'
|
||||||
import { SASjsRequest } from '../types'
|
import { SASjsRequest } from '../types'
|
||||||
import { parseWeboutResponse } from '../utils/parseWeboutResponse'
|
import { parseWeboutResponse } from '../utils/parseWeboutResponse'
|
||||||
@@ -132,26 +131,6 @@ export class RequestClient implements HttpClient {
|
|||||||
} else {
|
} else {
|
||||||
sasWork = response.log
|
sasWork = response.log
|
||||||
}
|
}
|
||||||
} else if (response?.result?.log) {
|
|
||||||
//In this scenario we know we got the response from SASJS server
|
|
||||||
//Log is array of `{ line: '' }` so we need to convert it back to text
|
|
||||||
//To be able to parse it with current functions.
|
|
||||||
let log: string = ''
|
|
||||||
|
|
||||||
if (typeof log !== 'string') {
|
|
||||||
log = response.result.log
|
|
||||||
.map((logLine: any) => logLine.line)
|
|
||||||
.join('\n')
|
|
||||||
}
|
|
||||||
|
|
||||||
sourceCode = parseSourceCode(log)
|
|
||||||
generatedCode = parseGeneratedCode(log)
|
|
||||||
|
|
||||||
if (response?.result?._webout) {
|
|
||||||
sasWork = response.result._webout.WORK
|
|
||||||
} else {
|
|
||||||
sasWork = log
|
|
||||||
}
|
|
||||||
} else if (response?.result) {
|
} else if (response?.result) {
|
||||||
sourceCode = parseSourceCode(response.result)
|
sourceCode = parseSourceCode(response.result)
|
||||||
generatedCode = parseGeneratedCode(response.result)
|
generatedCode = parseGeneratedCode(response.result)
|
||||||
@@ -518,10 +497,6 @@ export class RequestClient implements HttpClient {
|
|||||||
else return
|
else return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (e.isAxiosError && e.code === 'UNABLE_TO_VERIFY_LEAF_SIGNATURE') {
|
|
||||||
throw new CertificateError(e.message)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (e.message) throw e
|
if (e.message) throw e
|
||||||
else throw prefixMessage(e, 'Error while handling error. ')
|
else throw prefixMessage(e, 'Error while handling error. ')
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ describe('formatDataForRequest', () => {
|
|||||||
|
|
||||||
expect(() => formatDataForRequest(tableWithMissingValues)).toThrow(
|
expect(() => formatDataForRequest(tableWithMissingValues)).toThrow(
|
||||||
new Error(
|
new Error(
|
||||||
`A Special missing value can only be a single character from 'A' to 'Z', '_', '.[a-z]', '._'`
|
'Special missing value can only be a single character from A to Z or _'
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|||||||
47
src/types/FileTree.ts
Normal file
47
src/types/FileTree.ts
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
export interface FileTree {
|
||||||
|
members: [FolderMember, ServiceMember]
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum MemberType {
|
||||||
|
folder = 'folder',
|
||||||
|
service = 'service'
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface FolderMember {
|
||||||
|
name: string
|
||||||
|
type: MemberType.folder
|
||||||
|
members: [FolderMember, ServiceMember]
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ServiceMember {
|
||||||
|
name: string
|
||||||
|
type: MemberType.service
|
||||||
|
code: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export const isFileTree = (arg: any): arg is FileTree =>
|
||||||
|
arg &&
|
||||||
|
arg.members &&
|
||||||
|
Array.isArray(arg.members) &&
|
||||||
|
arg.members.filter(
|
||||||
|
(member: FolderMember | ServiceMember) =>
|
||||||
|
!isFolderMember(member) && !isServiceMember(member)
|
||||||
|
).length === 0
|
||||||
|
|
||||||
|
const isFolderMember = (arg: any): arg is FolderMember =>
|
||||||
|
arg &&
|
||||||
|
typeof arg.name === 'string' &&
|
||||||
|
arg.type === MemberType.folder &&
|
||||||
|
arg.members &&
|
||||||
|
Array.isArray(arg.members) &&
|
||||||
|
arg.members.filter(
|
||||||
|
(member: FolderMember | ServiceMember) =>
|
||||||
|
!isFolderMember(member) && !isServiceMember(member)
|
||||||
|
).length === 0
|
||||||
|
|
||||||
|
const isServiceMember = (arg: any): arg is ServiceMember =>
|
||||||
|
arg &&
|
||||||
|
typeof arg.name === 'string' &&
|
||||||
|
arg.type === MemberType.service &&
|
||||||
|
arg.code &&
|
||||||
|
typeof arg.code === 'string'
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
const instructionsToFix =
|
|
||||||
'https://github.com/sasjs/cli/issues/1181#issuecomment-1090638584'
|
|
||||||
|
|
||||||
export class CertificateError extends Error {
|
|
||||||
constructor(message: string) {
|
|
||||||
super(
|
|
||||||
`${message}\nPlease visit the link below for further information on this issue:\n- ${instructionsToFix}\n`
|
|
||||||
)
|
|
||||||
this.name = 'CertificateError'
|
|
||||||
Object.setPrototypeOf(this, CertificateError.prototype)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,14 +1,13 @@
|
|||||||
export * from './AuthorizeError'
|
export * from './AuthorizeError'
|
||||||
export * from './CertificateError'
|
|
||||||
export * from './ComputeJobExecutionError'
|
export * from './ComputeJobExecutionError'
|
||||||
export * from './ErrorResponse'
|
|
||||||
export * from './InternalServerError'
|
export * from './InternalServerError'
|
||||||
export * from './InvalidJsonError'
|
|
||||||
export * from './JobExecutionError'
|
export * from './JobExecutionError'
|
||||||
export * from './JobStatePollError'
|
export * from './JobStatePollError'
|
||||||
export * from './JsonParseArrayError'
|
|
||||||
export * from './LoginRequiredError'
|
export * from './LoginRequiredError'
|
||||||
export * from './NoSessionStateError'
|
|
||||||
export * from './NotFoundError'
|
export * from './NotFoundError'
|
||||||
|
export * from './ErrorResponse'
|
||||||
|
export * from './NoSessionStateError'
|
||||||
export * from './RootFolderNotFoundError'
|
export * from './RootFolderNotFoundError'
|
||||||
|
export * from './JsonParseArrayError'
|
||||||
export * from './WeboutResponseError'
|
export * from './WeboutResponseError'
|
||||||
|
export * from './InvalidJsonError'
|
||||||
|
|||||||
@@ -12,4 +12,5 @@ export * from './Session'
|
|||||||
export * from './UploadFile'
|
export * from './UploadFile'
|
||||||
export * from './PollOptions'
|
export * from './PollOptions'
|
||||||
export * from './WriteStream'
|
export * from './WriteStream'
|
||||||
|
export * from './FileTree'
|
||||||
export * from './ExecuteScript'
|
export * from './ExecuteScript'
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
import { isSpecialMissing } from '@sasjs/utils'
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts the given JSON object array to a CSV string.
|
* Converts the given JSON object array to a CSV string.
|
||||||
* @param data - the array of JSON objects to convert.
|
* @param data - the array of JSON objects to convert.
|
||||||
@@ -20,6 +18,7 @@ export const convertToCSV = (
|
|||||||
let headers: string[] = []
|
let headers: string[] = []
|
||||||
let csvTest
|
let csvTest
|
||||||
let invalidString = false
|
let invalidString = false
|
||||||
|
const specialMissingValueRegExp = /^[a-z_]{1}$/i
|
||||||
|
|
||||||
if (formats) {
|
if (formats) {
|
||||||
headers = Object.keys(formats).map((key) => `${key}:${formats![key]}`)
|
headers = Object.keys(formats).map((key) => `${key}:${formats![key]}`)
|
||||||
@@ -37,7 +36,7 @@ export const convertToCSV = (
|
|||||||
hasNullOrNumber = true
|
hasNullOrNumber = true
|
||||||
} else if (
|
} else if (
|
||||||
typeof row[field] === 'string' &&
|
typeof row[field] === 'string' &&
|
||||||
isSpecialMissing(row[field])
|
specialMissingValueRegExp.test(row[field])
|
||||||
) {
|
) {
|
||||||
hasSpecialMissingString = true
|
hasSpecialMissingString = true
|
||||||
}
|
}
|
||||||
@@ -131,10 +130,10 @@ export const convertToCSV = (
|
|||||||
value = currentCell === null ? '' : currentCell
|
value = currentCell === null ? '' : currentCell
|
||||||
|
|
||||||
if (formats && formats[fieldName] === 'best.') {
|
if (formats && formats[fieldName] === 'best.') {
|
||||||
if (value && !isSpecialMissing(value)) {
|
if (value && !specialMissingValueRegExp.test(value)) {
|
||||||
console.log(`🤖[value]🤖`, value)
|
console.log(`🤖[value]🤖`, value)
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`A Special missing value can only be a single character from 'A' to 'Z', '_', '.[a-z]', '._'`
|
'Special missing value can only be a single character from A to Z or _'
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,15 +16,10 @@ export const parseSasViyaDebugResponse = async (
|
|||||||
requestClient: RequestClient,
|
requestClient: RequestClient,
|
||||||
serverUrl: string
|
serverUrl: string
|
||||||
) => {
|
) => {
|
||||||
// On viya 3.5, iframe is like <iframe style="width: 99%; height: 500px" src="..."></iframe>
|
|
||||||
// On viya 4, iframe is like <iframe style="width: 99%; height: 500px; background-color:Canvas;" src=...></iframe>
|
|
||||||
|
|
||||||
const iframeStart = response.split(
|
const iframeStart = response.split(
|
||||||
/<iframe style="width: 99%; height: 500px" src="|<iframe style="width: 99%; height: 500px; background-color:Canvas;" src=/
|
'<iframe style="width: 99%; height: 500px" src="'
|
||||||
)[1]
|
)[1]
|
||||||
const jsonUrl = iframeStart
|
const jsonUrl = iframeStart ? iframeStart.split('"></iframe>')[0] : null
|
||||||
? iframeStart.split(/"><\/iframe>|><\/iframe>/)[0]
|
|
||||||
: null
|
|
||||||
if (!jsonUrl) {
|
if (!jsonUrl) {
|
||||||
throw new Error('Unable to find webout file URL.')
|
throw new Error('Unable to find webout file URL.')
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user