1
0
mirror of https://github.com/sasjs/adapter.git synced 2026-01-04 03:00:05 +00:00

Compare commits

..

24 Commits

Author SHA1 Message Date
Allan Bowe
8ea621ac98 Merge pull request #687 from sasjs/issue-686
fix: file upload on SASJS SERVER
2022-04-04 12:37:29 +03:00
ea61119919 chore(git): Merge branch 'master' into issue-686 2022-03-31 15:09:21 +02:00
Allan Bowe
01235616a0 Merge pull request #690 from sasjs/issue-689
fix: update code for extracting JSON URL on viya4 when debug is enabled
2022-03-31 15:54:20 +03:00
Muhammad Saad
10051cb7d1 Merge pull request #692 from sasjs/deploy-to-sasjs-server
fix(deploy): to SASJS with complete JSON object
2022-03-31 17:18:17 +05:00
Saad Jutt
7b0ad2d60d chore: sasjs/utils version bump 2022-03-31 16:39:46 +05:00
Saad Jutt
fc0a450e94 fix(deploy): to SASJS with complete JSON object 2022-03-31 04:20:49 +05:00
6cab245cde fix: update code for extracting json url when debug is enabled 2022-03-30 01:22:03 +05:00
ed90cd8036 chore: uploadFile test added 2022-03-28 17:32:30 +02:00
Allan Bowe
784bab4522 fix: adding README for new sendMacVars service 2022-03-28 12:30:01 +00:00
Allan Bowe
ee97e8211e Merge pull request #685 from sasjs/issue-684
fix: blob is not defined
2022-03-28 14:26:58 +03:00
b0eb8b07a8 style: lint 2022-03-25 18:11:20 +01:00
1d1ef7179e fix: file upload on SASJS SERVER
Also fixed appendRequest when debug on while on SASJS SERVER
2022-03-25 18:05:47 +01:00
d0eb1a7bfb fix: should not create blob in node 2022-03-24 02:43:14 +05:00
Allan Bowe
256e4ef314 Merge pull request #681 from sasjs/sasjs-deploy-with-streaming-app
feat(deploy): stream app deployment on SASJS server
2022-03-21 23:54:40 +02:00
Saad Jutt
6a6dfc5e9d chore: corrected authorised in SASjs.ts only 2022-03-22 02:49:46 +05:00
Saad Jutt
5140848039 chore: sasjs deploy return template type 2022-03-22 02:38:20 +05:00
Saad Jutt
31baf01d3e feat(deploy): stream app deployment on SASJS server 2022-03-22 01:18:02 +05:00
Allan Bowe
804e78cf0c Merge pull request #678 from sasjs/issue-677
fix: return requestPromise from sas9JobExecutor
2022-03-11 12:54:17 +02:00
f6a621fe46 chore: update comments 2022-03-11 14:22:45 +05:00
c47d0c9789 fix: return requestPromise from sas9JobExecutor #677 2022-03-11 14:16:44 +05:00
Allan Bowe
1ddc71b017 Create CNAME 2022-03-10 12:08:46 +00:00
Allan Bowe
3e507885ab Merge pull request #676 from sasjs/issue-675
fix: no need to stringify res/err in sas9JobExecutor before appending…
2022-03-10 14:06:50 +02:00
e92d0d73b5 chore: add comments 2022-03-10 16:17:09 +05:00
00a99e752c fix: no need to stringify res/err in sas9JobExecutor before appending request #675 2022-03-10 15:44:38 +05:00
17 changed files with 183 additions and 144 deletions

1
docs/CNAME Normal file
View File

@@ -0,0 +1 @@
adapter.sasjs.io

14
package-lock.json generated
View File

@@ -8,7 +8,7 @@
"hasInstallScript": true, "hasInstallScript": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"@sasjs/utils": "2.36.1", "@sasjs/utils": "2.42.0",
"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",
@@ -1142,9 +1142,9 @@
} }
}, },
"node_modules/@sasjs/utils": { "node_modules/@sasjs/utils": {
"version": "2.36.1", "version": "2.42.0",
"resolved": "https://registry.npmjs.org/@sasjs/utils/-/utils-2.36.1.tgz", "resolved": "https://registry.npmjs.org/@sasjs/utils/-/utils-2.42.0.tgz",
"integrity": "sha512-JkGUpLOODsvkeU+S25jb9k2WnvzyD2w6cEk7YyQ/byuqKL8xawH91PPWegrVcJlDY8WmqKE4CPcA3d1mM3B3LA==", "integrity": "sha512-Y69l89PYNF/h9xvVH72om/39xA+cY80bhiVLzp/fJb3BlvzCf4RNswBBanUOv2I5JNa7gPpJuE7mEiXOlhD3eg==",
"hasInstallScript": true, "hasInstallScript": true,
"dependencies": { "dependencies": {
"@types/fs-extra": "9.0.13", "@types/fs-extra": "9.0.13",
@@ -13870,9 +13870,9 @@
} }
}, },
"@sasjs/utils": { "@sasjs/utils": {
"version": "2.36.1", "version": "2.42.0",
"resolved": "https://registry.npmjs.org/@sasjs/utils/-/utils-2.36.1.tgz", "resolved": "https://registry.npmjs.org/@sasjs/utils/-/utils-2.42.0.tgz",
"integrity": "sha512-JkGUpLOODsvkeU+S25jb9k2WnvzyD2w6cEk7YyQ/byuqKL8xawH91PPWegrVcJlDY8WmqKE4CPcA3d1mM3B3LA==", "integrity": "sha512-Y69l89PYNF/h9xvVH72om/39xA+cY80bhiVLzp/fJb3BlvzCf4RNswBBanUOv2I5JNa7gPpJuE7mEiXOlhD3eg==",
"requires": { "requires": {
"@types/fs-extra": "9.0.13", "@types/fs-extra": "9.0.13",
"@types/prompts": "2.0.13", "@types/prompts": "2.0.13",

View File

@@ -72,7 +72,7 @@
}, },
"main": "index.js", "main": "index.js",
"dependencies": { "dependencies": {
"@sasjs/utils": "2.36.1", "@sasjs/utils": "2.42.0",
"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",

View File

@@ -84,6 +84,15 @@ 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
;;;; ;;;;
@@ -118,7 +127,6 @@ 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)
@@ -132,7 +140,15 @@ parmcards4;
%webout(CLOSE) %webout(CLOSE)
;;;; ;;;;
%mp_createwebservice(path=/Public/app/common,name=sendArr) %mp_createwebservice(path=/Public/app/common,name=sendArr)
filename ft15f001 temp; parmcards4;
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,

View File

@@ -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-lbDWueAEnfNlu4OGrc9hBEzT0aoLfAy7eLd2nLHArrF6zukcSGBNhUgOqxIhlz4WeBdf1gt3nk1G7p5X1mrWYQ==", "integrity": "sha512-5qtEs9yFuZ4v2UrFGNHeCIr/yZTp7D9He+e+N333qW9mdLJJ8fzRifuur/rFE6bNPqC2bdCjicYkO/yrHR4LQw==",
"hasInstallScript": true, "hasInstallScript": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"@sasjs/utils": "2.36.1", "@sasjs/utils": "2.40.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.36.1", "version": "2.40.1",
"resolved": "https://registry.npmjs.org/@sasjs/utils/-/utils-2.36.1.tgz", "resolved": "https://registry.npmjs.org/@sasjs/utils/-/utils-2.40.1.tgz",
"integrity": "sha512-JkGUpLOODsvkeU+S25jb9k2WnvzyD2w6cEk7YyQ/byuqKL8xawH91PPWegrVcJlDY8WmqKE4CPcA3d1mM3B3LA==", "integrity": "sha512-wWYElDH71bSZTdZ5V38743vAnw2EPDhzH7+1s7zxINHpaQWK/qrDldI0vgVFLeGpxVU0D7WPZ/ltG6MoE2obeg==",
"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-lbDWueAEnfNlu4OGrc9hBEzT0aoLfAy7eLd2nLHArrF6zukcSGBNhUgOqxIhlz4WeBdf1gt3nk1G7p5X1mrWYQ==", "integrity": "sha512-5qtEs9yFuZ4v2UrFGNHeCIr/yZTp7D9He+e+N333qW9mdLJJ8fzRifuur/rFE6bNPqC2bdCjicYkO/yrHR4LQw==",
"requires": { "requires": {
"@sasjs/utils": "2.36.1", "@sasjs/utils": "2.40.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.36.1", "version": "2.40.1",
"resolved": "https://registry.npmjs.org/@sasjs/utils/-/utils-2.36.1.tgz", "resolved": "https://registry.npmjs.org/@sasjs/utils/-/utils-2.40.1.tgz",
"integrity": "sha512-JkGUpLOODsvkeU+S25jb9k2WnvzyD2w6cEk7YyQ/byuqKL8xawH91PPWegrVcJlDY8WmqKE4CPcA3d1mM3B3LA==", "integrity": "sha512-wWYElDH71bSZTdZ5V38743vAnw2EPDhzH7+1s7zxINHpaQWK/qrDldI0vgVFLeGpxVU0D7WPZ/ltG6MoE2obeg==",
"requires": { "requires": {
"@types/fs-extra": "9.0.13", "@types/fs-extra": "9.0.13",
"@types/prompts": "2.0.13", "@types/prompts": "2.0.13",

View File

@@ -6,6 +6,7 @@ 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)
@@ -18,7 +19,8 @@ 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') {

View File

@@ -0,0 +1,35 @@
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
}
]
})

View File

@@ -218,6 +218,7 @@ 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) =>

View File

@@ -5,8 +5,7 @@ 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 +16,8 @@ import {
MacroVar, MacroVar,
AuthConfig, AuthConfig,
ExtraResponseAttributes, ExtraResponseAttributes,
SasAuthResponse SasAuthResponse,
ServicePackSASjs
} 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'
@@ -134,7 +134,7 @@ export default class SASjs {
/** /**
* Gets compute contexts. * Gets compute contexts.
* @param accessToken - an access token for an authorized user. * @param accessToken - an access token for an authorised user.
*/ */
public async getComputeContexts(accessToken: string) { public async getComputeContexts(accessToken: string) {
this.isMethodSupported('getComputeContexts', [ServerType.SasViya]) this.isMethodSupported('getComputeContexts', [ServerType.SasViya])
@@ -144,7 +144,7 @@ export default class SASjs {
/** /**
* Gets launcher contexts. * Gets launcher contexts.
* @param accessToken - an access token for an authorized user. * @param accessToken - an access token for an authorised user.
*/ */
public async getLauncherContexts(accessToken: string) { public async getLauncherContexts(accessToken: string) {
this.isMethodSupported('getLauncherContexts', [ServerType.SasViya]) this.isMethodSupported('getLauncherContexts', [ServerType.SasViya])
@@ -163,7 +163,7 @@ export default class SASjs {
/** /**
* Gets executable compute contexts. * Gets executable compute contexts.
* @param authConfig - an access token, refresh token, client and secret for an authorized user. * @param authConfig - an access token, refresh token, client and secret for an authorised user.
*/ */
public async getExecutableContexts(authConfig: AuthConfig) { public async getExecutableContexts(authConfig: AuthConfig) {
this.isMethodSupported('getExecutableContexts', [ServerType.SasViya]) this.isMethodSupported('getExecutableContexts', [ServerType.SasViya])
@@ -177,8 +177,8 @@ export default class SASjs {
* @param launchContextName - the name of the launcher context used by the compute service. * @param launchContextName - the name of the launcher context used by the compute service.
* @param sharedAccountId - the ID of the account to run the servers for this context as. * @param sharedAccountId - the ID of the account to run the servers for this context as.
* @param autoExecLines - the lines of code to execute during session initialization. * @param autoExecLines - the lines of code to execute during session initialization.
* @param accessToken - an access token for an authorized user. * @param accessToken - an access token for an authorised user.
* @param authorizedUsers - an optional list of authorized user IDs. * @param authorisedUsers - an optional list of authorised user IDs.
*/ */
public async createComputeContext( public async createComputeContext(
contextName: string, contextName: string,
@@ -186,7 +186,7 @@ export default class SASjs {
sharedAccountId: string, sharedAccountId: string,
autoExecLines: string[], autoExecLines: string[],
accessToken: string, accessToken: string,
authorizedUsers?: string[] authorisedUsers?: string[]
) { ) {
this.isMethodSupported('createComputeContext', [ServerType.SasViya]) this.isMethodSupported('createComputeContext', [ServerType.SasViya])
@@ -196,7 +196,7 @@ export default class SASjs {
sharedAccountId, sharedAccountId,
autoExecLines, autoExecLines,
accessToken, accessToken,
authorizedUsers authorisedUsers
) )
} }
@@ -205,7 +205,7 @@ export default class SASjs {
* @param contextName - the name of the context to be created. * @param contextName - the name of the context to be created.
* @param description - the description of the context to be created. * @param description - the description of the context to be created.
* @param launchType - launch type of the context to be created. * @param launchType - launch type of the context to be created.
* @param accessToken - an access token for an authorized user. * @param accessToken - an access token for an authorised user.
*/ */
public async createLauncherContext( public async createLauncherContext(
contextName: string, contextName: string,
@@ -227,7 +227,7 @@ export default class SASjs {
* Updates a compute context on the given server. * Updates a compute context on the given server.
* @param contextName - the original name of the context to be deleted. * @param contextName - the original name of the context to be deleted.
* @param editedContext - an object with the properties to be updated. * @param editedContext - an object with the properties to be updated.
* @param accessToken - an access token for an authorized user. * @param accessToken - an access token for an authorised user.
*/ */
public async editComputeContext( public async editComputeContext(
contextName: string, contextName: string,
@@ -246,7 +246,7 @@ export default class SASjs {
/** /**
* Deletes a compute context on the given server. * Deletes a compute context on the given server.
* @param contextName - the name of the context to be deleted. * @param contextName - the name of the context to be deleted.
* @param accessToken - an access token for an authorized user. * @param accessToken - an access token for an authorised user.
*/ */
public async deleteComputeContext(contextName: string, accessToken?: string) { public async deleteComputeContext(contextName: string, accessToken?: string) {
this.isMethodSupported('deleteComputeContext', [ServerType.SasViya]) this.isMethodSupported('deleteComputeContext', [ServerType.SasViya])
@@ -261,7 +261,7 @@ export default class SASjs {
* Returns a JSON representation of a compute context. * Returns a JSON representation of a compute context.
* @example: { "createdBy": "admin", "links": [...], "id": "ID", "version": 2, "name": "context1" } * @example: { "createdBy": "admin", "links": [...], "id": "ID", "version": 2, "name": "context1" }
* @param contextName - the name of the context to return. * @param contextName - the name of the context to return.
* @param accessToken - an access token for an authorized user. * @param accessToken - an access token for an authorised user.
*/ */
public async getComputeContextByName( public async getComputeContextByName(
contextName: string, contextName: string,
@@ -278,7 +278,7 @@ export default class SASjs {
/** /**
* Returns a JSON representation of a compute context. * Returns a JSON representation of a compute context.
* @param contextId - an id of the context to return. * @param contextId - an id of the context to return.
* @param accessToken - an access token for an authorized user. * @param accessToken - an access token for an authorised user.
*/ */
public async getComputeContextById(contextId: string, accessToken?: string) { public async getComputeContextById(contextId: string, accessToken?: string) {
this.isMethodSupported('getComputeContextById', [ServerType.SasViya]) this.isMethodSupported('getComputeContextById', [ServerType.SasViya])
@@ -888,20 +888,21 @@ 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 members - the JSON specifying the folders and services to be created. * @param dataJson - the JSON specifying the folders and files to be created, can also includes
* @param appLoc - the base folder in which to create the new folders and * appLoc, streamServiceName, streamWebFolder, streamLogo
* services. If not provided, is taken from SASjsConfig. * @param appLoc - (optional) the base folder in which to create the new folders and
* @param authConfig - a valid client, secret, refresh and access tokens that are authorised to execute compute jobs. * services. If not provided, is taken from SASjsConfig. Precedence will be of appLoc present in dataJson.
* @param authConfig - (optional) a valid client, secret, refresh and access tokens that are authorised to execute compute jobs.
*/ */
public async deployToSASjs( public async deployToSASjs(
members: FileTree, dataJson: ServicePackSASjs,
appLoc?: string, appLoc?: string,
authConfig?: AuthConfig authConfig?: AuthConfig
) { ) {
if (!appLoc) { if (!appLoc) {
appLoc = this.sasjsConfig.appLoc appLoc = this.sasjsConfig.appLoc
} }
return await this.sasJSApiClient?.deploy(members, appLoc, authConfig) return await this.sasJSApiClient?.deploy(dataJson, appLoc, authConfig)
} }
public async executeJobSASjs(query: ExecutionQuery) { public async executeJobSASjs(query: ExecutionQuery) {
@@ -972,7 +973,7 @@ export default class SASjs {
/** /**
* Fetches content of the log file * Fetches content of the log file
* @param logUrl - url of the log file. * @param logUrl - url of the log file.
* @param accessToken - an access token for an authorized user. * @param accessToken - an access token for an authorised user.
*/ */
public async fetchLogFileContent(logUrl: string, accessToken?: string) { public async fetchLogFileContent(logUrl: string, accessToken?: string) {
return await this.requestClient!.get(logUrl, accessToken).then((res) => { return await this.requestClient!.get(logUrl, accessToken).then((res) => {
@@ -1094,13 +1095,8 @@ export default class SASjs {
} }
if (this.sasjsConfig.serverType === ServerType.Sasjs) { if (this.sasjsConfig.serverType === ServerType.Sasjs) {
if (this.sasJSApiClient) { if (!this.sasJSApiClient) {
this.sasJSApiClient.setConfig(this.sasjsConfig.serverUrl) this.sasJSApiClient = new SASjsApiClient(this.requestClient)
} else {
this.sasJSApiClient = new SASjsApiClient(
this.sasjsConfig.serverUrl,
this.requestClient
)
} }
} }

View File

@@ -1,5 +1,5 @@
import { AuthConfig, ServerType } from '@sasjs/utils/types' import { AuthConfig, ServerType, ServicePackSASjs } from '@sasjs/utils/types'
import { FileTree, ExecutionQuery } from './types' import { 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,17 +8,10 @@ import { parseWeboutResponse } from './utils'
import { getTokens } from './auth/getTokens' import { getTokens } from './auth/getTokens'
export class SASjsApiClient { export class SASjsApiClient {
constructor( constructor(private requestClient: RequestClient) {}
private serverUrl: string,
private requestClient: RequestClient
) {}
public setConfig(serverUrl: string) {
if (serverUrl) this.serverUrl = serverUrl
}
public async deploy( public async deploy(
members: FileTree, dataJson: ServicePackSASjs,
appLoc: string, appLoc: string,
authConfig?: AuthConfig authConfig?: AuthConfig
) { ) {
@@ -30,13 +23,17 @@ 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
streamServiceName?: string
example?: {} example?: {}
}>( }>(
'SASjsApi/drive/deploy', 'SASjsApi/drive/deploy',
{ fileTree: members, appLoc: appLoc }, dataJson,
access_token, access_token,
undefined, undefined,
{}, {},

View File

@@ -26,11 +26,18 @@ export const generateFileUploadForm = (
) )
} }
const file = new Blob([csv], { if (typeof FormData === 'undefined' && formData instanceof NodeFormData) {
type: 'application/csv' formData.append(name, csv, {
}) filename: `${name}.csv`,
contentType: 'application/csv'
})
} else {
const file = new Blob([csv], {
type: 'application/csv'
})
formData.append(name, file, `${name}.csv`) formData.append(name, file, `${name}.csv`)
}
} }
return formData return formData

View File

@@ -99,7 +99,20 @@ 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'

View File

@@ -74,38 +74,32 @@ export class Sas9JobExecutor extends BaseJobExecutor {
? 'multipart/form-data; boundary=' + (formData as any)._boundary ? 'multipart/form-data; boundary=' + (formData as any)._boundary
: 'text/plain' : 'text/plain'
return await this.sas9RequestClient!.post( const requestPromise = new Promise((resolve, reject) =>
apiUrl, this.sas9RequestClient!.post(apiUrl, formData, undefined, contentType, {
formData,
undefined,
contentType,
{
Accept: '*/*', Accept: '*/*',
Connection: 'Keep-Alive' Connection: 'Keep-Alive'
} })
.then((res: any) => {
// appending response to requests array that will be used for requests history reference
this.requestClient!.appendRequest(res, sasJob, config.debug)
resolve(res)
})
.catch((err: any) => {
// by default error string is equal to actual error object
let errString = err
// if error object contains non empty result attribute, set result to errString
if (err.result && err.result !== '') errString = err.result
// if there's no result but error message, set error message to errString
else if (err.message) errString = err.message
// appending error to requests array that will be used for requests history reference
this.requestClient!.appendRequest(errString, sasJob, config.debug)
reject(new ErrorResponse(err?.message, err))
})
) )
.then((res: any) => {
let resString = res
if (typeof res === 'object') { return requestPromise
resString = JSON.stringify(res)
}
this.requestClient!.appendRequest(resString, sasJob, config.debug)
return res
})
.catch((err: any) => {
let errString = err
if (typeof err === 'object') {
errString = JSON.stringify(errString)
}
this.requestClient!.appendRequest(errString, sasJob, config.debug)
return err
})
} }
private getRequestParams(config: any): any { private getRequestParams(config: any): any {

View File

@@ -131,6 +131,26 @@ 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)

View File

@@ -1,47 +0,0 @@
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'

View File

@@ -12,5 +12,4 @@ 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'

View File

@@ -16,10 +16,15 @@ 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" src="|<iframe style="width: 99%; height: 500px; background-color:Canvas;" src=/
)[1] )[1]
const jsonUrl = iframeStart ? iframeStart.split('"></iframe>')[0] : null const jsonUrl = iframeStart
? 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.')
} }