@sasjs/adapter 4.9.0 → 4.9.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/SASjs.d.ts +2 -2
- package/api/viya/{executeScript.d.ts → executeOnComputeApi.d.ts} +2 -2
- package/index-dev.js +2 -2
- package/index.js +1 -1
- package/minified_sas9.js +1 -1
- package/node/SASjs.d.ts +2 -2
- package/node/api/viya/{executeScript.d.ts → executeOnComputeApi.d.ts} +2 -2
- package/node/index.js +1 -1
- package/node/request/RequestClient.d.ts +2 -2
- package/package.json +1 -1
- package/request/RequestClient.d.ts +2 -2
- package/src/SASViyaApiClient.ts +2 -2
- package/src/SASjs.ts +3 -3
- package/src/api/viya/{executeScript.ts → executeOnComputeApi.ts} +13 -22
- package/src/request/RequestClient.ts +75 -5
|
@@ -1,5 +1,5 @@
|
|
|
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
5
|
import { SASjsRequest, HttpClient, VerboseMode } from '../types';
|
|
@@ -90,7 +90,7 @@ export declare class RequestClient implements HttpClient {
|
|
|
90
90
|
* @param successCallBack - function that should be triggered on every HTTP response with the status 2**.
|
|
91
91
|
* @param errorCallBack - function that should be triggered on every HTTP response with the status different from 2**.
|
|
92
92
|
*/
|
|
93
|
-
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;
|
|
94
94
|
/**
|
|
95
95
|
* Turns off verbose mode to log every HTTP response.
|
|
96
96
|
*/
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
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
5
|
import { SASjsRequest, HttpClient, VerboseMode } from '../types';
|
|
@@ -90,7 +90,7 @@ export declare class RequestClient implements HttpClient {
|
|
|
90
90
|
* @param successCallBack - function that should be triggered on every HTTP response with the status 2**.
|
|
91
91
|
* @param errorCallBack - function that should be triggered on every HTTP response with the status different from 2**.
|
|
92
92
|
*/
|
|
93
|
-
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;
|
|
94
94
|
/**
|
|
95
95
|
* Turns off verbose mode to log every HTTP response.
|
|
96
96
|
*/
|
package/src/SASViyaApiClient.ts
CHANGED
|
@@ -25,7 +25,7 @@ import { prefixMessage } from '@sasjs/utils/error'
|
|
|
25
25
|
import { pollJobState } from './api/viya/pollJobState'
|
|
26
26
|
import { getTokens } from './auth/getTokens'
|
|
27
27
|
import { uploadTables } from './api/viya/uploadTables'
|
|
28
|
-
import {
|
|
28
|
+
import { executeOnComputeApi } from './api/viya/executeOnComputeApi'
|
|
29
29
|
import { getAccessTokenForViya } from './auth/getAccessTokenForViya'
|
|
30
30
|
import { refreshTokensForViya } from './auth/refreshTokensForViya'
|
|
31
31
|
|
|
@@ -293,7 +293,7 @@ export class SASViyaApiClient {
|
|
|
293
293
|
printPid = false,
|
|
294
294
|
variables?: MacroVar
|
|
295
295
|
): Promise<any> {
|
|
296
|
-
return
|
|
296
|
+
return executeOnComputeApi(
|
|
297
297
|
this.requestClient,
|
|
298
298
|
this.sessionManager,
|
|
299
299
|
this.rootFolderName,
|
package/src/SASjs.ts
CHANGED
|
@@ -34,7 +34,7 @@ import {
|
|
|
34
34
|
Sas9JobExecutor,
|
|
35
35
|
FileUploader
|
|
36
36
|
} from './job-execution'
|
|
37
|
-
import { AxiosResponse } from 'axios'
|
|
37
|
+
import { AxiosResponse, AxiosError } from 'axios'
|
|
38
38
|
|
|
39
39
|
interface ExecuteScriptParams {
|
|
40
40
|
linesOfCode: string[]
|
|
@@ -1170,8 +1170,8 @@ export default class SASjs {
|
|
|
1170
1170
|
* @param errorCallBack - function that should be triggered on every HTTP response with the status different from 2**.
|
|
1171
1171
|
*/
|
|
1172
1172
|
public enableVerboseMode(
|
|
1173
|
-
successCallBack?: (response: AxiosResponse) => AxiosResponse,
|
|
1174
|
-
errorCallBack?: (response: AxiosResponse) => AxiosResponse
|
|
1173
|
+
successCallBack?: (response: AxiosResponse | AxiosError) => AxiosResponse,
|
|
1174
|
+
errorCallBack?: (response: AxiosResponse | AxiosError) => AxiosResponse
|
|
1175
1175
|
) {
|
|
1176
1176
|
this.requestClient?.enableVerboseMode(successCallBack, errorCallBack)
|
|
1177
1177
|
}
|
|
@@ -15,8 +15,12 @@ import { formatDataForRequest } from '../../utils/formatDataForRequest'
|
|
|
15
15
|
import { pollJobState, JobState } from './pollJobState'
|
|
16
16
|
import { uploadTables } from './uploadTables'
|
|
17
17
|
|
|
18
|
+
interface JobRequestBody {
|
|
19
|
+
[key: string]: number | string | string[]
|
|
20
|
+
}
|
|
21
|
+
|
|
18
22
|
/**
|
|
19
|
-
* Executes
|
|
23
|
+
* Executes SAS program on the current SAS Viya server using Compute API.
|
|
20
24
|
* @param jobPath - the path to the file being submitted for execution.
|
|
21
25
|
* @param linesOfCode - an array of code lines to execute.
|
|
22
26
|
* @param contextName - the context to execute the code in.
|
|
@@ -29,7 +33,7 @@ import { uploadTables } from './uploadTables'
|
|
|
29
33
|
* @param printPid - a boolean that indicates whether the function should print (PID) of the started job.
|
|
30
34
|
* @param variables - an object that represents macro variables.
|
|
31
35
|
*/
|
|
32
|
-
export async function
|
|
36
|
+
export async function executeOnComputeApi(
|
|
33
37
|
requestClient: RequestClient,
|
|
34
38
|
sessionManager: SessionManager,
|
|
35
39
|
rootFolderName: string,
|
|
@@ -46,6 +50,7 @@ export async function executeScript(
|
|
|
46
50
|
variables?: MacroVar
|
|
47
51
|
): Promise<any> {
|
|
48
52
|
let access_token = (authConfig || {}).access_token
|
|
53
|
+
|
|
49
54
|
if (authConfig) {
|
|
50
55
|
;({ access_token } = await getTokens(requestClient, authConfig))
|
|
51
56
|
}
|
|
@@ -78,27 +83,13 @@ export async function executeScript(
|
|
|
78
83
|
const logger = process.logger || console
|
|
79
84
|
|
|
80
85
|
logger.info(
|
|
81
|
-
`
|
|
86
|
+
`Triggering '${relativeJobPath}' with PID ${
|
|
82
87
|
jobIdVariable.value
|
|
83
88
|
} at ${timestampToYYYYMMDDHHMMSS()}`
|
|
84
89
|
)
|
|
85
90
|
}
|
|
86
91
|
}
|
|
87
92
|
|
|
88
|
-
const jobArguments: { [key: string]: any } = {
|
|
89
|
-
_contextName: contextName,
|
|
90
|
-
_OMITJSONLISTING: true,
|
|
91
|
-
_OMITJSONLOG: true,
|
|
92
|
-
_OMITSESSIONRESULTS: true,
|
|
93
|
-
_OMITTEXTLISTING: true,
|
|
94
|
-
_OMITTEXTLOG: true
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
if (debug) {
|
|
98
|
-
jobArguments['_OMITTEXTLOG'] = false
|
|
99
|
-
jobArguments['_OMITSESSIONRESULTS'] = false
|
|
100
|
-
}
|
|
101
|
-
|
|
102
93
|
let fileName
|
|
103
94
|
|
|
104
95
|
if (isRelativePath(jobPath)) {
|
|
@@ -107,6 +98,7 @@ export async function executeScript(
|
|
|
107
98
|
}`
|
|
108
99
|
} else {
|
|
109
100
|
const jobPathParts = jobPath.split('/')
|
|
101
|
+
|
|
110
102
|
fileName = jobPathParts.pop()
|
|
111
103
|
}
|
|
112
104
|
|
|
@@ -118,7 +110,6 @@ export async function executeScript(
|
|
|
118
110
|
}
|
|
119
111
|
|
|
120
112
|
if (variables) jobVariables = { ...jobVariables, ...variables }
|
|
121
|
-
|
|
122
113
|
if (debug) jobVariables = { ...jobVariables, _DEBUG: 131 }
|
|
123
114
|
|
|
124
115
|
let files: any[] = []
|
|
@@ -145,12 +136,12 @@ export async function executeScript(
|
|
|
145
136
|
}
|
|
146
137
|
|
|
147
138
|
// Execute job in session
|
|
148
|
-
const jobRequestBody = {
|
|
149
|
-
name: fileName,
|
|
139
|
+
const jobRequestBody: JobRequestBody = {
|
|
140
|
+
name: fileName || 'Default Job Name',
|
|
150
141
|
description: 'Powered by SASjs',
|
|
151
142
|
code: linesOfCode,
|
|
152
143
|
variables: jobVariables,
|
|
153
|
-
|
|
144
|
+
version: 2
|
|
154
145
|
}
|
|
155
146
|
|
|
156
147
|
const { result: postedJob, etag } = await requestClient
|
|
@@ -279,7 +270,7 @@ export async function executeScript(
|
|
|
279
270
|
const error = e as HttpError
|
|
280
271
|
|
|
281
272
|
if (error.status === 404) {
|
|
282
|
-
return
|
|
273
|
+
return executeOnComputeApi(
|
|
283
274
|
requestClient,
|
|
284
275
|
sessionManager,
|
|
285
276
|
rootFolderName,
|
|
@@ -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'
|
|
@@ -65,6 +71,7 @@ export class RequestClient implements HttpClient {
|
|
|
65
71
|
this.csrfToken = { headerName: '', value: '' }
|
|
66
72
|
this.fileUploadCsrfToken = { headerName: '', value: '' }
|
|
67
73
|
}
|
|
74
|
+
|
|
68
75
|
public clearLocalStorageTokens() {
|
|
69
76
|
localStorage.setItem('accessToken', '')
|
|
70
77
|
localStorage.setItem('refreshToken', '')
|
|
@@ -406,10 +413,73 @@ export class RequestClient implements HttpClient {
|
|
|
406
413
|
return bodyLines.join('\n')
|
|
407
414
|
}
|
|
408
415
|
|
|
409
|
-
private defaultInterceptionCallBack = (
|
|
410
|
-
|
|
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
|
|
411
481
|
const { data: reqData } = config
|
|
412
|
-
const { _header: reqHeaders, res } = request
|
|
482
|
+
const { _header: reqHeaders, res } = request || fallbackRequest
|
|
413
483
|
const { rawHeaders } = res
|
|
414
484
|
|
|
415
485
|
// Converts an array of strings into a single string with the following format:
|
|
@@ -439,7 +509,7 @@ HTTP Response (first 50 lines):
|
|
|
439
509
|
${resHeaders}${parsedResBody ? `\n\n${parsedResBody}` : ''}
|
|
440
510
|
`)
|
|
441
511
|
|
|
442
|
-
return
|
|
512
|
+
return axiosResponse
|
|
443
513
|
}
|
|
444
514
|
|
|
445
515
|
/**
|