From d0eb1a7bfb6651017befc1412f00dada2e6ed24e Mon Sep 17 00:00:00 2001 From: Sabir Hassan Date: Thu, 24 Mar 2022 02:43:14 +0500 Subject: [PATCH 1/4] fix: should not create blob in node --- src/file/generateFileUploadForm.ts | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/file/generateFileUploadForm.ts b/src/file/generateFileUploadForm.ts index 04e9c30..d88f13d 100644 --- a/src/file/generateFileUploadForm.ts +++ b/src/file/generateFileUploadForm.ts @@ -26,11 +26,18 @@ export const generateFileUploadForm = ( ) } - const file = new Blob([csv], { - type: 'application/csv' - }) + if (typeof FormData === 'undefined' && formData instanceof NodeFormData) { + 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 From 6cab245cde12e8c49d06c0ec8a895fd148ec2ac7 Mon Sep 17 00:00:00 2001 From: Sabir Hassan Date: Wed, 30 Mar 2022 01:22:03 +0500 Subject: [PATCH 2/4] fix: update code for extracting json url when debug is enabled --- src/utils/parseViyaDebugResponse.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/utils/parseViyaDebugResponse.ts b/src/utils/parseViyaDebugResponse.ts index d3d3e6e..f5e4e54 100644 --- a/src/utils/parseViyaDebugResponse.ts +++ b/src/utils/parseViyaDebugResponse.ts @@ -16,10 +16,15 @@ export const parseSasViyaDebugResponse = async ( requestClient: RequestClient, serverUrl: string ) => { + // On viya 3.5, iframe is like + // On viya 4, iframe is like + const iframeStart = response.split( - '')[0] : null + const jsonUrl = iframeStart + ? iframeStart.split(/"><\/iframe>|><\/iframe>/)[0] + : null if (!jsonUrl) { throw new Error('Unable to find webout file URL.') } From fc0a450e94ea97b80af5cbde5c6d72a8a027e3e4 Mon Sep 17 00:00:00 2001 From: Saad Jutt Date: Thu, 31 Mar 2022 04:20:49 +0500 Subject: [PATCH 3/4] fix(deploy): to SASJS with complete JSON object --- package-lock.json | 14 ++++++------- package.json | 2 +- src/SASjs.ts | 34 ++++++++++--------------------- src/SASjsApiClient.ts | 27 ++++++++----------------- src/types/FileTree.ts | 47 ------------------------------------------- src/types/index.ts | 1 - 6 files changed, 27 insertions(+), 98 deletions(-) delete mode 100644 src/types/FileTree.ts diff --git a/package-lock.json b/package-lock.json index 134f7f9..4d59496 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,7 +8,7 @@ "hasInstallScript": true, "license": "ISC", "dependencies": { - "@sasjs/utils": "2.40.0", + "@sasjs/utils": "file:../utils/build/sasjs-utils-5.0.0.tgz", "axios": "0.26.0", "axios-cookiejar-support": "1.0.1", "form-data": "4.0.0", @@ -1142,10 +1142,11 @@ } }, "node_modules/@sasjs/utils": { - "version": "2.40.0", - "resolved": "https://registry.npmjs.org/@sasjs/utils/-/utils-2.40.0.tgz", - "integrity": "sha512-U0y/eqRlvfkMHmKDlr1xmeN+Rask7TnJPuRpOz71P8QpGYTw1M9AyZvzRSk503p4KCJb8ysdcqXyGVLfhuoM+A==", + "version": "5.0.0", + "resolved": "file:../utils/build/sasjs-utils-5.0.0.tgz", + "integrity": "sha512-MN4t2AgGAra0wYjsPgMG6XJOSFeQLOIDUJaI47mvl73qodqdeAAiVfCkfN7XSkfllQBVHE0X/t0AA7Imrq1uDg==", "hasInstallScript": true, + "license": "ISC", "dependencies": { "@types/fs-extra": "9.0.13", "@types/prompts": "2.0.13", @@ -13870,9 +13871,8 @@ } }, "@sasjs/utils": { - "version": "2.40.0", - "resolved": "https://registry.npmjs.org/@sasjs/utils/-/utils-2.40.0.tgz", - "integrity": "sha512-U0y/eqRlvfkMHmKDlr1xmeN+Rask7TnJPuRpOz71P8QpGYTw1M9AyZvzRSk503p4KCJb8ysdcqXyGVLfhuoM+A==", + "version": "file:../utils/build/sasjs-utils-5.0.0.tgz", + "integrity": "sha512-MN4t2AgGAra0wYjsPgMG6XJOSFeQLOIDUJaI47mvl73qodqdeAAiVfCkfN7XSkfllQBVHE0X/t0AA7Imrq1uDg==", "requires": { "@types/fs-extra": "9.0.13", "@types/prompts": "2.0.13", diff --git a/package.json b/package.json index e708586..b1948ea 100644 --- a/package.json +++ b/package.json @@ -72,7 +72,7 @@ }, "main": "index.js", "dependencies": { - "@sasjs/utils": "2.40.0", + "@sasjs/utils": "file:../utils/build/sasjs-utils-5.0.0.tgz", "axios": "0.26.0", "axios-cookiejar-support": "1.0.1", "form-data": "4.0.0", diff --git a/src/SASjs.ts b/src/SASjs.ts index 8aed075..2b2fb6d 100644 --- a/src/SASjs.ts +++ b/src/SASjs.ts @@ -5,8 +5,7 @@ import { EditContextInput, PollOptions, LoginMechanism, - ExecutionQuery, - FileTree + ExecutionQuery } from './types' import { SASViyaApiClient } from './SASViyaApiClient' import { SAS9ApiClient } from './SAS9ApiClient' @@ -18,7 +17,7 @@ import { AuthConfig, ExtraResponseAttributes, SasAuthResponse, - StreamConfig + ServicePackSASjs } from '@sasjs/utils/types' import { RequestClient } from './request/RequestClient' import { SasjsRequestClient } from './request/SasjsRequestClient' @@ -889,27 +888,21 @@ export default class SASjs { /** * 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 appLoc - the base folder in which to create the new folders and - * services. If not provided, is taken from SASjsConfig. - * @param streamConfig - optional configuration object of StreamConfig for deploying streaming app. - * @param authConfig - a valid client, secret, refresh and access tokens that are authorised to execute compute jobs. + * @param dataJson - the JSON specifying the folders and files to be created, can also includes + * appLoc, streamServiceName, streamWebFolder, streamLogo + * @param appLoc - (optional) the base folder in which to create the new folders and + * 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( - members: FileTree, + dataJson: ServicePackSASjs, appLoc?: string, - streamConfig?: StreamConfig, authConfig?: AuthConfig ) { if (!appLoc) { appLoc = this.sasjsConfig.appLoc } - return await this.sasJSApiClient?.deploy( - members, - appLoc, - streamConfig, - authConfig - ) + return await this.sasJSApiClient?.deploy(dataJson, appLoc, authConfig) } public async executeJobSASjs(query: ExecutionQuery) { @@ -1102,13 +1095,8 @@ export default class SASjs { } if (this.sasjsConfig.serverType === ServerType.Sasjs) { - if (this.sasJSApiClient) { - this.sasJSApiClient.setConfig(this.sasjsConfig.serverUrl) - } else { - this.sasJSApiClient = new SASjsApiClient( - this.sasjsConfig.serverUrl, - this.requestClient - ) + if (!this.sasJSApiClient) { + this.sasJSApiClient = new SASjsApiClient(this.requestClient) } } diff --git a/src/SASjsApiClient.ts b/src/SASjsApiClient.ts index e4fa737..c0a4268 100644 --- a/src/SASjsApiClient.ts +++ b/src/SASjsApiClient.ts @@ -1,5 +1,5 @@ -import { AuthConfig, ServerType, StreamConfig } from '@sasjs/utils/types' -import { FileTree, ExecutionQuery } from './types' +import { AuthConfig, ServerType, ServicePackSASjs } from '@sasjs/utils/types' +import { ExecutionQuery } from './types' import { RequestClient } from './request/RequestClient' import { getAccessTokenForSasjs } from './auth/getAccessTokenForSasjs' import { refreshTokensForSasjs } from './auth/refreshTokensForSasjs' @@ -8,19 +8,11 @@ import { parseWeboutResponse } from './utils' import { getTokens } from './auth/getTokens' export class SASjsApiClient { - constructor( - private serverUrl: string, - private requestClient: RequestClient - ) {} - - public setConfig(serverUrl: string) { - if (serverUrl) this.serverUrl = serverUrl - } + constructor(private requestClient: RequestClient) {} public async deploy( - members: FileTree, + dataJson: ServicePackSASjs, appLoc: string, - streamConfig?: StreamConfig, authConfig?: AuthConfig ) { let access_token = (authConfig || {}).access_token @@ -31,6 +23,9 @@ export class SASjsApiClient { ServerType.Sasjs )) } + + dataJson.appLoc = dataJson.appLoc || appLoc + const { result } = await this.requestClient.post<{ status: string message: string @@ -38,13 +33,7 @@ export class SASjsApiClient { example?: {} }>( 'SASjsApi/drive/deploy', - { - fileTree: members, - appLoc: appLoc, - streamServiceName: streamConfig?.streamServiceName, - streamWebFolder: streamConfig?.streamWebFolder, - streamLogo: streamConfig?.streamLogo - }, + dataJson, access_token, undefined, {}, diff --git a/src/types/FileTree.ts b/src/types/FileTree.ts deleted file mode 100644 index 548bc5a..0000000 --- a/src/types/FileTree.ts +++ /dev/null @@ -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' diff --git a/src/types/index.ts b/src/types/index.ts index 97f5406..c5994f7 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -12,5 +12,4 @@ export * from './Session' export * from './UploadFile' export * from './PollOptions' export * from './WriteStream' -export * from './FileTree' export * from './ExecuteScript' From 7b0ad2d60d9d2bc2ca801d52c5595d3e0873d420 Mon Sep 17 00:00:00 2001 From: Saad Jutt Date: Thu, 31 Mar 2022 16:39:46 +0500 Subject: [PATCH 4/4] chore: sasjs/utils version bump --- package-lock.json | 14 +++++++------- package.json | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index 4d59496..f51088d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,7 +8,7 @@ "hasInstallScript": true, "license": "ISC", "dependencies": { - "@sasjs/utils": "file:../utils/build/sasjs-utils-5.0.0.tgz", + "@sasjs/utils": "2.42.0", "axios": "0.26.0", "axios-cookiejar-support": "1.0.1", "form-data": "4.0.0", @@ -1142,11 +1142,10 @@ } }, "node_modules/@sasjs/utils": { - "version": "5.0.0", - "resolved": "file:../utils/build/sasjs-utils-5.0.0.tgz", - "integrity": "sha512-MN4t2AgGAra0wYjsPgMG6XJOSFeQLOIDUJaI47mvl73qodqdeAAiVfCkfN7XSkfllQBVHE0X/t0AA7Imrq1uDg==", + "version": "2.42.0", + "resolved": "https://registry.npmjs.org/@sasjs/utils/-/utils-2.42.0.tgz", + "integrity": "sha512-Y69l89PYNF/h9xvVH72om/39xA+cY80bhiVLzp/fJb3BlvzCf4RNswBBanUOv2I5JNa7gPpJuE7mEiXOlhD3eg==", "hasInstallScript": true, - "license": "ISC", "dependencies": { "@types/fs-extra": "9.0.13", "@types/prompts": "2.0.13", @@ -13871,8 +13870,9 @@ } }, "@sasjs/utils": { - "version": "file:../utils/build/sasjs-utils-5.0.0.tgz", - "integrity": "sha512-MN4t2AgGAra0wYjsPgMG6XJOSFeQLOIDUJaI47mvl73qodqdeAAiVfCkfN7XSkfllQBVHE0X/t0AA7Imrq1uDg==", + "version": "2.42.0", + "resolved": "https://registry.npmjs.org/@sasjs/utils/-/utils-2.42.0.tgz", + "integrity": "sha512-Y69l89PYNF/h9xvVH72om/39xA+cY80bhiVLzp/fJb3BlvzCf4RNswBBanUOv2I5JNa7gPpJuE7mEiXOlhD3eg==", "requires": { "@types/fs-extra": "9.0.13", "@types/prompts": "2.0.13", diff --git a/package.json b/package.json index b1948ea..e2e4dc5 100644 --- a/package.json +++ b/package.json @@ -72,7 +72,7 @@ }, "main": "index.js", "dependencies": { - "@sasjs/utils": "file:../utils/build/sasjs-utils-5.0.0.tgz", + "@sasjs/utils": "2.42.0", "axios": "0.26.0", "axios-cookiejar-support": "1.0.1", "form-data": "4.0.0",