@sasjs/adapter 2.11.4 → 3.0.2
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.
- package/SAS9ApiClient.d.ts +3 -1
- package/SASViyaApiClient.d.ts +7 -1
- package/SASjs.d.ts +15 -2
- package/SASjsApiClient.d.ts +20 -0
- package/index.js +2 -2
- package/job-execution/Sas9JobExecutor.d.ts +6 -5
- package/node/SAS9ApiClient.d.ts +3 -1
- package/node/SASViyaApiClient.d.ts +7 -1
- package/node/SASjs.d.ts +15 -2
- package/node/SASjsApiClient.d.ts +20 -0
- package/node/index.js +2 -2
- package/node/job-execution/Sas9JobExecutor.d.ts +6 -5
- package/node/request/RequestClient.d.ts +4 -2
- package/node/request/Sas9RequestClient.d.ts +3 -1
- package/node/types/ExecuteScript.d.ts +4 -0
- package/node/types/FileTree.d.ts +18 -0
- package/node/types/SASjsConfig.d.ts +6 -4
- package/node/types/index.d.ts +2 -0
- package/node/utils/createAxiosInstance.d.ts +3 -0
- package/node/utils/index.d.ts +1 -0
- package/package.json +11 -7
- package/request/RequestClient.d.ts +4 -2
- package/request/Sas9RequestClient.d.ts +3 -1
- package/src/SAS9ApiClient.ts +3 -2
- package/src/SASjs.ts +39 -12
- package/src/SASjsApiClient.ts +39 -0
- package/src/auth/AuthManager.ts +4 -0
- package/src/auth/getAccessToken.ts +1 -1
- package/src/job-execution/Sas9JobExecutor.ts +36 -5
- package/src/request/RequestClient.ts +24 -21
- package/src/request/Sas9RequestClient.ts +3 -2
- package/src/test/SAS_server_app.ts +38 -0
- package/src/types/ExecuteScript.ts +4 -0
- package/src/types/FileTree.ts +47 -0
- package/src/types/SASjsConfig.ts +5 -4
- package/src/types/index.ts +2 -0
- package/src/utils/createAxiosInstance.ts +7 -0
- package/src/utils/index.ts +1 -0
- package/test/RequestClient.spec.d.ts +1 -0
- package/test/SAS_server_app.d.ts +10 -0
- package/types/ExecuteScript.d.ts +4 -0
- package/types/FileTree.d.ts +18 -0
- package/types/SASjsConfig.d.ts +6 -4
- package/types/index.d.ts +2 -0
- package/utils/createAxiosInstance.d.ts +3 -0
- package/utils/index.d.ts +1 -0
- package/.all-contributorsrc +0 -103
- 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
|
-
|
|
13
|
-
|
|
14
|
-
|
|
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,
|
|
38
|
-
setConfig(baseUrl: string,
|
|
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,
|
|
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;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface FileTree {
|
|
2
|
+
members: [FolderMember, ServiceMember];
|
|
3
|
+
}
|
|
4
|
+
export declare enum MemberType {
|
|
5
|
+
folder = "folder",
|
|
6
|
+
service = "service"
|
|
7
|
+
}
|
|
8
|
+
export interface FolderMember {
|
|
9
|
+
name: string;
|
|
10
|
+
type: MemberType.folder;
|
|
11
|
+
members: [FolderMember, ServiceMember];
|
|
12
|
+
}
|
|
13
|
+
export interface ServiceMember {
|
|
14
|
+
name: string;
|
|
15
|
+
type: MemberType.service;
|
|
16
|
+
code: string;
|
|
17
|
+
}
|
|
18
|
+
export declare const isFileTree: (arg: any) => arg is FileTree;
|
|
@@ -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
|
|
@@ -53,11 +55,11 @@ export declare class SASjsConfig {
|
|
|
53
55
|
*/
|
|
54
56
|
useComputeApi: boolean | null;
|
|
55
57
|
/**
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
58
|
+
* Optional settings to configure HTTPS Agent.
|
|
59
|
+
* By providing `key`, `cert`, `ca` to connect with server
|
|
60
|
+
* Other options can be set `rejectUnauthorized` and `requestCert`
|
|
59
61
|
*/
|
|
60
|
-
|
|
62
|
+
httpsAgentOptions?: https.AgentOptions;
|
|
61
63
|
/**
|
|
62
64
|
* Supported login mechanisms are - Redirected and Default
|
|
63
65
|
*/
|
package/node/types/index.d.ts
CHANGED
package/node/utils/index.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -41,40 +41,44 @@
|
|
|
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.
|
|
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": "^
|
|
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.
|
|
64
|
+
"ts-loader": "^9.2.6",
|
|
61
65
|
"tslint": "^6.1.3",
|
|
62
66
|
"tslint-config-prettier": "^1.18.0",
|
|
63
|
-
"typedoc": "
|
|
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.
|
|
71
|
+
"webpack": "^5.56.0",
|
|
68
72
|
"webpack-cli": "^4.7.2"
|
|
69
73
|
},
|
|
70
74
|
"main": "index.js",
|
|
71
75
|
"dependencies": {
|
|
72
|
-
"@sasjs/utils": "^2.
|
|
76
|
+
"@sasjs/utils": "^2.32.0",
|
|
73
77
|
"axios": "^0.21.4",
|
|
74
78
|
"axios-cookiejar-support": "^1.0.1",
|
|
75
79
|
"form-data": "^4.0.0",
|
|
76
80
|
"https": "^1.0.0",
|
|
77
81
|
"tough-cookie": "^4.0.0"
|
|
78
82
|
},
|
|
79
|
-
"version": "
|
|
83
|
+
"version": "3.0.2"
|
|
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,
|
|
38
|
-
setConfig(baseUrl: string,
|
|
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,
|
|
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;
|
package/src/SAS9ApiClient.ts
CHANGED
|
@@ -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
|
-
|
|
17
|
+
httpsAgentOptions?: https.AgentOptions
|
|
17
18
|
) {
|
|
18
19
|
if (serverUrl) isUrl(serverUrl)
|
|
19
|
-
this.requestClient = new Sas9RequestClient(serverUrl,
|
|
20
|
+
this.requestClient = new Sas9RequestClient(serverUrl, httpsAgentOptions)
|
|
20
21
|
}
|
|
21
22
|
|
|
22
23
|
/**
|
package/src/SASjs.ts
CHANGED
|
@@ -4,10 +4,14 @@ import {
|
|
|
4
4
|
UploadFile,
|
|
5
5
|
EditContextInput,
|
|
6
6
|
PollOptions,
|
|
7
|
-
LoginMechanism
|
|
7
|
+
LoginMechanism,
|
|
8
|
+
FolderMember,
|
|
9
|
+
ServiceMember,
|
|
10
|
+
ExecutionQuery
|
|
8
11
|
} from './types'
|
|
9
12
|
import { SASViyaApiClient } from './SASViyaApiClient'
|
|
10
13
|
import { SAS9ApiClient } from './SAS9ApiClient'
|
|
14
|
+
import { SASjsApiClient } from './SASjsApiClient'
|
|
11
15
|
import { AuthManager } from './auth'
|
|
12
16
|
import {
|
|
13
17
|
ServerType,
|
|
@@ -36,7 +40,6 @@ const defaultConfig: SASjsConfig = {
|
|
|
36
40
|
debug: false,
|
|
37
41
|
contextName: 'SAS Job Execution compute context',
|
|
38
42
|
useComputeApi: null,
|
|
39
|
-
allowInsecureRequests: false,
|
|
40
43
|
loginMechanism: LoginMechanism.Default
|
|
41
44
|
}
|
|
42
45
|
|
|
@@ -49,6 +52,7 @@ export default class SASjs {
|
|
|
49
52
|
private jobsPath: string = ''
|
|
50
53
|
private sasViyaApiClient: SASViyaApiClient | null = null
|
|
51
54
|
private sas9ApiClient: SAS9ApiClient | null = null
|
|
55
|
+
private SASjsApiClient: SASjsApiClient | null = null
|
|
52
56
|
private fileUploader: FileUploader | null = null
|
|
53
57
|
private authManager: AuthManager | null = null
|
|
54
58
|
private requestClient: RequestClient | null = null
|
|
@@ -57,7 +61,7 @@ export default class SASjs {
|
|
|
57
61
|
private jesJobExecutor: JobExecutor | null = null
|
|
58
62
|
private sas9JobExecutor: JobExecutor | null = null
|
|
59
63
|
|
|
60
|
-
constructor(config?:
|
|
64
|
+
constructor(config?: Partial<SASjsConfig>) {
|
|
61
65
|
this.sasjsConfig = {
|
|
62
66
|
...defaultConfig,
|
|
63
67
|
...config
|
|
@@ -792,7 +796,7 @@ export default class SASjs {
|
|
|
792
796
|
sasApiClient = new SAS9ApiClient(
|
|
793
797
|
serverUrl,
|
|
794
798
|
this.jobsPath,
|
|
795
|
-
this.sasjsConfig.
|
|
799
|
+
this.sasjsConfig.httpsAgentOptions
|
|
796
800
|
)
|
|
797
801
|
}
|
|
798
802
|
} else {
|
|
@@ -824,6 +828,14 @@ export default class SASjs {
|
|
|
824
828
|
)
|
|
825
829
|
}
|
|
826
830
|
|
|
831
|
+
public async deployToSASjs(members: [FolderMember, ServiceMember]) {
|
|
832
|
+
return await this.SASjsApiClient?.deploy(members, this.sasjsConfig.appLoc)
|
|
833
|
+
}
|
|
834
|
+
|
|
835
|
+
public async executeJobSASjs(query: ExecutionQuery) {
|
|
836
|
+
return await this.SASjsApiClient?.executeJob(query)
|
|
837
|
+
}
|
|
838
|
+
|
|
827
839
|
/**
|
|
828
840
|
* Kicks off execution of the given job via the compute API.
|
|
829
841
|
* @returns an object representing the compute session created for the given job.
|
|
@@ -951,12 +963,12 @@ export default class SASjs {
|
|
|
951
963
|
if (!this.requestClient) {
|
|
952
964
|
this.requestClient = new RequestClient(
|
|
953
965
|
this.sasjsConfig.serverUrl,
|
|
954
|
-
this.sasjsConfig.
|
|
966
|
+
this.sasjsConfig.httpsAgentOptions
|
|
955
967
|
)
|
|
956
968
|
} else {
|
|
957
969
|
this.requestClient.setConfig(
|
|
958
970
|
this.sasjsConfig.serverUrl,
|
|
959
|
-
this.sasjsConfig.
|
|
971
|
+
this.sasjsConfig.httpsAgentOptions
|
|
960
972
|
)
|
|
961
973
|
}
|
|
962
974
|
|
|
@@ -973,30 +985,44 @@ export default class SASjs {
|
|
|
973
985
|
)
|
|
974
986
|
|
|
975
987
|
if (this.sasjsConfig.serverType === ServerType.SasViya) {
|
|
976
|
-
if (this.sasViyaApiClient)
|
|
988
|
+
if (this.sasViyaApiClient) {
|
|
977
989
|
this.sasViyaApiClient!.setConfig(
|
|
978
990
|
this.sasjsConfig.serverUrl,
|
|
979
991
|
this.sasjsConfig.appLoc
|
|
980
992
|
)
|
|
981
|
-
else
|
|
993
|
+
} else {
|
|
982
994
|
this.sasViyaApiClient = new SASViyaApiClient(
|
|
983
995
|
this.sasjsConfig.serverUrl,
|
|
984
996
|
this.sasjsConfig.appLoc,
|
|
985
997
|
this.sasjsConfig.contextName,
|
|
986
998
|
this.requestClient
|
|
987
999
|
)
|
|
1000
|
+
}
|
|
988
1001
|
|
|
989
1002
|
this.sasViyaApiClient.debug = this.sasjsConfig.debug
|
|
990
1003
|
}
|
|
1004
|
+
|
|
991
1005
|
if (this.sasjsConfig.serverType === ServerType.Sas9) {
|
|
992
|
-
if (this.sas9ApiClient)
|
|
1006
|
+
if (this.sas9ApiClient) {
|
|
993
1007
|
this.sas9ApiClient!.setConfig(this.sasjsConfig.serverUrl)
|
|
994
|
-
else
|
|
1008
|
+
} else {
|
|
995
1009
|
this.sas9ApiClient = new SAS9ApiClient(
|
|
996
1010
|
this.sasjsConfig.serverUrl,
|
|
997
1011
|
this.jobsPath,
|
|
998
|
-
this.sasjsConfig.
|
|
1012
|
+
this.sasjsConfig.httpsAgentOptions
|
|
999
1013
|
)
|
|
1014
|
+
}
|
|
1015
|
+
}
|
|
1016
|
+
|
|
1017
|
+
if (this.sasjsConfig.serverType === ServerType.Sasjs) {
|
|
1018
|
+
if (this.SASjsApiClient) {
|
|
1019
|
+
this.SASjsApiClient.setConfig(this.sasjsConfig.serverUrl)
|
|
1020
|
+
} else {
|
|
1021
|
+
this.SASjsApiClient = new SASjsApiClient(
|
|
1022
|
+
this.sasjsConfig.serverUrl,
|
|
1023
|
+
this.requestClient
|
|
1024
|
+
)
|
|
1025
|
+
}
|
|
1000
1026
|
}
|
|
1001
1027
|
|
|
1002
1028
|
this.fileUploader = new FileUploader(
|
|
@@ -1018,7 +1044,8 @@ export default class SASjs {
|
|
|
1018
1044
|
this.sasjsConfig.serverUrl,
|
|
1019
1045
|
this.sasjsConfig.serverType!,
|
|
1020
1046
|
this.jobsPath,
|
|
1021
|
-
this.
|
|
1047
|
+
this.requestClient,
|
|
1048
|
+
this.sasjsConfig.httpsAgentOptions
|
|
1022
1049
|
)
|
|
1023
1050
|
|
|
1024
1051
|
this.computeJobExecutor = new ComputeJobExecutor(
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { FolderMember, ServiceMember, ExecutionQuery } from './types'
|
|
2
|
+
import { RequestClient } from './request/RequestClient'
|
|
3
|
+
|
|
4
|
+
export class SASjsApiClient {
|
|
5
|
+
constructor(
|
|
6
|
+
private serverUrl: string,
|
|
7
|
+
private requestClient: RequestClient
|
|
8
|
+
) {}
|
|
9
|
+
|
|
10
|
+
public setConfig(serverUrl: string) {
|
|
11
|
+
if (serverUrl) this.serverUrl = serverUrl
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
public async deploy(members: [FolderMember, ServiceMember], appLoc: string) {
|
|
15
|
+
const { result } = await this.requestClient.post<{
|
|
16
|
+
status: string
|
|
17
|
+
message: string
|
|
18
|
+
example?: {}
|
|
19
|
+
}>(
|
|
20
|
+
'SASjsApi/drive/deploy',
|
|
21
|
+
{ fileTree: members, appLoc: appLoc },
|
|
22
|
+
undefined
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
return Promise.resolve(result)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
public async executeJob(query: ExecutionQuery) {
|
|
29
|
+
const { result } = await this.requestClient.post<{
|
|
30
|
+
status: string
|
|
31
|
+
message: string
|
|
32
|
+
log?: string
|
|
33
|
+
logPath?: string
|
|
34
|
+
error?: {}
|
|
35
|
+
}>('SASjsApi/stp/execute', query, undefined)
|
|
36
|
+
|
|
37
|
+
return Promise.resolve(result)
|
|
38
|
+
}
|
|
39
|
+
}
|
package/src/auth/AuthManager.ts
CHANGED
|
@@ -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
|
|
17
|
+
private sas9RequestClient: Sas9RequestClient
|
|
16
18
|
constructor(
|
|
17
19
|
serverUrl: string,
|
|
18
20
|
serverType: ServerType,
|
|
19
21
|
private jobsPath: string,
|
|
20
|
-
|
|
22
|
+
private requestClient: RequestClient,
|
|
23
|
+
httpsAgentOptions?: https.AgentOptions
|
|
21
24
|
) {
|
|
22
25
|
super(serverUrl, serverType)
|
|
23
|
-
this.
|
|
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.
|
|
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
|
-
|
|
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 {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import
|
|
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 {
|
|
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(
|
|
58
|
-
|
|
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,
|
|
62
|
-
this.createHttpClient(baseUrl,
|
|
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,23 +519,18 @@ export class RequestClient implements HttpClient {
|
|
|
511
519
|
return responseToReturn
|
|
512
520
|
}
|
|
513
521
|
|
|
514
|
-
private createHttpClient(
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
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
|
-
status >= 200 && status <
|
|
533
|
+
status >= 200 && status < 401
|
|
531
534
|
}
|
|
532
535
|
}
|
|
533
536
|
|
|
@@ -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,
|
|
13
|
-
super(baseUrl,
|
|
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
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import express = require('express')
|
|
2
|
+
|
|
3
|
+
export const app = express()
|
|
4
|
+
|
|
5
|
+
export const mockedAuthResponse = {
|
|
6
|
+
access_token: 'access_token',
|
|
7
|
+
token_type: 'bearer',
|
|
8
|
+
id_token: 'id_token',
|
|
9
|
+
refresh_token: 'refresh_token',
|
|
10
|
+
expires_in: 43199,
|
|
11
|
+
scope: 'openid',
|
|
12
|
+
jti: 'jti'
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
app.get('/', function (req: any, res: any) {
|
|
16
|
+
res.send('Hello World')
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
app.post('/SASLogon/oauth/token', function (req: any, res: any) {
|
|
20
|
+
let valid = true
|
|
21
|
+
// capture the encoded form data
|
|
22
|
+
req.on('data', (data: any) => {
|
|
23
|
+
const resData = data.toString()
|
|
24
|
+
|
|
25
|
+
if (resData.includes('incorrect')) valid = false
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
// send a response when finished reading
|
|
29
|
+
// the encoded form data
|
|
30
|
+
req.on('end', () => {
|
|
31
|
+
if (valid) res.status(200).send(mockedAuthResponse)
|
|
32
|
+
else
|
|
33
|
+
res.status(401).send({
|
|
34
|
+
error: 'unauthorized',
|
|
35
|
+
error_description: 'Bad credentials'
|
|
36
|
+
})
|
|
37
|
+
})
|
|
38
|
+
})
|