@sasjs/adapter 3.0.0 → 3.2.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.
- package/SASViyaApiClient.d.ts +2 -8
- package/SASjs.d.ts +17 -6
- package/SASjsApiClient.d.ts +22 -0
- package/auth/AuthManager.d.ts +14 -1
- package/auth/getAccessTokenForSasjs.d.ts +11 -0
- package/{node/auth/getAccessToken.d.ts → auth/getAccessTokenForViya.d.ts} +1 -1
- package/auth/getAuthCodeForSasjs.d.ts +9 -0
- package/auth/getTokens.d.ts +3 -2
- package/auth/refreshTokensForSasjs.d.ts +10 -0
- package/auth/{refreshTokens.d.ts → refreshTokensForViya.d.ts} +2 -2
- package/auth/spec/{getAccessToken.spec.d.ts → getAccessTokenForSasjs.spec.d.ts} +0 -0
- package/auth/spec/{refreshTokens.spec.d.ts → getAccessTokenForViya.spec.d.ts} +0 -0
- package/auth/spec/mockResponses.d.ts +4 -0
- package/auth/spec/refreshTokensForSasjs.spec.d.ts +1 -0
- package/auth/spec/refreshTokensForViya.spec.d.ts +1 -0
- package/index.js +2 -2
- package/job-execution/Sas9JobExecutor.d.ts +4 -5
- package/node/SASViyaApiClient.d.ts +2 -8
- package/node/SASjs.d.ts +17 -6
- package/node/SASjsApiClient.d.ts +22 -0
- package/node/auth/AuthManager.d.ts +14 -1
- package/node/auth/getAccessTokenForSasjs.d.ts +11 -0
- package/{auth/getAccessToken.d.ts → node/auth/getAccessTokenForViya.d.ts} +1 -1
- package/node/auth/getAuthCodeForSasjs.d.ts +9 -0
- package/node/auth/getTokens.d.ts +3 -2
- package/node/auth/refreshTokensForSasjs.d.ts +10 -0
- package/node/auth/{refreshTokens.d.ts → refreshTokensForViya.d.ts} +2 -2
- package/node/index.js +2 -2
- package/node/job-execution/Sas9JobExecutor.d.ts +4 -5
- package/node/request/RequestClient.d.ts +4 -0
- package/node/request/SasjsRequestClient.d.ts +8 -0
- package/node/types/SASjsConfig.d.ts +5 -0
- package/node/utils/getValidJson.d.ts +1 -1
- package/node/utils/parseViyaDebugResponse.d.ts +1 -1
- package/package.json +6 -6
- package/request/RequestClient.d.ts +4 -0
- package/request/SasjsRequestClient.d.ts +8 -0
- package/src/SASViyaApiClient.ts +10 -5
- package/src/SASjs.ts +84 -42
- package/src/SASjsApiClient.ts +43 -0
- package/src/auth/AuthManager.ts +74 -6
- package/src/auth/getAccessTokenForSasjs.ts +36 -0
- package/src/auth/{getAccessToken.ts → getAccessTokenForViya.ts} +1 -1
- package/src/auth/getAuthCodeForSasjs.ts +31 -0
- package/src/auth/getTokens.ts +16 -9
- package/src/auth/refreshTokensForSasjs.ts +35 -0
- package/src/auth/{refreshTokens.ts → refreshTokensForViya.ts} +2 -2
- package/src/auth/spec/mockResponses.ts +5 -0
- package/src/job-execution/Sas9JobExecutor.ts +34 -4
- package/src/job-execution/WebJobExecutor.ts +17 -3
- package/src/request/RequestClient.ts +11 -0
- package/src/request/Sas9RequestClient.ts +1 -1
- package/src/request/SasjsRequestClient.ts +23 -0
- package/src/types/SASjsConfig.ts +5 -0
- package/src/utils/getValidJson.ts +1 -1
- package/src/utils/parseWeboutResponse.ts +1 -1
- package/types/SASjsConfig.d.ts +5 -0
- package/utils/getValidJson.d.ts +1 -1
- package/utils/parseViyaDebugResponse.d.ts +1 -1
- package/CHANGELOG.md +0 -213
package/src/auth/AuthManager.ts
CHANGED
|
@@ -2,6 +2,8 @@ import { ServerType } from '@sasjs/utils/types'
|
|
|
2
2
|
import { RequestClient } from '../request/RequestClient'
|
|
3
3
|
import { LoginOptions, LoginResult } from '../types/Login'
|
|
4
4
|
import { serialize } from '../utils'
|
|
5
|
+
import { getAccessTokenForSasjs } from './getAccessTokenForSasjs'
|
|
6
|
+
import { getAuthCodeForSasjs } from './getAuthCodeForSasjs'
|
|
5
7
|
import { openWebPage } from './openWebPage'
|
|
6
8
|
import { verifySas9Login } from './verifySas9Login'
|
|
7
9
|
import { verifySasViyaLogin } from './verifySasViyaLogin'
|
|
@@ -21,7 +23,9 @@ export class AuthManager {
|
|
|
21
23
|
this.logoutUrl =
|
|
22
24
|
this.serverType === ServerType.Sas9
|
|
23
25
|
? '/SASLogon/logout?'
|
|
24
|
-
:
|
|
26
|
+
: this.serverType === ServerType.SasViya
|
|
27
|
+
? '/SASLogon/logout.do?'
|
|
28
|
+
: '/SASjsApi/auth/logout'
|
|
25
29
|
}
|
|
26
30
|
|
|
27
31
|
/**
|
|
@@ -79,6 +83,39 @@ export class AuthManager {
|
|
|
79
83
|
return { isLoggedIn: false, userName: '' }
|
|
80
84
|
}
|
|
81
85
|
|
|
86
|
+
/**
|
|
87
|
+
* Logs into the SAS server with the supplied credentials.
|
|
88
|
+
* @param userName - a string representing the username.
|
|
89
|
+
* @param password - a string representing the password.
|
|
90
|
+
* @param clientId - a string representing the client ID.
|
|
91
|
+
* @returns - a boolean `isLoggedin` and a string `username`
|
|
92
|
+
*/
|
|
93
|
+
public async logInSasjs(
|
|
94
|
+
username: string,
|
|
95
|
+
password: string,
|
|
96
|
+
clientId: string
|
|
97
|
+
): Promise<LoginResult> {
|
|
98
|
+
const isLoggedIn = await this.sendLoginRequestSasjs(
|
|
99
|
+
username,
|
|
100
|
+
password,
|
|
101
|
+
clientId
|
|
102
|
+
)
|
|
103
|
+
.then((res) => {
|
|
104
|
+
this.userName = username
|
|
105
|
+
this.requestClient.saveLocalStorageToken(
|
|
106
|
+
res.access_token,
|
|
107
|
+
res.refresh_token
|
|
108
|
+
)
|
|
109
|
+
return true
|
|
110
|
+
})
|
|
111
|
+
.catch(() => false)
|
|
112
|
+
|
|
113
|
+
return {
|
|
114
|
+
isLoggedIn,
|
|
115
|
+
userName: this.userName
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
82
119
|
/**
|
|
83
120
|
* Logs into the SAS server with the supplied credentials.
|
|
84
121
|
* @param username - a string representing the username.
|
|
@@ -178,6 +215,19 @@ export class AuthManager {
|
|
|
178
215
|
return loginResponse
|
|
179
216
|
}
|
|
180
217
|
|
|
218
|
+
private async sendLoginRequestSasjs(
|
|
219
|
+
username: string,
|
|
220
|
+
password: string,
|
|
221
|
+
clientId: string
|
|
222
|
+
) {
|
|
223
|
+
const authCode = await getAuthCodeForSasjs(
|
|
224
|
+
this.requestClient,
|
|
225
|
+
username,
|
|
226
|
+
password,
|
|
227
|
+
clientId
|
|
228
|
+
)
|
|
229
|
+
return getAccessTokenForSasjs(this.requestClient, clientId, authCode)
|
|
230
|
+
}
|
|
181
231
|
/**
|
|
182
232
|
* Checks whether a session is active, or login is required.
|
|
183
233
|
* @returns - a promise which resolves with an object containing three values
|
|
@@ -198,7 +248,8 @@ export class AuthManager {
|
|
|
198
248
|
//Residue can happen in case of session expiration
|
|
199
249
|
await this.logOut()
|
|
200
250
|
|
|
201
|
-
|
|
251
|
+
if (this.serverType !== ServerType.Sasjs)
|
|
252
|
+
loginForm = await this.getNewLoginForm()
|
|
202
253
|
}
|
|
203
254
|
|
|
204
255
|
return Promise.resolve({
|
|
@@ -222,12 +273,12 @@ export class AuthManager {
|
|
|
222
273
|
isLoggedIn: boolean
|
|
223
274
|
userName: string
|
|
224
275
|
}> {
|
|
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
276
|
const url =
|
|
228
277
|
this.serverType === ServerType.SasViya
|
|
229
278
|
? `${this.serverUrl}/identities/users/@currentUser`
|
|
230
|
-
:
|
|
279
|
+
: this.serverType === ServerType.Sas9
|
|
280
|
+
? `${this.serverUrl}/SASStoredProcess`
|
|
281
|
+
: `${this.serverUrl}/SASjsApi/session`
|
|
231
282
|
|
|
232
283
|
const { result: loginResponse } = await this.requestClient
|
|
233
284
|
.get<string>(url, undefined, 'text/plain')
|
|
@@ -256,7 +307,12 @@ export class AuthManager {
|
|
|
256
307
|
.split(' ')
|
|
257
308
|
.map((name: string) => name.slice(0, 3).toLowerCase())
|
|
258
309
|
.join('')
|
|
310
|
+
|
|
311
|
+
case ServerType.Sasjs:
|
|
312
|
+
return response?.username
|
|
313
|
+
|
|
259
314
|
default:
|
|
315
|
+
console.error('Server Type not found in extractUserName function')
|
|
260
316
|
return ''
|
|
261
317
|
}
|
|
262
318
|
}
|
|
@@ -304,9 +360,21 @@ export class AuthManager {
|
|
|
304
360
|
|
|
305
361
|
/**
|
|
306
362
|
* Logs out of the configured SAS server.
|
|
363
|
+
* @param accessToken - an optional access token is required for SASjs server type.
|
|
307
364
|
*/
|
|
308
|
-
public logOut() {
|
|
365
|
+
public async logOut() {
|
|
366
|
+
if (this.serverType === ServerType.Sasjs) {
|
|
367
|
+
return this.requestClient
|
|
368
|
+
.delete(this.logoutUrl)
|
|
369
|
+
.catch(() => true)
|
|
370
|
+
.finally(() => {
|
|
371
|
+
this.requestClient.clearLocalStorageTokens()
|
|
372
|
+
return true
|
|
373
|
+
})
|
|
374
|
+
}
|
|
375
|
+
|
|
309
376
|
this.requestClient.clearCsrfTokens()
|
|
377
|
+
|
|
310
378
|
return this.requestClient.get(this.logoutUrl, undefined).then(() => true)
|
|
311
379
|
}
|
|
312
380
|
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { prefixMessage } from '@sasjs/utils/error'
|
|
2
|
+
import { RequestClient } from '../request/RequestClient'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Exchanges the auth code for an access token for the given client.
|
|
6
|
+
* @param requestClient - the pre-configured HTTP request client
|
|
7
|
+
* @param clientId - the client ID to authenticate with.
|
|
8
|
+
* @param authCode - the auth code received from the server.
|
|
9
|
+
*/
|
|
10
|
+
export async function getAccessTokenForSasjs(
|
|
11
|
+
requestClient: RequestClient,
|
|
12
|
+
clientId: string,
|
|
13
|
+
authCode: string
|
|
14
|
+
) {
|
|
15
|
+
const url = '/SASjsApi/auth/token'
|
|
16
|
+
const data = {
|
|
17
|
+
clientId,
|
|
18
|
+
code: authCode
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return await requestClient
|
|
22
|
+
.post(url, data, undefined)
|
|
23
|
+
.then((res) => {
|
|
24
|
+
const sasAuth = res.result as {
|
|
25
|
+
accessToken: string
|
|
26
|
+
refreshToken: string
|
|
27
|
+
}
|
|
28
|
+
return {
|
|
29
|
+
access_token: sasAuth.accessToken,
|
|
30
|
+
refresh_token: sasAuth.refreshToken
|
|
31
|
+
}
|
|
32
|
+
})
|
|
33
|
+
.catch((err) => {
|
|
34
|
+
throw prefixMessage(err, 'Error while getting access token. ')
|
|
35
|
+
})
|
|
36
|
+
}
|
|
@@ -10,7 +10,7 @@ import { RequestClient } from '../request/RequestClient'
|
|
|
10
10
|
* @param clientSecret - the client secret to authenticate with.
|
|
11
11
|
* @param authCode - the auth code received from the server.
|
|
12
12
|
*/
|
|
13
|
-
export async function
|
|
13
|
+
export async function getAccessTokenForViya(
|
|
14
14
|
requestClient: RequestClient,
|
|
15
15
|
clientId: string,
|
|
16
16
|
clientSecret: string,
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { prefixMessage } from '@sasjs/utils/error'
|
|
2
|
+
import { RequestClient } from '../request/RequestClient'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Performs a login authenticate and returns an auth code for the given client.
|
|
6
|
+
* @param requestClient - the pre-configured HTTP request client
|
|
7
|
+
* @param username - a string representing the username.
|
|
8
|
+
* @param password - a string representing the password.
|
|
9
|
+
* @param clientId - the client ID to authenticate with.
|
|
10
|
+
*/
|
|
11
|
+
export const getAuthCodeForSasjs = async (
|
|
12
|
+
requestClient: RequestClient,
|
|
13
|
+
username: string,
|
|
14
|
+
password: string,
|
|
15
|
+
clientId: string
|
|
16
|
+
) => {
|
|
17
|
+
const url = '/SASjsApi/auth/authorize'
|
|
18
|
+
const data = { username, password, clientId }
|
|
19
|
+
|
|
20
|
+
const { code: authCode } = await requestClient
|
|
21
|
+
.post<{ code: string }>(url, data, undefined)
|
|
22
|
+
.then((res) => res.result)
|
|
23
|
+
.catch((err) => {
|
|
24
|
+
throw prefixMessage(
|
|
25
|
+
err,
|
|
26
|
+
'Error while authenticating with provided username, password and clientId. '
|
|
27
|
+
)
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
return authCode
|
|
31
|
+
}
|
package/src/auth/getTokens.ts
CHANGED
|
@@ -3,18 +3,21 @@ import {
|
|
|
3
3
|
isRefreshTokenExpiring,
|
|
4
4
|
hasTokenExpired
|
|
5
5
|
} from '@sasjs/utils/auth'
|
|
6
|
-
import { AuthConfig } from '@sasjs/utils/types'
|
|
6
|
+
import { AuthConfig, ServerType } from '@sasjs/utils/types'
|
|
7
7
|
import { RequestClient } from '../request/RequestClient'
|
|
8
|
-
import {
|
|
8
|
+
import { refreshTokensForViya } from './refreshTokensForViya'
|
|
9
|
+
import { refreshTokensForSasjs } from './refreshTokensForSasjs'
|
|
9
10
|
|
|
10
11
|
/**
|
|
11
12
|
* Returns the auth configuration, refreshing the tokens if necessary.
|
|
12
13
|
* @param requestClient - the pre-configured HTTP request client
|
|
13
14
|
* @param authConfig - an object containing a client ID, secret, access token and refresh token
|
|
15
|
+
* @param serverType - server type for which refreshing the tokens, defaults to SASVIYA
|
|
14
16
|
*/
|
|
15
17
|
export async function getTokens(
|
|
16
18
|
requestClient: RequestClient,
|
|
17
|
-
authConfig: AuthConfig
|
|
19
|
+
authConfig: AuthConfig,
|
|
20
|
+
serverType: ServerType = ServerType.SasViya
|
|
18
21
|
): Promise<AuthConfig> {
|
|
19
22
|
const logger = process.logger || console
|
|
20
23
|
let { access_token, refresh_token, client, secret } = authConfig
|
|
@@ -29,12 +32,16 @@ export async function getTokens(
|
|
|
29
32
|
throw new Error(error)
|
|
30
33
|
}
|
|
31
34
|
logger.info('Refreshing access and refresh tokens.')
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
35
|
+
const tokens =
|
|
36
|
+
serverType === ServerType.SasViya
|
|
37
|
+
? await refreshTokensForViya(
|
|
38
|
+
requestClient,
|
|
39
|
+
client,
|
|
40
|
+
secret,
|
|
41
|
+
refresh_token
|
|
42
|
+
)
|
|
43
|
+
: await refreshTokensForSasjs(requestClient, refresh_token)
|
|
44
|
+
;({ access_token, refresh_token } = tokens)
|
|
38
45
|
}
|
|
39
46
|
return { access_token, refresh_token, client, secret }
|
|
40
47
|
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { prefixMessage } from '@sasjs/utils/error'
|
|
2
|
+
import { RequestClient } from '../request/RequestClient'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Exchanges the refresh token for an access token for the given client.
|
|
6
|
+
* @param requestClient - the pre-configured HTTP request client
|
|
7
|
+
* @param refreshToken - the refresh token received from the server.
|
|
8
|
+
*/
|
|
9
|
+
export async function refreshTokensForSasjs(
|
|
10
|
+
requestClient: RequestClient,
|
|
11
|
+
refreshToken: string
|
|
12
|
+
) {
|
|
13
|
+
const url = '/SASjsApi/auth/refresh'
|
|
14
|
+
const headers = {
|
|
15
|
+
Authorization: 'Bearer ' + refreshToken
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const authResponse = await requestClient
|
|
19
|
+
.post(url, undefined, undefined, undefined, headers)
|
|
20
|
+
.then((res) => {
|
|
21
|
+
const sasAuth = res.result as {
|
|
22
|
+
accessToken: string
|
|
23
|
+
refreshToken: string
|
|
24
|
+
}
|
|
25
|
+
return {
|
|
26
|
+
access_token: sasAuth.accessToken,
|
|
27
|
+
refresh_token: sasAuth.refreshToken
|
|
28
|
+
}
|
|
29
|
+
})
|
|
30
|
+
.catch((err) => {
|
|
31
|
+
throw prefixMessage(err, 'Error while refreshing tokens')
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
return authResponse
|
|
35
|
+
}
|
|
@@ -8,9 +8,9 @@ import { RequestClient } from '../request/RequestClient'
|
|
|
8
8
|
* @param requestClient - the pre-configured HTTP request client
|
|
9
9
|
* @param clientId - the client ID to authenticate with.
|
|
10
10
|
* @param clientSecret - the client secret to authenticate with.
|
|
11
|
-
* @param
|
|
11
|
+
* @param refreshToken - the refresh token received from the server.
|
|
12
12
|
*/
|
|
13
|
-
export async function
|
|
13
|
+
export async function refreshTokensForViya(
|
|
14
14
|
requestClient: RequestClient,
|
|
15
15
|
clientId: string,
|
|
16
16
|
clientSecret: string,
|
|
@@ -13,6 +13,11 @@ export const mockAuthResponse: SasAuthResponse = {
|
|
|
13
13
|
jti: 'test'
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
+
export const mockSasjsAuthResponse = {
|
|
17
|
+
access_token: 'acc355',
|
|
18
|
+
refresh_token: 'r3fr35h'
|
|
19
|
+
}
|
|
20
|
+
|
|
16
21
|
export const generateToken = (timeToLiveSeconds: number): string => {
|
|
17
22
|
const exp =
|
|
18
23
|
new Date(new Date().getTime() + timeToLiveSeconds * 1000).getTime() / 1000
|
|
@@ -5,6 +5,7 @@ import { ErrorResponse } from '../types/errors'
|
|
|
5
5
|
import { convertToCSV, isRelativePath } from '../utils'
|
|
6
6
|
import { BaseJobExecutor } from './JobExecutor'
|
|
7
7
|
import { Sas9RequestClient } from '../request/Sas9RequestClient'
|
|
8
|
+
import { RequestClient } from '../request/RequestClient'
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* Job executor for SAS9 servers for use in Node.js environments.
|
|
@@ -13,15 +14,16 @@ import { Sas9RequestClient } from '../request/Sas9RequestClient'
|
|
|
13
14
|
* job execution requests.
|
|
14
15
|
*/
|
|
15
16
|
export class Sas9JobExecutor extends BaseJobExecutor {
|
|
16
|
-
private
|
|
17
|
+
private sas9RequestClient: Sas9RequestClient
|
|
17
18
|
constructor(
|
|
18
19
|
serverUrl: string,
|
|
19
20
|
serverType: ServerType,
|
|
20
21
|
private jobsPath: string,
|
|
22
|
+
private requestClient: RequestClient,
|
|
21
23
|
httpsAgentOptions?: https.AgentOptions
|
|
22
24
|
) {
|
|
23
25
|
super(serverUrl, serverType)
|
|
24
|
-
this.
|
|
26
|
+
this.sas9RequestClient = new Sas9RequestClient(serverUrl, httpsAgentOptions)
|
|
25
27
|
}
|
|
26
28
|
|
|
27
29
|
async execute(sasJob: string, data: any, config: any) {
|
|
@@ -37,6 +39,8 @@ export class Sas9JobExecutor extends BaseJobExecutor {
|
|
|
37
39
|
: ''
|
|
38
40
|
}`
|
|
39
41
|
|
|
42
|
+
apiUrl = `${apiUrl}${config.debug ? '&_debug=131' : ''}`
|
|
43
|
+
|
|
40
44
|
let requestParams = {
|
|
41
45
|
...this.getRequestParams(config)
|
|
42
46
|
}
|
|
@@ -49,6 +53,8 @@ export class Sas9JobExecutor extends BaseJobExecutor {
|
|
|
49
53
|
} catch (e: any) {
|
|
50
54
|
return Promise.reject(new ErrorResponse(e?.message, e))
|
|
51
55
|
}
|
|
56
|
+
} else {
|
|
57
|
+
data = ''
|
|
52
58
|
}
|
|
53
59
|
|
|
54
60
|
for (const key in requestParams) {
|
|
@@ -57,16 +63,18 @@ export class Sas9JobExecutor extends BaseJobExecutor {
|
|
|
57
63
|
}
|
|
58
64
|
}
|
|
59
65
|
|
|
60
|
-
await this.
|
|
66
|
+
await this.sas9RequestClient.login(
|
|
61
67
|
config.username,
|
|
62
68
|
config.password,
|
|
63
69
|
this.jobsPath
|
|
64
70
|
)
|
|
71
|
+
|
|
65
72
|
const contentType =
|
|
66
73
|
data && Object.keys(data).length
|
|
67
74
|
? 'multipart/form-data; boundary=' + (formData as any)._boundary
|
|
68
75
|
: 'text/plain'
|
|
69
|
-
|
|
76
|
+
|
|
77
|
+
return await this.sas9RequestClient!.post(
|
|
70
78
|
apiUrl,
|
|
71
79
|
formData,
|
|
72
80
|
undefined,
|
|
@@ -76,6 +84,28 @@ export class Sas9JobExecutor extends BaseJobExecutor {
|
|
|
76
84
|
Connection: 'Keep-Alive'
|
|
77
85
|
}
|
|
78
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
|
+
})
|
|
79
109
|
}
|
|
80
110
|
|
|
81
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,24 @@ export class WebJobExecutor extends BaseJobExecutor {
|
|
|
142
144
|
}
|
|
143
145
|
|
|
144
146
|
const requestPromise = new Promise((resolve, reject) => {
|
|
145
|
-
this.requestClient!.post(apiUrl, formData,
|
|
147
|
+
this.requestClient!.post(apiUrl, formData, authConfig?.access_token)
|
|
146
148
|
.then(async (res: any) => {
|
|
147
|
-
|
|
149
|
+
const resObj =
|
|
150
|
+
this.serverType === ServerType.Sasjs
|
|
151
|
+
? {
|
|
152
|
+
result: res.result._webout,
|
|
153
|
+
log: res.result.log
|
|
154
|
+
}
|
|
155
|
+
: res
|
|
156
|
+
this.requestClient!.appendRequest(resObj, sasJob, config.debug)
|
|
148
157
|
|
|
149
158
|
let jsonResponse = res.result
|
|
150
159
|
|
|
160
|
+
if (this.serverType === ServerType.Sasjs) {
|
|
161
|
+
const webout = parseWeboutResponse(res.result._webout, apiUrl)
|
|
162
|
+
jsonResponse = getValidJson(webout)
|
|
163
|
+
}
|
|
164
|
+
|
|
151
165
|
if (config.debug) {
|
|
152
166
|
switch (this.serverType) {
|
|
153
167
|
case ServerType.SasViya:
|
|
@@ -48,7 +48,9 @@ export interface HttpClient {
|
|
|
48
48
|
): Promise<{ result: T; etag: string }>
|
|
49
49
|
|
|
50
50
|
getCsrfToken(type: 'general' | 'file'): CsrfToken | undefined
|
|
51
|
+
saveLocalStorageToken(accessToken: string, refreshToken: string): void
|
|
51
52
|
clearCsrfTokens(): void
|
|
53
|
+
clearLocalStorageTokens(): void
|
|
52
54
|
getBaseUrl(): string
|
|
53
55
|
}
|
|
54
56
|
|
|
@@ -70,6 +72,11 @@ export class RequestClient implements HttpClient {
|
|
|
70
72
|
this.createHttpClient(baseUrl, httpsAgentOptions)
|
|
71
73
|
}
|
|
72
74
|
|
|
75
|
+
public saveLocalStorageToken(accessToken: string, refreshToken: string) {
|
|
76
|
+
localStorage.setItem('accessToken', accessToken)
|
|
77
|
+
localStorage.setItem('refreshToken', refreshToken)
|
|
78
|
+
}
|
|
79
|
+
|
|
73
80
|
public getCsrfToken(type: 'general' | 'file' = 'general') {
|
|
74
81
|
return type === 'file' ? this.fileUploadCsrfToken : this.csrfToken
|
|
75
82
|
}
|
|
@@ -78,6 +85,10 @@ export class RequestClient implements HttpClient {
|
|
|
78
85
|
this.csrfToken = { headerName: '', value: '' }
|
|
79
86
|
this.fileUploadCsrfToken = { headerName: '', value: '' }
|
|
80
87
|
}
|
|
88
|
+
public clearLocalStorageTokens() {
|
|
89
|
+
localStorage.setItem('accessToken', '')
|
|
90
|
+
localStorage.setItem('refreshToken', '')
|
|
91
|
+
}
|
|
81
92
|
|
|
82
93
|
public getBaseUrl() {
|
|
83
94
|
return this.httpClient.defaults.baseURL || ''
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { RequestClient } from './RequestClient'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Specific request client for SASJS.
|
|
5
|
+
* Append tokens in headers.
|
|
6
|
+
*/
|
|
7
|
+
export class SasjsRequestClient extends RequestClient {
|
|
8
|
+
getHeaders = (accessToken: string | undefined, contentType: string) => {
|
|
9
|
+
const headers: any = {}
|
|
10
|
+
|
|
11
|
+
if (contentType !== 'application/x-www-form-urlencoded')
|
|
12
|
+
headers['Content-Type'] = contentType
|
|
13
|
+
|
|
14
|
+
headers.Accept = contentType === 'application/json' ? contentType : '*/*'
|
|
15
|
+
|
|
16
|
+
if (!accessToken)
|
|
17
|
+
accessToken = localStorage.getItem('accessToken') ?? undefined
|
|
18
|
+
|
|
19
|
+
if (accessToken) headers.Authorization = `Bearer ${accessToken}`
|
|
20
|
+
|
|
21
|
+
return headers
|
|
22
|
+
}
|
|
23
|
+
}
|
package/src/types/SASjsConfig.ts
CHANGED
|
@@ -12,6 +12,11 @@ export class SASjsConfig {
|
|
|
12
12
|
* streamed.
|
|
13
13
|
*/
|
|
14
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 = ''
|
|
15
20
|
/**
|
|
16
21
|
* The location of the Stored Process Web Application. By default the adapter
|
|
17
22
|
* will use '/SASStoredProcess/do' on SAS 9.
|
|
@@ -4,7 +4,7 @@ import { JsonParseArrayError, InvalidJsonError } from '../types/errors'
|
|
|
4
4
|
* 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.
|
|
5
5
|
* @param str - string to check.
|
|
6
6
|
*/
|
|
7
|
-
export const getValidJson = (str: string | object) => {
|
|
7
|
+
export const getValidJson = (str: string | object): object => {
|
|
8
8
|
try {
|
|
9
9
|
if (str === null || str === undefined) throw new InvalidJsonError()
|
|
10
10
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { WeboutResponseError } from '../types/errors'
|
|
2
2
|
|
|
3
|
-
export const parseWeboutResponse = (response: string, url?: string) => {
|
|
3
|
+
export const parseWeboutResponse = (response: string, url?: string): string => {
|
|
4
4
|
let sasResponse = ''
|
|
5
5
|
|
|
6
6
|
if (response.includes('>>weboutBEGIN<<')) {
|
package/types/SASjsConfig.d.ts
CHANGED
|
@@ -12,6 +12,11 @@ export declare class SASjsConfig {
|
|
|
12
12
|
* streamed.
|
|
13
13
|
*/
|
|
14
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;
|
|
15
20
|
/**
|
|
16
21
|
* The location of the Stored Process Web Application. By default the adapter
|
|
17
22
|
* will use '/SASStoredProcess/do' on SAS 9.
|
package/utils/getValidJson.d.ts
CHANGED
|
@@ -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) =>
|
|
5
|
+
export declare const getValidJson: (str: string | object) => object;
|
|
@@ -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<
|
|
12
|
+
export declare const parseSasViyaDebugResponse: (response: string, requestClient: RequestClient, serverUrl: string) => Promise<object>;
|