@sasjs/adapter 4.8.0 → 4.9.1
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/README.md +1 -1
- package/SASjs.d.ts +22 -7
- package/index-dev.js +2 -2
- package/index.js +1 -1
- package/minified/sas9/SASjs.d.ts +1 -1
- package/minified_sas9.js +1 -1
- package/node/SASjs.d.ts +22 -7
- package/node/index.js +1 -1
- package/node/request/RequestClient.d.ts +11 -33
- package/node/request/SasjsRequestClient.d.ts +1 -7
- package/node/types/RequestClient.d.ts +46 -0
- package/node/types/SASjsConfig.d.ts +2 -1
- package/node/types/index.d.ts +3 -1
- package/node/utils/compareTimestamps.d.ts +1 -1
- package/package.json +1 -1
- package/request/RequestClient.d.ts +11 -33
- package/request/SasjsRequestClient.d.ts +1 -7
- package/src/SASjs.ts +40 -10
- package/src/api/viya/executeScript.ts +1 -1
- package/src/request/RequestClient.ts +96 -44
- package/src/request/SasjsRequestClient.ts +1 -9
- package/src/types/RequestClient.ts +55 -0
- package/src/types/SASjsConfig.ts +2 -1
- package/src/types/index.ts +3 -1
- package/src/utils/compareTimestamps.ts +1 -1
- package/types/RequestClient.d.ts +46 -0
- package/types/SASjsConfig.d.ts +2 -1
- package/types/index.d.ts +3 -1
- package/utils/compareTimestamps.d.ts +1 -1
- package/node/types/SASjsRequest.d.ts +0 -12
- package/src/types/SASjsRequest.ts +0 -12
- package/types/SASjsRequest.d.ts +0 -12
|
@@ -1,46 +1,18 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
|
-
import { AxiosInstance, AxiosResponse } from 'axios';
|
|
2
|
+
import { AxiosError, AxiosInstance, AxiosResponse } from 'axios';
|
|
3
3
|
import * as https from 'https';
|
|
4
4
|
import { CsrfToken } from '..';
|
|
5
|
-
import { SASjsRequest } from '../types';
|
|
6
|
-
export interface HttpClient {
|
|
7
|
-
get<T>(url: string, accessToken: string | undefined, contentType: string, overrideHeaders: {
|
|
8
|
-
[key: string]: string | number;
|
|
9
|
-
}): Promise<{
|
|
10
|
-
result: T;
|
|
11
|
-
etag: string;
|
|
12
|
-
}>;
|
|
13
|
-
post<T>(url: string, data: any, accessToken: string | undefined, contentType: string, overrideHeaders: {
|
|
14
|
-
[key: string]: string | number;
|
|
15
|
-
}): Promise<{
|
|
16
|
-
result: T;
|
|
17
|
-
etag: string;
|
|
18
|
-
}>;
|
|
19
|
-
put<T>(url: string, data: any, accessToken: string | undefined, overrideHeaders: {
|
|
20
|
-
[key: string]: string | number;
|
|
21
|
-
}): Promise<{
|
|
22
|
-
result: T;
|
|
23
|
-
etag: string;
|
|
24
|
-
}>;
|
|
25
|
-
delete<T>(url: string, accessToken: string | undefined): Promise<{
|
|
26
|
-
result: T;
|
|
27
|
-
etag: string;
|
|
28
|
-
}>;
|
|
29
|
-
getCsrfToken(type: 'general' | 'file'): CsrfToken | undefined;
|
|
30
|
-
saveLocalStorageToken(accessToken: string, refreshToken: string): void;
|
|
31
|
-
clearCsrfTokens(): void;
|
|
32
|
-
clearLocalStorageTokens(): void;
|
|
33
|
-
getBaseUrl(): string;
|
|
34
|
-
}
|
|
5
|
+
import { SASjsRequest, HttpClient, VerboseMode } from '../types';
|
|
35
6
|
export declare class RequestClient implements HttpClient {
|
|
36
7
|
protected baseUrl: string;
|
|
37
8
|
private requests;
|
|
38
9
|
private requestsLimit;
|
|
39
10
|
private httpInterceptor?;
|
|
11
|
+
private verboseMode;
|
|
40
12
|
protected csrfToken: CsrfToken;
|
|
41
13
|
protected fileUploadCsrfToken: CsrfToken | undefined;
|
|
42
14
|
protected httpClient: AxiosInstance;
|
|
43
|
-
constructor(baseUrl: string, httpsAgentOptions?: https.AgentOptions, requestsLimit?: number, verboseMode?:
|
|
15
|
+
constructor(baseUrl: string, httpsAgentOptions?: https.AgentOptions, requestsLimit?: number, verboseMode?: VerboseMode);
|
|
44
16
|
setConfig(baseUrl: string, httpsAgentOptions?: https.AgentOptions): void;
|
|
45
17
|
saveLocalStorageToken(accessToken: string, refreshToken: string): void;
|
|
46
18
|
getCsrfToken(type?: 'general' | 'file'): CsrfToken | undefined;
|
|
@@ -96,6 +68,7 @@ export declare class RequestClient implements HttpClient {
|
|
|
96
68
|
authorize: (response: string) => Promise<any>;
|
|
97
69
|
/**
|
|
98
70
|
* Adds colors to the string.
|
|
71
|
+
* If verboseMode is set to 'bleached', colors should be disabled
|
|
99
72
|
* @param str - string to be prettified.
|
|
100
73
|
* @returns - prettified string
|
|
101
74
|
*/
|
|
@@ -107,12 +80,17 @@ export declare class RequestClient implements HttpClient {
|
|
|
107
80
|
*/
|
|
108
81
|
private parseInterceptedBody;
|
|
109
82
|
private defaultInterceptionCallBack;
|
|
83
|
+
/**
|
|
84
|
+
* Sets verbose mode.
|
|
85
|
+
* @param verboseMode - value of the verbose mode, can be true, false or bleached(without extra colors).
|
|
86
|
+
*/
|
|
87
|
+
setVerboseMode: (verboseMode: VerboseMode) => void;
|
|
110
88
|
/**
|
|
111
89
|
* Turns on verbose mode to log every HTTP response.
|
|
112
90
|
* @param successCallBack - function that should be triggered on every HTTP response with the status 2**.
|
|
113
91
|
* @param errorCallBack - function that should be triggered on every HTTP response with the status different from 2**.
|
|
114
92
|
*/
|
|
115
|
-
enableVerboseMode: (successCallBack?: (
|
|
93
|
+
enableVerboseMode: (successCallBack?: (axiosResponse: AxiosResponse | AxiosError) => AxiosResponse<any, any> | AxiosError<unknown, any>, errorCallBack?: (axiosResponse: AxiosResponse | AxiosError) => AxiosResponse<any, any> | AxiosError<unknown, any>) => void;
|
|
116
94
|
/**
|
|
117
95
|
* Turns off verbose mode to log every HTTP response.
|
|
118
96
|
*/
|
|
@@ -1,12 +1,6 @@
|
|
|
1
1
|
import { RequestClient } from './RequestClient';
|
|
2
2
|
import { AxiosResponse } from 'axios';
|
|
3
|
-
|
|
4
|
-
result: T;
|
|
5
|
-
log: string;
|
|
6
|
-
etag: string;
|
|
7
|
-
status: number;
|
|
8
|
-
printOutput?: string;
|
|
9
|
-
}
|
|
3
|
+
import { SasjsParsedResponse } from '../types';
|
|
10
4
|
/**
|
|
11
5
|
* Specific request client for SASJS.
|
|
12
6
|
* Append tokens in headers.
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { CsrfToken } from '..';
|
|
2
|
+
export interface HttpClient {
|
|
3
|
+
get<T>(url: string, accessToken: string | undefined, contentType: string, overrideHeaders: {
|
|
4
|
+
[key: string]: string | number;
|
|
5
|
+
}): Promise<{
|
|
6
|
+
result: T;
|
|
7
|
+
etag: string;
|
|
8
|
+
}>;
|
|
9
|
+
post<T>(url: string, data: any, accessToken: string | undefined, contentType: string, overrideHeaders: {
|
|
10
|
+
[key: string]: string | number;
|
|
11
|
+
}): Promise<{
|
|
12
|
+
result: T;
|
|
13
|
+
etag: string;
|
|
14
|
+
}>;
|
|
15
|
+
put<T>(url: string, data: any, accessToken: string | undefined, overrideHeaders: {
|
|
16
|
+
[key: string]: string | number;
|
|
17
|
+
}): Promise<{
|
|
18
|
+
result: T;
|
|
19
|
+
etag: string;
|
|
20
|
+
}>;
|
|
21
|
+
delete<T>(url: string, accessToken: string | undefined): Promise<{
|
|
22
|
+
result: T;
|
|
23
|
+
etag: string;
|
|
24
|
+
}>;
|
|
25
|
+
getCsrfToken(type: 'general' | 'file'): CsrfToken | undefined;
|
|
26
|
+
saveLocalStorageToken(accessToken: string, refreshToken: string): void;
|
|
27
|
+
clearCsrfTokens(): void;
|
|
28
|
+
clearLocalStorageTokens(): void;
|
|
29
|
+
getBaseUrl(): string;
|
|
30
|
+
}
|
|
31
|
+
export interface SASjsRequest {
|
|
32
|
+
serviceLink: string;
|
|
33
|
+
timestamp: Date;
|
|
34
|
+
sourceCode: string;
|
|
35
|
+
generatedCode: string;
|
|
36
|
+
logFile: string;
|
|
37
|
+
SASWORK: any;
|
|
38
|
+
}
|
|
39
|
+
export interface SasjsParsedResponse<T> {
|
|
40
|
+
result: T;
|
|
41
|
+
log: string;
|
|
42
|
+
etag: string;
|
|
43
|
+
status: number;
|
|
44
|
+
printOutput?: string;
|
|
45
|
+
}
|
|
46
|
+
export declare type VerboseMode = boolean | 'bleached';
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
import * as https from 'https';
|
|
3
3
|
import { ServerType } from '@sasjs/utils/types';
|
|
4
|
+
import { VerboseMode } from '../types';
|
|
4
5
|
/**
|
|
5
6
|
* Specifies the configuration for the SASjs instance - eg where and how to
|
|
6
7
|
* connect to SAS.
|
|
@@ -48,7 +49,7 @@ export declare class SASjsConfig {
|
|
|
48
49
|
/**
|
|
49
50
|
* Set to `true` to enable verbose mode that will log a summary of every HTTP response.
|
|
50
51
|
*/
|
|
51
|
-
verbose?:
|
|
52
|
+
verbose?: VerboseMode;
|
|
52
53
|
/**
|
|
53
54
|
* The name of the compute context to use when calling the Viya services directly.
|
|
54
55
|
* Example value: 'SAS Job Execution compute context'
|
package/node/types/index.d.ts
CHANGED
|
@@ -6,10 +6,12 @@ export * from './Job';
|
|
|
6
6
|
export * from './JobDefinition';
|
|
7
7
|
export * from './JobResult';
|
|
8
8
|
export * from './Link';
|
|
9
|
+
export * from './Login';
|
|
9
10
|
export * from './SASjsConfig';
|
|
10
|
-
export * from './
|
|
11
|
+
export * from './RequestClient';
|
|
11
12
|
export * from './Session';
|
|
12
13
|
export * from './UploadFile';
|
|
13
14
|
export * from './PollOptions';
|
|
14
15
|
export * from './WriteStream';
|
|
15
16
|
export * from './ExecuteScript';
|
|
17
|
+
export * from './errors';
|
package/package.json
CHANGED
|
@@ -1,46 +1,18 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
|
-
import { AxiosInstance, AxiosResponse } from 'axios';
|
|
2
|
+
import { AxiosError, AxiosInstance, AxiosResponse } from 'axios';
|
|
3
3
|
import * as https from 'https';
|
|
4
4
|
import { CsrfToken } from '..';
|
|
5
|
-
import { SASjsRequest } from '../types';
|
|
6
|
-
export interface HttpClient {
|
|
7
|
-
get<T>(url: string, accessToken: string | undefined, contentType: string, overrideHeaders: {
|
|
8
|
-
[key: string]: string | number;
|
|
9
|
-
}): Promise<{
|
|
10
|
-
result: T;
|
|
11
|
-
etag: string;
|
|
12
|
-
}>;
|
|
13
|
-
post<T>(url: string, data: any, accessToken: string | undefined, contentType: string, overrideHeaders: {
|
|
14
|
-
[key: string]: string | number;
|
|
15
|
-
}): Promise<{
|
|
16
|
-
result: T;
|
|
17
|
-
etag: string;
|
|
18
|
-
}>;
|
|
19
|
-
put<T>(url: string, data: any, accessToken: string | undefined, overrideHeaders: {
|
|
20
|
-
[key: string]: string | number;
|
|
21
|
-
}): Promise<{
|
|
22
|
-
result: T;
|
|
23
|
-
etag: string;
|
|
24
|
-
}>;
|
|
25
|
-
delete<T>(url: string, accessToken: string | undefined): Promise<{
|
|
26
|
-
result: T;
|
|
27
|
-
etag: string;
|
|
28
|
-
}>;
|
|
29
|
-
getCsrfToken(type: 'general' | 'file'): CsrfToken | undefined;
|
|
30
|
-
saveLocalStorageToken(accessToken: string, refreshToken: string): void;
|
|
31
|
-
clearCsrfTokens(): void;
|
|
32
|
-
clearLocalStorageTokens(): void;
|
|
33
|
-
getBaseUrl(): string;
|
|
34
|
-
}
|
|
5
|
+
import { SASjsRequest, HttpClient, VerboseMode } from '../types';
|
|
35
6
|
export declare class RequestClient implements HttpClient {
|
|
36
7
|
protected baseUrl: string;
|
|
37
8
|
private requests;
|
|
38
9
|
private requestsLimit;
|
|
39
10
|
private httpInterceptor?;
|
|
11
|
+
private verboseMode;
|
|
40
12
|
protected csrfToken: CsrfToken;
|
|
41
13
|
protected fileUploadCsrfToken: CsrfToken | undefined;
|
|
42
14
|
protected httpClient: AxiosInstance;
|
|
43
|
-
constructor(baseUrl: string, httpsAgentOptions?: https.AgentOptions, requestsLimit?: number, verboseMode?:
|
|
15
|
+
constructor(baseUrl: string, httpsAgentOptions?: https.AgentOptions, requestsLimit?: number, verboseMode?: VerboseMode);
|
|
44
16
|
setConfig(baseUrl: string, httpsAgentOptions?: https.AgentOptions): void;
|
|
45
17
|
saveLocalStorageToken(accessToken: string, refreshToken: string): void;
|
|
46
18
|
getCsrfToken(type?: 'general' | 'file'): CsrfToken | undefined;
|
|
@@ -96,6 +68,7 @@ export declare class RequestClient implements HttpClient {
|
|
|
96
68
|
authorize: (response: string) => Promise<any>;
|
|
97
69
|
/**
|
|
98
70
|
* Adds colors to the string.
|
|
71
|
+
* If verboseMode is set to 'bleached', colors should be disabled
|
|
99
72
|
* @param str - string to be prettified.
|
|
100
73
|
* @returns - prettified string
|
|
101
74
|
*/
|
|
@@ -107,12 +80,17 @@ export declare class RequestClient implements HttpClient {
|
|
|
107
80
|
*/
|
|
108
81
|
private parseInterceptedBody;
|
|
109
82
|
private defaultInterceptionCallBack;
|
|
83
|
+
/**
|
|
84
|
+
* Sets verbose mode.
|
|
85
|
+
* @param verboseMode - value of the verbose mode, can be true, false or bleached(without extra colors).
|
|
86
|
+
*/
|
|
87
|
+
setVerboseMode: (verboseMode: VerboseMode) => void;
|
|
110
88
|
/**
|
|
111
89
|
* Turns on verbose mode to log every HTTP response.
|
|
112
90
|
* @param successCallBack - function that should be triggered on every HTTP response with the status 2**.
|
|
113
91
|
* @param errorCallBack - function that should be triggered on every HTTP response with the status different from 2**.
|
|
114
92
|
*/
|
|
115
|
-
enableVerboseMode: (successCallBack?: (
|
|
93
|
+
enableVerboseMode: (successCallBack?: (axiosResponse: AxiosResponse | AxiosError) => AxiosResponse<any, any> | AxiosError<unknown, any>, errorCallBack?: (axiosResponse: AxiosResponse | AxiosError) => AxiosResponse<any, any> | AxiosError<unknown, any>) => void;
|
|
116
94
|
/**
|
|
117
95
|
* Turns off verbose mode to log every HTTP response.
|
|
118
96
|
*/
|
|
@@ -1,12 +1,6 @@
|
|
|
1
1
|
import { RequestClient } from './RequestClient';
|
|
2
2
|
import { AxiosResponse } from 'axios';
|
|
3
|
-
|
|
4
|
-
result: T;
|
|
5
|
-
log: string;
|
|
6
|
-
etag: string;
|
|
7
|
-
status: number;
|
|
8
|
-
printOutput?: string;
|
|
9
|
-
}
|
|
3
|
+
import { SasjsParsedResponse } from '../types';
|
|
10
4
|
/**
|
|
11
5
|
* Specific request client for SASJS.
|
|
12
6
|
* Append tokens in headers.
|
package/src/SASjs.ts
CHANGED
|
@@ -4,7 +4,12 @@ import {
|
|
|
4
4
|
UploadFile,
|
|
5
5
|
EditContextInput,
|
|
6
6
|
PollOptions,
|
|
7
|
-
LoginMechanism
|
|
7
|
+
LoginMechanism,
|
|
8
|
+
VerboseMode,
|
|
9
|
+
ErrorResponse,
|
|
10
|
+
LoginOptions,
|
|
11
|
+
LoginResult,
|
|
12
|
+
ExecutionQuery
|
|
8
13
|
} from './types'
|
|
9
14
|
import { SASViyaApiClient } from './SASViyaApiClient'
|
|
10
15
|
import { SAS9ApiClient } from './SAS9ApiClient'
|
|
@@ -29,9 +34,7 @@ import {
|
|
|
29
34
|
Sas9JobExecutor,
|
|
30
35
|
FileUploader
|
|
31
36
|
} from './job-execution'
|
|
32
|
-
import {
|
|
33
|
-
import { LoginOptions, LoginResult } from './types/Login'
|
|
34
|
-
import { AxiosResponse } from 'axios'
|
|
37
|
+
import { AxiosResponse, AxiosError } from 'axios'
|
|
35
38
|
|
|
36
39
|
interface ExecuteScriptParams {
|
|
37
40
|
linesOfCode: string[]
|
|
@@ -158,6 +161,23 @@ export default class SASjs {
|
|
|
158
161
|
}
|
|
159
162
|
}
|
|
160
163
|
|
|
164
|
+
/**
|
|
165
|
+
* Executes job on SASJS server.
|
|
166
|
+
* @param query - an object containing job path and debug level.
|
|
167
|
+
* @param appLoc - an application path.
|
|
168
|
+
* @param authConfig - an object for authentication.
|
|
169
|
+
* @returns a promise that resolves into job execution result and log.
|
|
170
|
+
*/
|
|
171
|
+
public async executeJob(
|
|
172
|
+
query: ExecutionQuery,
|
|
173
|
+
appLoc: string,
|
|
174
|
+
authConfig?: AuthConfig
|
|
175
|
+
) {
|
|
176
|
+
this.isMethodSupported('executeScript', [ServerType.Sasjs])
|
|
177
|
+
|
|
178
|
+
return await this.sasJSApiClient?.executeJob(query, appLoc, authConfig)
|
|
179
|
+
}
|
|
180
|
+
|
|
161
181
|
/**
|
|
162
182
|
* Gets compute contexts.
|
|
163
183
|
* @param accessToken - an access token for an authorised user.
|
|
@@ -855,7 +875,7 @@ export default class SASjs {
|
|
|
855
875
|
* @param pollOptions - an object that represents poll interval(milliseconds) and maximum amount of attempts. Object example: { maxPollCount: 24 * 60 * 60, pollInterval: 1000 }. More information available at src/api/viya/pollJobState.ts.
|
|
856
876
|
* @param printPid - a boolean that indicates whether the function should print (PID) of the started job.
|
|
857
877
|
* @param variables - an object that represents macro variables.
|
|
858
|
-
* @param verboseMode - boolean to enable verbose mode (log every HTTP response).
|
|
878
|
+
* @param verboseMode - boolean or a string equal to 'bleached' to enable verbose mode (log every HTTP response).
|
|
859
879
|
*/
|
|
860
880
|
public async startComputeJob(
|
|
861
881
|
sasJob: string,
|
|
@@ -866,7 +886,7 @@ export default class SASjs {
|
|
|
866
886
|
pollOptions?: PollOptions,
|
|
867
887
|
printPid = false,
|
|
868
888
|
variables?: MacroVar,
|
|
869
|
-
verboseMode?:
|
|
889
|
+
verboseMode?: VerboseMode
|
|
870
890
|
) {
|
|
871
891
|
config = {
|
|
872
892
|
...this.sasjsConfig,
|
|
@@ -880,8 +900,10 @@ export default class SASjs {
|
|
|
880
900
|
)
|
|
881
901
|
}
|
|
882
902
|
|
|
883
|
-
if (verboseMode)
|
|
884
|
-
|
|
903
|
+
if (verboseMode) {
|
|
904
|
+
this.requestClient?.setVerboseMode(verboseMode)
|
|
905
|
+
this.requestClient?.enableVerboseMode()
|
|
906
|
+
} else if (verboseMode === false) this.requestClient?.disableVerboseMode()
|
|
885
907
|
|
|
886
908
|
return this.sasViyaApiClient?.executeComputeJob(
|
|
887
909
|
sasJob,
|
|
@@ -1148,8 +1170,8 @@ export default class SASjs {
|
|
|
1148
1170
|
* @param errorCallBack - function that should be triggered on every HTTP response with the status different from 2**.
|
|
1149
1171
|
*/
|
|
1150
1172
|
public enableVerboseMode(
|
|
1151
|
-
successCallBack?: (response: AxiosResponse) => AxiosResponse,
|
|
1152
|
-
errorCallBack?: (response: AxiosResponse) => AxiosResponse
|
|
1173
|
+
successCallBack?: (response: AxiosResponse | AxiosError) => AxiosResponse,
|
|
1174
|
+
errorCallBack?: (response: AxiosResponse | AxiosError) => AxiosResponse
|
|
1153
1175
|
) {
|
|
1154
1176
|
this.requestClient?.enableVerboseMode(successCallBack, errorCallBack)
|
|
1155
1177
|
}
|
|
@@ -1160,4 +1182,12 @@ export default class SASjs {
|
|
|
1160
1182
|
public disableVerboseMode() {
|
|
1161
1183
|
this.requestClient?.disableVerboseMode()
|
|
1162
1184
|
}
|
|
1185
|
+
|
|
1186
|
+
/**
|
|
1187
|
+
* Sets verbose mode.
|
|
1188
|
+
* @param verboseMode - value of the verbose mode, can be true, false or bleached(without extra colors).
|
|
1189
|
+
*/
|
|
1190
|
+
public setVerboseMode = (verboseMode: VerboseMode) => {
|
|
1191
|
+
this.requestClient?.setVerboseMode(verboseMode)
|
|
1192
|
+
}
|
|
1163
1193
|
}
|
|
@@ -78,7 +78,7 @@ export async function executeScript(
|
|
|
78
78
|
const logger = process.logger || console
|
|
79
79
|
|
|
80
80
|
logger.info(
|
|
81
|
-
`
|
|
81
|
+
`Triggering '${relativeJobPath}' with PID ${
|
|
82
82
|
jobIdVariable.value
|
|
83
83
|
} at ${timestampToYYYYMMDDHHMMSS()}`
|
|
84
84
|
)
|
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
AxiosError,
|
|
3
|
+
AxiosInstance,
|
|
4
|
+
AxiosRequestConfig,
|
|
5
|
+
AxiosResponse
|
|
6
|
+
} from 'axios'
|
|
7
|
+
import axios from 'axios'
|
|
2
8
|
import * as https from 'https'
|
|
3
9
|
import { CsrfToken } from '..'
|
|
4
10
|
import { isAuthorizeFormRequired, isLogInRequired } from '../auth'
|
|
@@ -10,7 +16,7 @@ import {
|
|
|
10
16
|
JobExecutionError,
|
|
11
17
|
CertificateError
|
|
12
18
|
} from '../types/errors'
|
|
13
|
-
import { SASjsRequest } from '../types'
|
|
19
|
+
import { SASjsRequest, HttpClient, VerboseMode } from '../types'
|
|
14
20
|
import { parseWeboutResponse } from '../utils/parseWeboutResponse'
|
|
15
21
|
import { prefixMessage } from '@sasjs/utils/error'
|
|
16
22
|
import { SAS9AuthError } from '../types/errors/SAS9AuthError'
|
|
@@ -22,45 +28,11 @@ import {
|
|
|
22
28
|
import { InvalidSASjsCsrfError } from '../types/errors/InvalidSASjsCsrfError'
|
|
23
29
|
import { inspect } from 'util'
|
|
24
30
|
|
|
25
|
-
export interface HttpClient {
|
|
26
|
-
get<T>(
|
|
27
|
-
url: string,
|
|
28
|
-
accessToken: string | undefined,
|
|
29
|
-
contentType: string,
|
|
30
|
-
overrideHeaders: { [key: string]: string | number }
|
|
31
|
-
): Promise<{ result: T; etag: string }>
|
|
32
|
-
|
|
33
|
-
post<T>(
|
|
34
|
-
url: string,
|
|
35
|
-
data: any,
|
|
36
|
-
accessToken: string | undefined,
|
|
37
|
-
contentType: string,
|
|
38
|
-
overrideHeaders: { [key: string]: string | number }
|
|
39
|
-
): Promise<{ result: T; etag: string }>
|
|
40
|
-
|
|
41
|
-
put<T>(
|
|
42
|
-
url: string,
|
|
43
|
-
data: any,
|
|
44
|
-
accessToken: string | undefined,
|
|
45
|
-
overrideHeaders: { [key: string]: string | number }
|
|
46
|
-
): Promise<{ result: T; etag: string }>
|
|
47
|
-
|
|
48
|
-
delete<T>(
|
|
49
|
-
url: string,
|
|
50
|
-
accessToken: string | undefined
|
|
51
|
-
): Promise<{ result: T; etag: string }>
|
|
52
|
-
|
|
53
|
-
getCsrfToken(type: 'general' | 'file'): CsrfToken | undefined
|
|
54
|
-
saveLocalStorageToken(accessToken: string, refreshToken: string): void
|
|
55
|
-
clearCsrfTokens(): void
|
|
56
|
-
clearLocalStorageTokens(): void
|
|
57
|
-
getBaseUrl(): string
|
|
58
|
-
}
|
|
59
|
-
|
|
60
31
|
export class RequestClient implements HttpClient {
|
|
61
32
|
private requests: SASjsRequest[] = []
|
|
62
33
|
private requestsLimit: number = 10
|
|
63
34
|
private httpInterceptor?: number
|
|
35
|
+
private verboseMode: VerboseMode = false
|
|
64
36
|
|
|
65
37
|
protected csrfToken: CsrfToken = { headerName: '', value: '' }
|
|
66
38
|
protected fileUploadCsrfToken: CsrfToken | undefined
|
|
@@ -70,13 +42,16 @@ export class RequestClient implements HttpClient {
|
|
|
70
42
|
protected baseUrl: string,
|
|
71
43
|
httpsAgentOptions?: https.AgentOptions,
|
|
72
44
|
requestsLimit?: number,
|
|
73
|
-
verboseMode?:
|
|
45
|
+
verboseMode?: VerboseMode
|
|
74
46
|
) {
|
|
75
47
|
this.createHttpClient(baseUrl, httpsAgentOptions)
|
|
76
48
|
|
|
77
49
|
if (requestsLimit) this.requestsLimit = requestsLimit
|
|
78
50
|
|
|
79
|
-
if (verboseMode)
|
|
51
|
+
if (verboseMode) {
|
|
52
|
+
this.setVerboseMode(verboseMode)
|
|
53
|
+
this.enableVerboseMode()
|
|
54
|
+
}
|
|
80
55
|
}
|
|
81
56
|
|
|
82
57
|
public setConfig(baseUrl: string, httpsAgentOptions?: https.AgentOptions) {
|
|
@@ -96,6 +71,7 @@ export class RequestClient implements HttpClient {
|
|
|
96
71
|
this.csrfToken = { headerName: '', value: '' }
|
|
97
72
|
this.fileUploadCsrfToken = { headerName: '', value: '' }
|
|
98
73
|
}
|
|
74
|
+
|
|
99
75
|
public clearLocalStorageTokens() {
|
|
100
76
|
localStorage.setItem('accessToken', '')
|
|
101
77
|
localStorage.setItem('refreshToken', '')
|
|
@@ -398,10 +374,12 @@ export class RequestClient implements HttpClient {
|
|
|
398
374
|
|
|
399
375
|
/**
|
|
400
376
|
* Adds colors to the string.
|
|
377
|
+
* If verboseMode is set to 'bleached', colors should be disabled
|
|
401
378
|
* @param str - string to be prettified.
|
|
402
379
|
* @returns - prettified string
|
|
403
380
|
*/
|
|
404
|
-
private prettifyString = (str: any) =>
|
|
381
|
+
private prettifyString = (str: any) =>
|
|
382
|
+
inspect(str, { colors: this.verboseMode !== 'bleached' })
|
|
405
383
|
|
|
406
384
|
/**
|
|
407
385
|
* Formats HTTP request/response body.
|
|
@@ -435,10 +413,73 @@ export class RequestClient implements HttpClient {
|
|
|
435
413
|
return bodyLines.join('\n')
|
|
436
414
|
}
|
|
437
415
|
|
|
438
|
-
private defaultInterceptionCallBack = (
|
|
439
|
-
|
|
416
|
+
private defaultInterceptionCallBack = (
|
|
417
|
+
axiosResponse: AxiosResponse | AxiosError
|
|
418
|
+
) => {
|
|
419
|
+
// Message indicating absent value.
|
|
420
|
+
const noValueMessage = 'Not provided'
|
|
421
|
+
|
|
422
|
+
// Fallback request object that can be safely used to form request summary.
|
|
423
|
+
type FallbackRequest = { _header?: string; res: { rawHeaders: string[] } }
|
|
424
|
+
// _header is not present in responses with status 1**
|
|
425
|
+
// rawHeaders are not present in responses with status 1**
|
|
426
|
+
let fallbackRequest: FallbackRequest = {
|
|
427
|
+
_header: `${noValueMessage}\n`,
|
|
428
|
+
res: { rawHeaders: [noValueMessage] }
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
// Fallback response object that can be safely used to form response summary.
|
|
432
|
+
type FallbackResponse = {
|
|
433
|
+
status?: number | string
|
|
434
|
+
request?: FallbackRequest
|
|
435
|
+
config: { data?: string }
|
|
436
|
+
data?: unknown
|
|
437
|
+
}
|
|
438
|
+
let fallbackResponse: FallbackResponse = axiosResponse
|
|
439
|
+
|
|
440
|
+
if (axios.isAxiosError(axiosResponse)) {
|
|
441
|
+
const { response, request, config } = axiosResponse
|
|
442
|
+
|
|
443
|
+
// Try to use axiosResponse.response to form response summary.
|
|
444
|
+
if (response) {
|
|
445
|
+
fallbackResponse = response
|
|
446
|
+
} else {
|
|
447
|
+
// Try to use axiosResponse.request to form request summary.
|
|
448
|
+
if (request) {
|
|
449
|
+
const { _header, _currentRequest } = request
|
|
450
|
+
|
|
451
|
+
// Try to use axiosResponse.request._header to form request summary.
|
|
452
|
+
if (_header) {
|
|
453
|
+
fallbackRequest._header = _header
|
|
454
|
+
}
|
|
455
|
+
// Try to use axiosResponse.request._currentRequest._header to form request summary.
|
|
456
|
+
else if (_currentRequest && _currentRequest._header) {
|
|
457
|
+
fallbackRequest._header = _currentRequest._header
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
const { res } = request
|
|
461
|
+
|
|
462
|
+
// Try to use axiosResponse.request.res.rawHeaders to form request summary.
|
|
463
|
+
if (res && res.rawHeaders) {
|
|
464
|
+
fallbackRequest.res.rawHeaders = res.rawHeaders
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
// Fallback config that can be safely used to form response summary.
|
|
469
|
+
const fallbackConfig = { data: noValueMessage }
|
|
470
|
+
|
|
471
|
+
fallbackResponse = {
|
|
472
|
+
status: noValueMessage,
|
|
473
|
+
request: fallbackRequest,
|
|
474
|
+
config: config || fallbackConfig,
|
|
475
|
+
data: noValueMessage
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
const { status, config, request, data: resData } = fallbackResponse
|
|
440
481
|
const { data: reqData } = config
|
|
441
|
-
const { _header: reqHeaders, res } = request
|
|
482
|
+
const { _header: reqHeaders, res } = request || fallbackRequest
|
|
442
483
|
const { rawHeaders } = res
|
|
443
484
|
|
|
444
485
|
// Converts an array of strings into a single string with the following format:
|
|
@@ -468,7 +509,18 @@ HTTP Response (first 50 lines):
|
|
|
468
509
|
${resHeaders}${parsedResBody ? `\n\n${parsedResBody}` : ''}
|
|
469
510
|
`)
|
|
470
511
|
|
|
471
|
-
return
|
|
512
|
+
return axiosResponse
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
/**
|
|
516
|
+
* Sets verbose mode.
|
|
517
|
+
* @param verboseMode - value of the verbose mode, can be true, false or bleached(without extra colors).
|
|
518
|
+
*/
|
|
519
|
+
public setVerboseMode = (verboseMode: VerboseMode) => {
|
|
520
|
+
this.verboseMode = verboseMode
|
|
521
|
+
|
|
522
|
+
if (this.verboseMode) this.enableVerboseMode()
|
|
523
|
+
else this.disableVerboseMode()
|
|
472
524
|
}
|
|
473
525
|
|
|
474
526
|
/**
|
|
@@ -1,19 +1,11 @@
|
|
|
1
1
|
import { RequestClient } from './RequestClient'
|
|
2
2
|
import { AxiosResponse } from 'axios'
|
|
3
|
-
|
|
4
|
-
export interface SasjsParsedResponse<T> {
|
|
5
|
-
result: T
|
|
6
|
-
log: string
|
|
7
|
-
etag: string
|
|
8
|
-
status: number
|
|
9
|
-
printOutput?: string
|
|
10
|
-
}
|
|
3
|
+
import { SasjsParsedResponse } from '../types'
|
|
11
4
|
|
|
12
5
|
/**
|
|
13
6
|
* Specific request client for SASJS.
|
|
14
7
|
* Append tokens in headers.
|
|
15
8
|
*/
|
|
16
|
-
|
|
17
9
|
export class SasjsRequestClient extends RequestClient {
|
|
18
10
|
getHeaders = (accessToken: string | undefined, contentType: string) => {
|
|
19
11
|
const headers: any = {}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { CsrfToken } from '..'
|
|
2
|
+
|
|
3
|
+
export interface HttpClient {
|
|
4
|
+
get<T>(
|
|
5
|
+
url: string,
|
|
6
|
+
accessToken: string | undefined,
|
|
7
|
+
contentType: string,
|
|
8
|
+
overrideHeaders: { [key: string]: string | number }
|
|
9
|
+
): Promise<{ result: T; etag: string }>
|
|
10
|
+
|
|
11
|
+
post<T>(
|
|
12
|
+
url: string,
|
|
13
|
+
data: any,
|
|
14
|
+
accessToken: string | undefined,
|
|
15
|
+
contentType: string,
|
|
16
|
+
overrideHeaders: { [key: string]: string | number }
|
|
17
|
+
): Promise<{ result: T; etag: string }>
|
|
18
|
+
|
|
19
|
+
put<T>(
|
|
20
|
+
url: string,
|
|
21
|
+
data: any,
|
|
22
|
+
accessToken: string | undefined,
|
|
23
|
+
overrideHeaders: { [key: string]: string | number }
|
|
24
|
+
): Promise<{ result: T; etag: string }>
|
|
25
|
+
|
|
26
|
+
delete<T>(
|
|
27
|
+
url: string,
|
|
28
|
+
accessToken: string | undefined
|
|
29
|
+
): Promise<{ result: T; etag: string }>
|
|
30
|
+
|
|
31
|
+
getCsrfToken(type: 'general' | 'file'): CsrfToken | undefined
|
|
32
|
+
saveLocalStorageToken(accessToken: string, refreshToken: string): void
|
|
33
|
+
clearCsrfTokens(): void
|
|
34
|
+
clearLocalStorageTokens(): void
|
|
35
|
+
getBaseUrl(): string
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface SASjsRequest {
|
|
39
|
+
serviceLink: string
|
|
40
|
+
timestamp: Date
|
|
41
|
+
sourceCode: string
|
|
42
|
+
generatedCode: string
|
|
43
|
+
logFile: string
|
|
44
|
+
SASWORK: any
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export interface SasjsParsedResponse<T> {
|
|
48
|
+
result: T
|
|
49
|
+
log: string
|
|
50
|
+
etag: string
|
|
51
|
+
status: number
|
|
52
|
+
printOutput?: string
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export type VerboseMode = boolean | 'bleached'
|