@sasjs/adapter 2.12.0 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/SAS9ApiClient.d.ts +3 -1
  2. package/SASViyaApiClient.d.ts +7 -1
  3. package/SASjs.d.ts +9 -7
  4. package/auth/AuthManager.d.ts +7 -2
  5. package/index.js +2 -2
  6. package/job-execution/Sas9JobExecutor.d.ts +6 -5
  7. package/node/SAS9ApiClient.d.ts +3 -1
  8. package/node/SASViyaApiClient.d.ts +7 -1
  9. package/node/SASjs.d.ts +9 -7
  10. package/node/auth/AuthManager.d.ts +7 -2
  11. package/node/index.js +2 -2
  12. package/node/job-execution/Sas9JobExecutor.d.ts +6 -5
  13. package/node/request/RequestClient.d.ts +4 -2
  14. package/node/request/Sas9RequestClient.d.ts +3 -1
  15. package/node/types/ExecuteScript.d.ts +0 -1
  16. package/node/types/SASjsConfig.d.ts +11 -4
  17. package/node/utils/createAxiosInstance.d.ts +3 -0
  18. package/node/utils/getValidJson.d.ts +1 -1
  19. package/node/utils/index.d.ts +1 -0
  20. package/node/utils/parseViyaDebugResponse.d.ts +1 -1
  21. package/package.json +10 -6
  22. package/request/RequestClient.d.ts +4 -2
  23. package/request/Sas9RequestClient.d.ts +3 -1
  24. package/src/SAS9ApiClient.ts +3 -2
  25. package/src/SASjs.ts +17 -12
  26. package/src/auth/AuthManager.ts +23 -10
  27. package/src/auth/getAccessToken.ts +1 -1
  28. package/src/job-execution/Sas9JobExecutor.ts +36 -5
  29. package/src/job-execution/WebJobExecutor.ts +18 -3
  30. package/src/request/RequestClient.ts +23 -20
  31. package/src/request/Sas9RequestClient.ts +3 -2
  32. package/src/test/SAS_server_app.ts +38 -0
  33. package/src/types/ExecuteScript.ts +0 -1
  34. package/src/types/SASjsConfig.ts +10 -4
  35. package/src/utils/createAxiosInstance.ts +7 -0
  36. package/src/utils/getValidJson.ts +1 -1
  37. package/src/utils/index.ts +1 -0
  38. package/src/utils/parseWeboutResponse.ts +1 -1
  39. package/test/RequestClient.spec.d.ts +1 -0
  40. package/test/SAS_server_app.d.ts +10 -0
  41. package/types/ExecuteScript.d.ts +0 -1
  42. package/types/SASjsConfig.d.ts +11 -4
  43. package/utils/createAxiosInstance.d.ts +3 -0
  44. package/utils/getValidJson.d.ts +1 -1
  45. package/utils/index.d.ts +1 -0
  46. package/utils/parseViyaDebugResponse.d.ts +1 -1
  47. package/CHANGELOG.md +0 -213
@@ -1,5 +1,8 @@
1
+ /// <reference types="node" />
2
+ import * as https from 'https';
1
3
  import { ServerType } from '@sasjs/utils/types';
2
4
  import { BaseJobExecutor } from './JobExecutor';
5
+ import { RequestClient } from '../request/RequestClient';
3
6
  /**
4
7
  * Job executor for SAS9 servers for use in Node.js environments.
5
8
  * Initiates login with the provided username and password from the config
@@ -9,10 +12,8 @@ import { BaseJobExecutor } from './JobExecutor';
9
12
  export declare class Sas9JobExecutor extends BaseJobExecutor {
10
13
  private jobsPath;
11
14
  private requestClient;
12
- constructor(serverUrl: string, serverType: ServerType, jobsPath: string, allowInsecureRequests: boolean);
13
- execute(sasJob: string, data: any, config: any): Promise<{
14
- result: unknown;
15
- etag: string;
16
- }>;
15
+ private sas9RequestClient;
16
+ constructor(serverUrl: string, serverType: ServerType, jobsPath: string, requestClient: RequestClient, httpsAgentOptions?: https.AgentOptions);
17
+ execute(sasJob: string, data: any, config: any): Promise<any>;
17
18
  private getRequestParams;
18
19
  }
@@ -1,4 +1,6 @@
1
+ /// <reference types="node" />
1
2
  import { AxiosInstance, AxiosResponse } from 'axios';
3
+ import * as https from 'https';
2
4
  import { CsrfToken } from '..';
3
5
  import { SASjsRequest } from '../types';
4
6
  export interface HttpClient {
@@ -34,8 +36,8 @@ export declare class RequestClient implements HttpClient {
34
36
  protected csrfToken: CsrfToken;
35
37
  protected fileUploadCsrfToken: CsrfToken | undefined;
36
38
  protected httpClient: AxiosInstance;
37
- constructor(baseUrl: string, allowInsecure?: boolean);
38
- setConfig(baseUrl: string, allowInsecure?: boolean): void;
39
+ constructor(baseUrl: string, httpsAgentOptions?: https.AgentOptions);
40
+ setConfig(baseUrl: string, httpsAgentOptions?: https.AgentOptions): void;
39
41
  getCsrfToken(type?: 'general' | 'file'): CsrfToken | undefined;
40
42
  clearCsrfTokens(): void;
41
43
  getBaseUrl(): string;
@@ -1,10 +1,12 @@
1
+ /// <reference types="node" />
2
+ import * as https from 'https';
1
3
  import { RequestClient } from './RequestClient';
2
4
  /**
3
5
  * Specific request client for SAS9 in Node.js environments.
4
6
  * Handles redirects and cookie management.
5
7
  */
6
8
  export declare class Sas9RequestClient extends RequestClient {
7
- constructor(baseUrl: string, allowInsecure?: boolean);
9
+ constructor(baseUrl: string, httpsAgentOptions?: https.AgentOptions);
8
10
  login(username: string, password: string, jobsPath: string): Promise<void>;
9
11
  get<T>(url: string, accessToken: string | undefined, contentType?: string, overrideHeaders?: {
10
12
  [key: string]: string | number;
@@ -1,5 +1,4 @@
1
1
  export interface ExecutionQuery {
2
2
  _program: string;
3
3
  _debug?: number;
4
- _log?: boolean;
5
4
  }
@@ -1,3 +1,5 @@
1
+ /// <reference types="node" />
2
+ import * as https from 'https';
1
3
  import { ServerType } from '@sasjs/utils/types';
2
4
  /**
3
5
  * Specifies the configuration for the SASjs instance - eg where and how to
@@ -10,6 +12,11 @@ export declare class SASjsConfig {
10
12
  * streamed.
11
13
  */
12
14
  serverUrl: string;
15
+ /**
16
+ * The location of the STP Process Web Application. By default the adapter
17
+ * will use '/SASjsApi/stp/execute' on SAS JS.
18
+ */
19
+ pathSASJS?: string;
13
20
  /**
14
21
  * The location of the Stored Process Web Application. By default the adapter
15
22
  * will use '/SASStoredProcess/do' on SAS 9.
@@ -53,11 +60,11 @@ export declare class SASjsConfig {
53
60
  */
54
61
  useComputeApi: boolean | null;
55
62
  /**
56
- * Defaults to `false`.
57
- * When set to `true`, the adapter will allow requests to SAS servers that use a self-signed SSL certificate.
58
- * Changing this setting is not recommended.
63
+ * Optional settings to configure HTTPS Agent.
64
+ * By providing `key`, `cert`, `ca` to connect with server
65
+ * Other options can be set `rejectUnauthorized` and `requestCert`
59
66
  */
60
- allowInsecureRequests: boolean;
67
+ httpsAgentOptions?: https.AgentOptions;
61
68
  /**
62
69
  * Supported login mechanisms are - Redirected and Default
63
70
  */
@@ -0,0 +1,3 @@
1
+ /// <reference types="node" />
2
+ import * as https from 'https';
3
+ export declare const createAxiosInstance: (baseURL: string, httpsAgent?: https.Agent | undefined) => import("axios").AxiosInstance;
@@ -2,4 +2,4 @@
2
2
  * if string passed then parse the string to json else if throw error for all other types unless it is not a valid json object.
3
3
  * @param str - string to check.
4
4
  */
5
- export declare const getValidJson: (str: string | object) => any;
5
+ export declare const getValidJson: (str: string | object) => object;
@@ -1,6 +1,7 @@
1
1
  export * from './asyncForEach';
2
2
  export * from './compareTimestamps';
3
3
  export * from './convertToCsv';
4
+ export * from './createAxiosInstance';
4
5
  export * from './delay';
5
6
  export * from './isNode';
6
7
  export * from './isRelativePath';
@@ -9,4 +9,4 @@ import { RequestClient } from '../request/RequestClient';
9
9
  * @param serverUrl
10
10
  * @returns
11
11
  */
12
- export declare const parseSasViyaDebugResponse: (response: string, requestClient: RequestClient, serverUrl: string) => Promise<any>;
12
+ export declare const parseSasViyaDebugResponse: (response: string, requestClient: RequestClient, serverUrl: string) => Promise<object>;
package/package.json CHANGED
@@ -41,30 +41,34 @@
41
41
  "license": "ISC",
42
42
  "devDependencies": {
43
43
  "@types/axios": "^0.14.0",
44
+ "@types/express": "^4.17.13",
44
45
  "@types/form-data": "^2.5.0",
45
- "@types/jest": "^27.0.1",
46
+ "@types/jest": "^27.0.2",
46
47
  "@types/mime": "^2.0.3",
48
+ "@types/pem": "^1.9.6",
47
49
  "@types/tough-cookie": "^4.0.1",
48
50
  "copyfiles": "^2.4.1",
49
51
  "cp": "^0.2.0",
50
52
  "dotenv": "^10.0.0",
53
+ "express": "^4.17.1",
51
54
  "jest": "^27.2.0",
52
55
  "jest-extended": "^0.11.5",
53
56
  "node-polyfill-webpack-plugin": "^1.1.4",
54
57
  "path": "^0.12.7",
58
+ "pem": "^1.14.4",
55
59
  "process": "^0.11.10",
56
60
  "rimraf": "^3.0.2",
57
- "semantic-release": "^17.4.7",
61
+ "semantic-release": "^18.0.0",
58
62
  "terser-webpack-plugin": "^5.2.4",
59
63
  "ts-jest": "^27.0.3",
60
- "ts-loader": "^9.2.2",
64
+ "ts-loader": "^9.2.6",
61
65
  "tslint": "^6.1.3",
62
66
  "tslint-config-prettier": "^1.18.0",
63
- "typedoc": "^0.22.3",
67
+ "typedoc": "0.19.2",
64
68
  "typedoc-neo-theme": "^1.1.1",
65
69
  "typedoc-plugin-external-module-name": "^4.0.6",
66
70
  "typescript": "4.3.5",
67
- "webpack": "^5.52.1",
71
+ "webpack": "^5.56.0",
68
72
  "webpack-cli": "^4.7.2"
69
73
  },
70
74
  "main": "index.js",
@@ -76,5 +80,5 @@
76
80
  "https": "^1.0.0",
77
81
  "tough-cookie": "^4.0.0"
78
82
  },
79
- "version": "2.12.0"
83
+ "version": "3.1.0"
80
84
  }
@@ -1,4 +1,6 @@
1
+ /// <reference types="node" />
1
2
  import { AxiosInstance, AxiosResponse } from 'axios';
3
+ import * as https from 'https';
2
4
  import { CsrfToken } from '..';
3
5
  import { SASjsRequest } from '../types';
4
6
  export interface HttpClient {
@@ -34,8 +36,8 @@ export declare class RequestClient implements HttpClient {
34
36
  protected csrfToken: CsrfToken;
35
37
  protected fileUploadCsrfToken: CsrfToken | undefined;
36
38
  protected httpClient: AxiosInstance;
37
- constructor(baseUrl: string, allowInsecure?: boolean);
38
- setConfig(baseUrl: string, allowInsecure?: boolean): void;
39
+ constructor(baseUrl: string, httpsAgentOptions?: https.AgentOptions);
40
+ setConfig(baseUrl: string, httpsAgentOptions?: https.AgentOptions): void;
39
41
  getCsrfToken(type?: 'general' | 'file'): CsrfToken | undefined;
40
42
  clearCsrfTokens(): void;
41
43
  getBaseUrl(): string;
@@ -1,10 +1,12 @@
1
+ /// <reference types="node" />
2
+ import * as https from 'https';
1
3
  import { RequestClient } from './RequestClient';
2
4
  /**
3
5
  * Specific request client for SAS9 in Node.js environments.
4
6
  * Handles redirects and cookie management.
5
7
  */
6
8
  export declare class Sas9RequestClient extends RequestClient {
7
- constructor(baseUrl: string, allowInsecure?: boolean);
9
+ constructor(baseUrl: string, httpsAgentOptions?: https.AgentOptions);
8
10
  login(username: string, password: string, jobsPath: string): Promise<void>;
9
11
  get<T>(url: string, accessToken: string | undefined, contentType?: string, overrideHeaders?: {
10
12
  [key: string]: string | number;
@@ -1,3 +1,4 @@
1
+ import * as https from 'https'
1
2
  import { generateTimestamp } from '@sasjs/utils/time'
2
3
  import * as NodeFormData from 'form-data'
3
4
  import { Sas9RequestClient } from './request/Sas9RequestClient'
@@ -13,10 +14,10 @@ export class SAS9ApiClient {
13
14
  constructor(
14
15
  private serverUrl: string,
15
16
  private jobsPath: string,
16
- allowInsecureRequests: boolean
17
+ httpsAgentOptions?: https.AgentOptions
17
18
  ) {
18
19
  if (serverUrl) isUrl(serverUrl)
19
- this.requestClient = new Sas9RequestClient(serverUrl, allowInsecureRequests)
20
+ this.requestClient = new Sas9RequestClient(serverUrl, httpsAgentOptions)
20
21
  }
21
22
 
22
23
  /**
package/src/SASjs.ts CHANGED
@@ -33,6 +33,7 @@ import { LoginOptions, LoginResult } from './types/Login'
33
33
 
34
34
  const defaultConfig: SASjsConfig = {
35
35
  serverUrl: '',
36
+ pathSASJS: '/SASjsApi/stp/execute',
36
37
  pathSAS9: '/SASStoredProcess/do',
37
38
  pathSASViya: '/SASJobExecution',
38
39
  appLoc: '/Public/seedapp',
@@ -40,7 +41,6 @@ const defaultConfig: SASjsConfig = {
40
41
  debug: false,
41
42
  contextName: 'SAS Job Execution compute context',
42
43
  useComputeApi: null,
43
- allowInsecureRequests: false,
44
44
  loginMechanism: LoginMechanism.Default
45
45
  }
46
46
 
@@ -62,7 +62,7 @@ export default class SASjs {
62
62
  private jesJobExecutor: JobExecutor | null = null
63
63
  private sas9JobExecutor: JobExecutor | null = null
64
64
 
65
- constructor(config?: any) {
65
+ constructor(config?: Partial<SASjsConfig>) {
66
66
  this.sasjsConfig = {
67
67
  ...defaultConfig,
68
68
  ...config
@@ -528,10 +528,11 @@ export default class SASjs {
528
528
 
529
529
  /**
530
530
  * Checks whether a session is active, or login is required.
531
+ * @param accessToken - an optional access token is required for SASjs server type.
531
532
  * @returns - a promise which resolves with an object containing two values - a boolean `isLoggedIn`, and a string `userName`.
532
533
  */
533
- public async checkSession() {
534
- return this.authManager!.checkSession()
534
+ public async checkSession(accessToken?: string) {
535
+ return this.authManager!.checkSession(accessToken)
535
536
  }
536
537
 
537
538
  /**
@@ -564,9 +565,10 @@ export default class SASjs {
564
565
 
565
566
  /**
566
567
  * Logs out of the configured SAS server.
568
+ * @param accessToken - an optional access token is required for SASjs server type.
567
569
  */
568
- public logOut() {
569
- return this.authManager!.logOut()
570
+ public logOut(accessToken?: string) {
571
+ return this.authManager!.logOut(accessToken)
570
572
  }
571
573
 
572
574
  /**
@@ -797,7 +799,7 @@ export default class SASjs {
797
799
  sasApiClient = new SAS9ApiClient(
798
800
  serverUrl,
799
801
  this.jobsPath,
800
- this.sasjsConfig.allowInsecureRequests
802
+ this.sasjsConfig.httpsAgentOptions
801
803
  )
802
804
  }
803
805
  } else {
@@ -964,19 +966,21 @@ export default class SASjs {
964
966
  if (!this.requestClient) {
965
967
  this.requestClient = new RequestClient(
966
968
  this.sasjsConfig.serverUrl,
967
- this.sasjsConfig.allowInsecureRequests
969
+ this.sasjsConfig.httpsAgentOptions
968
970
  )
969
971
  } else {
970
972
  this.requestClient.setConfig(
971
973
  this.sasjsConfig.serverUrl,
972
- this.sasjsConfig.allowInsecureRequests
974
+ this.sasjsConfig.httpsAgentOptions
973
975
  )
974
976
  }
975
977
 
976
978
  this.jobsPath =
977
979
  this.sasjsConfig.serverType === ServerType.SasViya
978
980
  ? this.sasjsConfig.pathSASViya
979
- : this.sasjsConfig.pathSAS9
981
+ : this.sasjsConfig.serverType === ServerType.Sas9
982
+ ? this.sasjsConfig.pathSAS9
983
+ : this.sasjsConfig.pathSASJS || ''
980
984
 
981
985
  this.authManager = new AuthManager(
982
986
  this.sasjsConfig.serverUrl,
@@ -1010,7 +1014,7 @@ export default class SASjs {
1010
1014
  this.sas9ApiClient = new SAS9ApiClient(
1011
1015
  this.sasjsConfig.serverUrl,
1012
1016
  this.jobsPath,
1013
- this.sasjsConfig.allowInsecureRequests
1017
+ this.sasjsConfig.httpsAgentOptions
1014
1018
  )
1015
1019
  }
1016
1020
  }
@@ -1045,7 +1049,8 @@ export default class SASjs {
1045
1049
  this.sasjsConfig.serverUrl,
1046
1050
  this.sasjsConfig.serverType!,
1047
1051
  this.jobsPath,
1048
- this.sasjsConfig.allowInsecureRequests
1052
+ this.requestClient,
1053
+ this.sasjsConfig.httpsAgentOptions
1049
1054
  )
1050
1055
 
1051
1056
  this.computeJobExecutor = new ComputeJobExecutor(
@@ -21,7 +21,9 @@ export class AuthManager {
21
21
  this.logoutUrl =
22
22
  this.serverType === ServerType.Sas9
23
23
  ? '/SASLogon/logout?'
24
- : '/SASLogon/logout.do?'
24
+ : this.serverType === ServerType.SasViya
25
+ ? '/SASLogon/logout.do?'
26
+ : '/SASjsApi/auth/logout'
25
27
  }
26
28
 
27
29
  /**
@@ -180,20 +182,21 @@ export class AuthManager {
180
182
 
181
183
  /**
182
184
  * Checks whether a session is active, or login is required.
185
+ * @param accessToken - an optional access token is required for SASjs server type.
183
186
  * @returns - a promise which resolves with an object containing three values
184
187
  * - a boolean `isLoggedIn`
185
188
  * - a string `userName` and
186
189
  * - a form `loginForm` if not loggedin.
187
190
  */
188
- public async checkSession(): Promise<{
191
+ public async checkSession(accessToken?: string): Promise<{
189
192
  isLoggedIn: boolean
190
193
  userName: string
191
194
  loginForm?: any
192
195
  }> {
193
- const { isLoggedIn, userName } = await this.fetchUserName()
196
+ const { isLoggedIn, userName } = await this.fetchUserName(accessToken)
194
197
  let loginForm = null
195
198
 
196
- if (!isLoggedIn) {
199
+ if (!isLoggedIn && this.serverType !== ServerType.Sasjs) {
197
200
  //We will logout to make sure cookies are removed and login form is presented
198
201
  //Residue can happen in case of session expiration
199
202
  await this.logOut()
@@ -218,19 +221,20 @@ export class AuthManager {
218
221
  return await this.getLoginForm(formResponse)
219
222
  }
220
223
 
221
- private async fetchUserName(): Promise<{
224
+ private async fetchUserName(accessToken?: string): Promise<{
222
225
  isLoggedIn: boolean
223
226
  userName: string
224
227
  }> {
225
- //For VIYA we will send request on API endpoint. Which is faster then pinging SASJobExecution.
226
- //For SAS9 we will send request on SASStoredProcess
227
228
  const url =
228
229
  this.serverType === ServerType.SasViya
229
230
  ? `${this.serverUrl}/identities/users/@currentUser`
230
- : `${this.serverUrl}/SASStoredProcess`
231
+ : this.serverType === ServerType.Sas9
232
+ ? `${this.serverUrl}/SASStoredProcess`
233
+ : `${this.serverUrl}/SASjsApi/session`
231
234
 
235
+ // Access token is required for server type `SASjs`
232
236
  const { result: loginResponse } = await this.requestClient
233
- .get<string>(url, undefined, 'text/plain')
237
+ .get<string>(url, accessToken, 'text/plain')
234
238
  .catch((err: any) => {
235
239
  return { result: 'authErr' }
236
240
  })
@@ -256,7 +260,12 @@ export class AuthManager {
256
260
  .split(' ')
257
261
  .map((name: string) => name.slice(0, 3).toLowerCase())
258
262
  .join('')
263
+
264
+ case ServerType.Sasjs:
265
+ return response?.username
266
+
259
267
  default:
268
+ console.error('Server Type not found in extractUserName function')
260
269
  return ''
261
270
  }
262
271
  }
@@ -304,8 +313,12 @@ export class AuthManager {
304
313
 
305
314
  /**
306
315
  * Logs out of the configured SAS server.
316
+ * @param accessToken - an optional access token is required for SASjs server type.
307
317
  */
308
- public logOut() {
318
+ public logOut(accessToken?: string) {
319
+ if (this.serverType === ServerType.Sasjs) {
320
+ return this.requestClient.post(this.logoutUrl, undefined, accessToken)
321
+ }
309
322
  this.requestClient.clearCsrfTokens()
310
323
  return this.requestClient.get(this.logoutUrl, undefined).then(() => true)
311
324
  }
@@ -46,7 +46,7 @@ export async function getAccessToken(
46
46
  )
47
47
  .then((res) => res.result as SasAuthResponse)
48
48
  .catch((err) => {
49
- throw prefixMessage(err, 'Error while getting access token')
49
+ throw prefixMessage(err, 'Error while getting access token. ')
50
50
  })
51
51
 
52
52
  return authResponse
@@ -1,9 +1,11 @@
1
+ import * as https from 'https'
1
2
  import { ServerType } from '@sasjs/utils/types'
2
3
  import * as NodeFormData from 'form-data'
3
4
  import { ErrorResponse } from '../types/errors'
4
5
  import { convertToCSV, isRelativePath } from '../utils'
5
6
  import { BaseJobExecutor } from './JobExecutor'
6
7
  import { Sas9RequestClient } from '../request/Sas9RequestClient'
8
+ import { RequestClient } from '../request/RequestClient'
7
9
 
8
10
  /**
9
11
  * Job executor for SAS9 servers for use in Node.js environments.
@@ -12,15 +14,16 @@ import { Sas9RequestClient } from '../request/Sas9RequestClient'
12
14
  * job execution requests.
13
15
  */
14
16
  export class Sas9JobExecutor extends BaseJobExecutor {
15
- private requestClient: Sas9RequestClient
17
+ private sas9RequestClient: Sas9RequestClient
16
18
  constructor(
17
19
  serverUrl: string,
18
20
  serverType: ServerType,
19
21
  private jobsPath: string,
20
- allowInsecureRequests: boolean
22
+ private requestClient: RequestClient,
23
+ httpsAgentOptions?: https.AgentOptions
21
24
  ) {
22
25
  super(serverUrl, serverType)
23
- this.requestClient = new Sas9RequestClient(serverUrl, allowInsecureRequests)
26
+ this.sas9RequestClient = new Sas9RequestClient(serverUrl, httpsAgentOptions)
24
27
  }
25
28
 
26
29
  async execute(sasJob: string, data: any, config: any) {
@@ -36,6 +39,8 @@ export class Sas9JobExecutor extends BaseJobExecutor {
36
39
  : ''
37
40
  }`
38
41
 
42
+ apiUrl = `${apiUrl}${config.debug ? '&_debug=131' : ''}`
43
+
39
44
  let requestParams = {
40
45
  ...this.getRequestParams(config)
41
46
  }
@@ -48,6 +53,8 @@ export class Sas9JobExecutor extends BaseJobExecutor {
48
53
  } catch (e: any) {
49
54
  return Promise.reject(new ErrorResponse(e?.message, e))
50
55
  }
56
+ } else {
57
+ data = ''
51
58
  }
52
59
 
53
60
  for (const key in requestParams) {
@@ -56,16 +63,18 @@ export class Sas9JobExecutor extends BaseJobExecutor {
56
63
  }
57
64
  }
58
65
 
59
- await this.requestClient.login(
66
+ await this.sas9RequestClient.login(
60
67
  config.username,
61
68
  config.password,
62
69
  this.jobsPath
63
70
  )
71
+
64
72
  const contentType =
65
73
  data && Object.keys(data).length
66
74
  ? 'multipart/form-data; boundary=' + (formData as any)._boundary
67
75
  : 'text/plain'
68
- return await this.requestClient!.post(
76
+
77
+ return await this.sas9RequestClient!.post(
69
78
  apiUrl,
70
79
  formData,
71
80
  undefined,
@@ -75,6 +84,28 @@ export class Sas9JobExecutor extends BaseJobExecutor {
75
84
  Connection: 'Keep-Alive'
76
85
  }
77
86
  )
87
+ .then((res: any) => {
88
+ let resString = res
89
+
90
+ if (typeof res === 'object') {
91
+ resString = JSON.stringify(res)
92
+ }
93
+
94
+ this.requestClient!.appendRequest(resString, sasJob, config.debug)
95
+
96
+ return res
97
+ })
98
+ .catch((err: any) => {
99
+ let errString = err
100
+
101
+ if (typeof err === 'object') {
102
+ errString = JSON.stringify(errString)
103
+ }
104
+
105
+ this.requestClient!.appendRequest(errString, sasJob, config.debug)
106
+
107
+ return err
108
+ })
78
109
  }
79
110
 
80
111
  private getRequestParams(config: any): any {
@@ -15,7 +15,8 @@ import { SASViyaApiClient } from '../SASViyaApiClient'
15
15
  import {
16
16
  isRelativePath,
17
17
  parseSasViyaDebugResponse,
18
- appendExtraResponseAttributes
18
+ appendExtraResponseAttributes,
19
+ getValidJson
19
20
  } from '../utils'
20
21
  import { BaseJobExecutor } from './JobExecutor'
21
22
  import { parseWeboutResponse } from '../utils/parseWeboutResponse'
@@ -113,6 +114,7 @@ export class WebJobExecutor extends BaseJobExecutor {
113
114
  const stringifiedData = JSON.stringify(data)
114
115
  if (
115
116
  config.serverType === ServerType.Sas9 ||
117
+ config.serverType === ServerType.Sasjs ||
116
118
  stringifiedData.length > 500000 ||
117
119
  stringifiedData.includes(';')
118
120
  ) {
@@ -142,12 +144,25 @@ export class WebJobExecutor extends BaseJobExecutor {
142
144
  }
143
145
 
144
146
  const requestPromise = new Promise((resolve, reject) => {
145
- this.requestClient!.post(apiUrl, formData, undefined)
147
+ // Access token is required for server type `SASjs`
148
+ this.requestClient!.post(apiUrl, formData, authConfig?.access_token)
146
149
  .then(async (res: any) => {
147
- this.requestClient!.appendRequest(res, sasJob, config.debug)
150
+ const resObj =
151
+ this.serverType === ServerType.Sasjs
152
+ ? {
153
+ result: res.result._webout,
154
+ log: res.result.log
155
+ }
156
+ : res
157
+ this.requestClient!.appendRequest(resObj, sasJob, config.debug)
148
158
 
149
159
  let jsonResponse = res.result
150
160
 
161
+ if (this.serverType === ServerType.Sasjs) {
162
+ const webout = parseWeboutResponse(res.result._webout, apiUrl)
163
+ jsonResponse = getValidJson(webout)
164
+ }
165
+
151
166
  if (config.debug) {
152
167
  switch (this.serverType) {
153
168
  case ServerType.SasViya:
@@ -1,4 +1,5 @@
1
- import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios'
1
+ import { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios'
2
+ import * as https from 'https'
2
3
  import { CsrfToken } from '..'
3
4
  import { isAuthorizeFormRequired, isLogInRequired } from '../auth'
4
5
  import {
@@ -12,7 +13,11 @@ import { SASjsRequest } from '../types'
12
13
  import { parseWeboutResponse } from '../utils/parseWeboutResponse'
13
14
  import { prefixMessage } from '@sasjs/utils/error'
14
15
  import { SAS9AuthError } from '../types/errors/SAS9AuthError'
15
- import { parseGeneratedCode, parseSourceCode } from '../utils'
16
+ import {
17
+ parseGeneratedCode,
18
+ parseSourceCode,
19
+ createAxiosInstance
20
+ } from '../utils'
16
21
 
17
22
  export interface HttpClient {
18
23
  get<T>(
@@ -54,12 +59,15 @@ export class RequestClient implements HttpClient {
54
59
  protected fileUploadCsrfToken: CsrfToken | undefined
55
60
  protected httpClient!: AxiosInstance
56
61
 
57
- constructor(protected baseUrl: string, allowInsecure = false) {
58
- this.createHttpClient(baseUrl, allowInsecure)
62
+ constructor(
63
+ protected baseUrl: string,
64
+ httpsAgentOptions?: https.AgentOptions
65
+ ) {
66
+ this.createHttpClient(baseUrl, httpsAgentOptions)
59
67
  }
60
68
 
61
- public setConfig(baseUrl: string, allowInsecure = false) {
62
- this.createHttpClient(baseUrl, allowInsecure)
69
+ public setConfig(baseUrl: string, httpsAgentOptions?: https.AgentOptions) {
70
+ this.createHttpClient(baseUrl, httpsAgentOptions)
63
71
  }
64
72
 
65
73
  public getCsrfToken(type: 'general' | 'file' = 'general') {
@@ -511,20 +519,15 @@ export class RequestClient implements HttpClient {
511
519
  return responseToReturn
512
520
  }
513
521
 
514
- private createHttpClient(baseUrl: string, allowInsecure = false) {
515
- const https = require('https')
516
- if (allowInsecure && https.Agent) {
517
- this.httpClient = axios.create({
518
- baseURL: baseUrl,
519
- httpsAgent: new https.Agent({
520
- rejectUnauthorized: !allowInsecure
521
- })
522
- })
523
- } else {
524
- this.httpClient = axios.create({
525
- baseURL: baseUrl
526
- })
527
- }
522
+ private createHttpClient(
523
+ baseUrl: string,
524
+ httpsAgentOptions?: https.AgentOptions
525
+ ) {
526
+ const httpsAgent = httpsAgentOptions
527
+ ? new https.Agent(httpsAgentOptions)
528
+ : undefined
529
+
530
+ this.httpClient = createAxiosInstance(baseUrl, httpsAgent)
528
531
 
529
532
  this.httpClient.defaults.validateStatus = (status) =>
530
533
  status >= 200 && status < 401
@@ -1,3 +1,4 @@
1
+ import * as https from 'https'
1
2
  import { AxiosRequestConfig } from 'axios'
2
3
  import axiosCookieJarSupport from 'axios-cookiejar-support'
3
4
  import * as tough from 'tough-cookie'
@@ -9,8 +10,8 @@ import { RequestClient, throwIfError } from './RequestClient'
9
10
  * Handles redirects and cookie management.
10
11
  */
11
12
  export class Sas9RequestClient extends RequestClient {
12
- constructor(baseUrl: string, allowInsecure = false) {
13
- super(baseUrl, allowInsecure)
13
+ constructor(baseUrl: string, httpsAgentOptions?: https.AgentOptions) {
14
+ super(baseUrl, httpsAgentOptions)
14
15
  this.httpClient.defaults.maxRedirects = 0
15
16
  this.httpClient.defaults.validateStatus = (status) =>
16
17
  status >= 200 && status < 303