@sasjs/adapter 4.3.8 → 4.5.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.
@@ -0,0 +1,88 @@
1
+ import { ServerType } from '@sasjs/utils/types'
2
+
3
+ type Server = ServerType.SasViya | ServerType.Sasjs
4
+ type Operation = 'fetching access token' | 'refreshing tokens'
5
+
6
+ const getServerName = (server: Server) =>
7
+ server === ServerType.SasViya ? 'Viya' : 'Sasjs'
8
+
9
+ const getResponseTitle = (server: Server) =>
10
+ `Response from ${getServerName(server)} is below.`
11
+
12
+ /**
13
+ * Forms error prefix for requests related to token operations.
14
+ * @param operation - string describing operation ('fetching access token' or 'refreshing tokens').
15
+ * @param funcName - name of the function sent the request.
16
+ * @param server - server type (SASVIYA or SASJS).
17
+ * @param url - endpoint used to send the request.
18
+ * @param data - request payload.
19
+ * @param headers - request headers.
20
+ * @param clientId - client ID to authenticate with.
21
+ * @param clientSecret - client secret to authenticate with.
22
+ * @returns - string containing request information. Example:
23
+ * Error while fetching access token from /SASLogon/oauth/token
24
+ * Thrown by the @sasjs/adapter getAccessTokenForViya function.
25
+ * Payload:
26
+ * {
27
+ * "grant_type": "authorization_code",
28
+ * "code": "example_code"
29
+ * }
30
+ * Headers:
31
+ * {
32
+ * "Authorization": "Basic NEdMQXBwOjRHTEFwcDE=",
33
+ * "Accept": "application/json"
34
+ * }
35
+ * ClientId: exampleClientId
36
+ * ClientSecret: exampleClientSecret
37
+ *
38
+ * Response from Viya is below.
39
+ * Auth error: {
40
+ * "error": "invalid_token",
41
+ * "error_description": "No scopes were granted"
42
+ * }
43
+ */
44
+ export const getTokenRequestErrorPrefix = (
45
+ operation: Operation,
46
+ funcName: string,
47
+ server: Server,
48
+ url: string,
49
+ data?: {},
50
+ headers?: {},
51
+ clientId?: string,
52
+ clientSecret?: string
53
+ ) => {
54
+ const stringify = (obj: {}) => JSON.stringify(obj, null, 2)
55
+
56
+ const lines = [
57
+ `Error while ${operation} from ${url}`,
58
+ `Thrown by the @sasjs/adapter ${funcName} function.`
59
+ ]
60
+
61
+ if (data) {
62
+ lines.push('Payload:')
63
+ lines.push(stringify(data))
64
+ }
65
+ if (headers) {
66
+ lines.push('Headers:')
67
+ lines.push(stringify(headers))
68
+ }
69
+ if (clientId) lines.push(`ClientId: ${clientId}`)
70
+ if (clientSecret) lines.push(`ClientSecret: ${clientSecret}`)
71
+
72
+ lines.push('')
73
+ lines.push(`${getResponseTitle(server)}`)
74
+ lines.push('')
75
+
76
+ return lines.join(`\n`)
77
+ }
78
+
79
+ /**
80
+ * Parse error prefix to get response payload.
81
+ * @param prefix - error prefix generated by getTokenRequestErrorPrefix function.
82
+ * @param server - server type (SASVIYA or SASJS).
83
+ * @returns - response payload.
84
+ */
85
+ export const getTokenRequestErrorPrefixResponse = (
86
+ prefix: string,
87
+ server: ServerType.SasViya | ServerType.Sasjs
88
+ ) => prefix.split(`${getResponseTitle(server)}\n`).pop() as string
@@ -22,6 +22,7 @@ export async function getTokens(
22
22
  ): Promise<AuthConfig> {
23
23
  const logger = process.logger || console
24
24
  let { access_token, refresh_token, client, secret } = authConfig
25
+
25
26
  if (
26
27
  isAccessTokenExpiring(access_token) ||
27
28
  isRefreshTokenExpiring(refresh_token)
@@ -29,6 +30,7 @@ export async function getTokens(
29
30
  if (hasTokenExpired(refresh_token)) {
30
31
  const error =
31
32
  'Unable to obtain new access token. Your refresh token has expired.'
33
+
32
34
  logger.error(error)
33
35
 
34
36
  throw new Error(error)
@@ -47,5 +49,6 @@ export async function getTokens(
47
49
  : await refreshTokensForSasjs(requestClient, refresh_token)
48
50
  ;({ access_token, refresh_token } = tokens)
49
51
  }
52
+
50
53
  return { access_token, refresh_token, client, secret }
51
54
  }
@@ -1,5 +1,7 @@
1
1
  import { prefixMessage } from '@sasjs/utils/error'
2
2
  import { RequestClient } from '../request/RequestClient'
3
+ import { getTokenRequestErrorPrefix } from './getTokenRequestErrorPrefix'
4
+ import { ServerType } from '@sasjs/utils/types'
3
5
 
4
6
  /**
5
7
  * Exchanges the refresh token for an access token for the given client.
@@ -28,7 +30,15 @@ export async function refreshTokensForSasjs(
28
30
  }
29
31
  })
30
32
  .catch((err) => {
31
- throw prefixMessage(err, 'Error while refreshing tokens: ')
33
+ throw prefixMessage(
34
+ err,
35
+ getTokenRequestErrorPrefix(
36
+ 'refreshing tokens',
37
+ 'refreshTokensForSasjs',
38
+ ServerType.Sasjs,
39
+ url
40
+ )
41
+ )
32
42
  })
33
43
 
34
44
  return authResponse
@@ -1,8 +1,9 @@
1
- import { SasAuthResponse } from '@sasjs/utils/types'
1
+ import { SasAuthResponse, ServerType } from '@sasjs/utils/types'
2
2
  import { prefixMessage } from '@sasjs/utils/error'
3
3
  import * as NodeFormData from 'form-data'
4
4
  import { RequestClient } from '../request/RequestClient'
5
5
  import { isNode } from '../utils'
6
+ import { getTokenRequestErrorPrefix } from './getTokenRequestErrorPrefix'
6
7
 
7
8
  /**
8
9
  * Exchanges the refresh token for an access token for the given client.
@@ -46,7 +47,19 @@ export async function refreshTokensForViya(
46
47
  )
47
48
  .then((res) => res.result)
48
49
  .catch((err) => {
49
- throw prefixMessage(err, 'Error while refreshing tokens: ')
50
+ throw prefixMessage(
51
+ err,
52
+ getTokenRequestErrorPrefix(
53
+ 'refreshing tokens',
54
+ 'refreshTokensForViya',
55
+ ServerType.SasViya,
56
+ url,
57
+ formData,
58
+ headers,
59
+ clientId,
60
+ clientSecret
61
+ )
62
+ )
50
63
  })
51
64
 
52
65
  return authResponse
@@ -93,12 +93,21 @@ export class FileUploader extends BaseJobExecutor {
93
93
  this.requestClient,
94
94
  config.serverUrl
95
95
  )
96
+
96
97
  break
97
98
  case ServerType.Sas9:
98
99
  jsonResponse =
99
100
  typeof res.result === 'string'
100
101
  ? parseWeboutResponse(res.result, uploadUrl)
101
102
  : res.result
103
+
104
+ break
105
+ case ServerType.Sasjs:
106
+ jsonResponse =
107
+ typeof res.result === 'string'
108
+ ? getValidJson(res.result)
109
+ : res.result
110
+
102
111
  break
103
112
  }
104
113
  } else {
@@ -1,6 +1,9 @@
1
1
  export interface PollOptions {
2
2
  maxPollCount: number
3
- pollInterval: number
4
- streamLog: boolean
3
+ pollInterval: number // milliseconds
4
+ pollStrategy?: PollStrategy
5
+ streamLog?: boolean
5
6
  logFolderPath?: string
6
7
  }
8
+
9
+ export type PollStrategy = PollOptions[]
@@ -1,6 +1,8 @@
1
1
  export interface PollOptions {
2
2
  maxPollCount: number;
3
3
  pollInterval: number;
4
- streamLog: boolean;
4
+ pollStrategy?: PollStrategy;
5
+ streamLog?: boolean;
5
6
  logFolderPath?: string;
6
7
  }
8
+ export declare type PollStrategy = PollOptions[];