@sasjs/adapter 4.16.7 → 4.17.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/README.md +1 -0
- package/cypress.config.js +1 -1
- package/file/spec/generateTableUploadForm.spec.d.ts +1 -0
- package/index-dev.js +118 -2
- package/index.js +118 -2
- package/job-execution/WebJobExecutor.d.ts +1 -0
- package/job-execution/spec/executionTasks.spec.d.ts +1 -0
- package/minified_sas9.js +57 -1
- package/node/index.js +118 -2
- package/node/job-execution/WebJobExecutor.d.ts +1 -0
- package/node/types/SASjsConfig.d.ts +8 -0
- package/node/utils/index.d.ts +1 -0
- package/node/utils/parseViyaLogDebugResponse.d.ts +10 -0
- package/package.json +1 -1
- package/src/file/generateTableUploadForm.ts +7 -0
- package/src/job-execution/JobExecutor.ts +0 -1
- package/src/job-execution/WebJobExecutor.ts +78 -6
- package/src/types/SASjsConfig.ts +8 -0
- package/src/utils/index.ts +1 -0
- package/src/utils/parseViyaLogDebugResponse.ts +32 -0
- package/types/SASjsConfig.d.ts +8 -0
- package/utils/index.d.ts +1 -0
- package/utils/parseViyaLogDebugResponse.d.ts +10 -0
- package/utils/spec/parseViyaLogDebugResponse.spec.d.ts +1 -0
|
@@ -13,5 +13,6 @@ export declare class WebJobExecutor extends BaseJobExecutor {
|
|
|
13
13
|
private sasViyaApiClient;
|
|
14
14
|
constructor(serverUrl: string, serverType: ServerType, jobsPath: string, requestClient: RequestClient, sasViyaApiClient: SASViyaApiClient);
|
|
15
15
|
execute(sasJob: string, data: any, config: any, loginRequiredCallback?: any, authConfig?: AuthConfig, extraResponseAttributes?: ExtraResponseAttributes[]): Promise<unknown>;
|
|
16
|
+
protected getRequestParams(config: any): any;
|
|
16
17
|
private getJobUri;
|
|
17
18
|
}
|
|
@@ -79,6 +79,14 @@ export declare class SASjsConfig {
|
|
|
79
79
|
* may affect browser performance, especially with debug (logs) enabled.
|
|
80
80
|
*/
|
|
81
81
|
requestHistoryLimit?: number;
|
|
82
|
+
/**
|
|
83
|
+
* Optional setting. When `true`, the request runs as a Viya execution task —
|
|
84
|
+
* appends `_executionTasks=true` to the request URL. Only applies to the Viya
|
|
85
|
+
* web jobs path, i.e. when `serverType === SASVIYA` AND
|
|
86
|
+
* `useComputeApi` is `null`/`undefined`. Has no effect when `useComputeApi`
|
|
87
|
+
* is explicitly set to `true` or `false`.
|
|
88
|
+
*/
|
|
89
|
+
runAsTask?: boolean;
|
|
82
90
|
}
|
|
83
91
|
export declare enum LoginMechanism {
|
|
84
92
|
Default = "Default",
|
package/node/utils/index.d.ts
CHANGED
|
@@ -15,6 +15,7 @@ export * from './parseGeneratedCode';
|
|
|
15
15
|
export * from './parseSasViyaLog';
|
|
16
16
|
export * from './parseSourceCode';
|
|
17
17
|
export * from './parseViyaDebugResponse';
|
|
18
|
+
export * from './parseViyaLogDebugResponse';
|
|
18
19
|
export * from './parseWeboutResponse';
|
|
19
20
|
export * from './serialize';
|
|
20
21
|
export * from './splitChunks';
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* When querying a Viya job using the Web approach with _DEBUG=128 (used when
|
|
3
|
+
* runAsTask is true), the webout JSON is inlined into the response via:
|
|
4
|
+
* var blob = new Blob([`{...}`], {type: 'application/json'});
|
|
5
|
+
* On abort/error paths the same shape is used but with text/plain and
|
|
6
|
+
* weboutBEGIN/END markers around the JSON:
|
|
7
|
+
* var blob = new Blob([`>>weboutBEGIN<<\n{...}\n>>weboutEND<<\n`], {type: 'text/plain'});
|
|
8
|
+
* No follow-up request is needed — extract and parse the JSON directly.
|
|
9
|
+
*/
|
|
10
|
+
export declare const parseSasViyaLogDebugResponse: (response: any) => Promise<any>;
|
package/package.json
CHANGED
|
@@ -11,6 +11,13 @@ export const generateTableUploadForm = (
|
|
|
11
11
|
let tableCounter = 0
|
|
12
12
|
|
|
13
13
|
for (const tableName in data) {
|
|
14
|
+
if (
|
|
15
|
+
isFormatsTable(tableName) &&
|
|
16
|
+
Object.keys(data).includes(tableName.replace(/^\$/, ''))
|
|
17
|
+
) {
|
|
18
|
+
continue
|
|
19
|
+
}
|
|
20
|
+
|
|
14
21
|
tableCounter++
|
|
15
22
|
|
|
16
23
|
// Formats table should not be sent as part of 'sasjs_tables'
|
|
@@ -16,9 +16,11 @@ import { SASViyaApiClient } from '../SASViyaApiClient'
|
|
|
16
16
|
import {
|
|
17
17
|
isRelativePath,
|
|
18
18
|
parseSasViyaDebugResponse,
|
|
19
|
+
parseSasViyaLogDebugResponse,
|
|
19
20
|
appendExtraResponseAttributes,
|
|
20
21
|
parseWeboutResponse,
|
|
21
|
-
getFormData
|
|
22
|
+
getFormData,
|
|
23
|
+
isNode
|
|
22
24
|
} from '../utils'
|
|
23
25
|
import { BaseJobExecutor } from './JobExecutor'
|
|
24
26
|
|
|
@@ -101,6 +103,10 @@ export class WebJobExecutor extends BaseJobExecutor {
|
|
|
101
103
|
apiUrl += config.contextName?.trim()
|
|
102
104
|
? `&_contextname=${encodeURIComponent(config.contextName)}`
|
|
103
105
|
: ''
|
|
106
|
+
|
|
107
|
+
if (config.runAsTask === true) {
|
|
108
|
+
apiUrl += '&_executionTasks=true'
|
|
109
|
+
}
|
|
104
110
|
}
|
|
105
111
|
|
|
106
112
|
let requestParams = {
|
|
@@ -113,6 +119,26 @@ export class WebJobExecutor extends BaseJobExecutor {
|
|
|
113
119
|
*/
|
|
114
120
|
let formData = getFormData()
|
|
115
121
|
|
|
122
|
+
// FIXME(viya - SAS Track CS0409737): remove when Viya stops rejecting empty multipart on
|
|
123
|
+
// _executionTasks=true. Dummy file keeps the body non-empty
|
|
124
|
+
const hasExecutionTasksFlag = config.runAsTask === true
|
|
125
|
+
|
|
126
|
+
// Move debug params to URL for viya; viya seems to honor them more
|
|
127
|
+
// reliably in the query string than the multipart body.
|
|
128
|
+
if (
|
|
129
|
+
hasExecutionTasksFlag &&
|
|
130
|
+
config.debug &&
|
|
131
|
+
config.serverType === ServerType.SasViya
|
|
132
|
+
) {
|
|
133
|
+
const debugKeys = ['_debug', '_omitSessionResults']
|
|
134
|
+
debugKeys.forEach((key) => {
|
|
135
|
+
if (requestParams[key] !== undefined) {
|
|
136
|
+
apiUrl += `&${key}=${encodeURIComponent(requestParams[key])}`
|
|
137
|
+
delete requestParams[key]
|
|
138
|
+
}
|
|
139
|
+
})
|
|
140
|
+
}
|
|
141
|
+
|
|
116
142
|
if (data) {
|
|
117
143
|
const stringifiedData = JSON.stringify(data)
|
|
118
144
|
if (
|
|
@@ -133,10 +159,21 @@ export class WebJobExecutor extends BaseJobExecutor {
|
|
|
133
159
|
generateTableUploadForm(formData, data)
|
|
134
160
|
formData = newFormData
|
|
135
161
|
requestParams = { ...requestParams, ...params }
|
|
162
|
+
|
|
163
|
+
if (
|
|
164
|
+
config.serverType === ServerType.SasViya &&
|
|
165
|
+
hasExecutionTasksFlag
|
|
166
|
+
) {
|
|
167
|
+
addDummyFile(formData)
|
|
168
|
+
}
|
|
136
169
|
} catch (e: any) {
|
|
137
170
|
return Promise.reject(new ErrorResponse(e?.message, e))
|
|
138
171
|
}
|
|
139
172
|
}
|
|
173
|
+
} else {
|
|
174
|
+
if (config.serverType === ServerType.SasViya && hasExecutionTasksFlag) {
|
|
175
|
+
addDummyFile(formData)
|
|
176
|
+
}
|
|
140
177
|
}
|
|
141
178
|
|
|
142
179
|
for (const key in requestParams) {
|
|
@@ -168,11 +205,14 @@ export class WebJobExecutor extends BaseJobExecutor {
|
|
|
168
205
|
if (config.debug) {
|
|
169
206
|
switch (this.serverType) {
|
|
170
207
|
case ServerType.SasViya:
|
|
171
|
-
jsonResponse =
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
208
|
+
jsonResponse =
|
|
209
|
+
config.useComputeApi === null && config.runAsTask === true
|
|
210
|
+
? await parseSasViyaLogDebugResponse(res.result)
|
|
211
|
+
: await parseSasViyaDebugResponse(
|
|
212
|
+
res.result,
|
|
213
|
+
this.requestClient,
|
|
214
|
+
this.serverUrl
|
|
215
|
+
)
|
|
176
216
|
break
|
|
177
217
|
case ServerType.Sas9:
|
|
178
218
|
jsonResponse =
|
|
@@ -231,6 +271,23 @@ export class WebJobExecutor extends BaseJobExecutor {
|
|
|
231
271
|
return requestPromise
|
|
232
272
|
}
|
|
233
273
|
|
|
274
|
+
protected getRequestParams(config: any): any {
|
|
275
|
+
const requestParams = super.getRequestParams(config)
|
|
276
|
+
|
|
277
|
+
// FIXME(viya - possible issue with default debug flags)
|
|
278
|
+
// runAsTask on Viya: use _debug=128 (not 131) and omit _omittextlog
|
|
279
|
+
if (
|
|
280
|
+
config.debug &&
|
|
281
|
+
config.serverType === ServerType.SasViya &&
|
|
282
|
+
config.runAsTask === true
|
|
283
|
+
) {
|
|
284
|
+
requestParams['_debug'] = 128
|
|
285
|
+
delete requestParams['_omittextlog']
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
return requestParams
|
|
289
|
+
}
|
|
290
|
+
|
|
234
291
|
private async getJobUri(sasJob: string) {
|
|
235
292
|
if (!this.sasViyaApiClient) return ''
|
|
236
293
|
let uri = ''
|
|
@@ -263,3 +320,18 @@ export class WebJobExecutor extends BaseJobExecutor {
|
|
|
263
320
|
return uri
|
|
264
321
|
}
|
|
265
322
|
}
|
|
323
|
+
|
|
324
|
+
function addDummyFile(formData: NodeFormData | FormData) {
|
|
325
|
+
if (isNode()) {
|
|
326
|
+
;(formData as NodeFormData).append('_sasjs_noop', '', {
|
|
327
|
+
filename: '_sasjs_noop.txt',
|
|
328
|
+
contentType: 'text/plain'
|
|
329
|
+
})
|
|
330
|
+
} else {
|
|
331
|
+
;(formData as FormData).append(
|
|
332
|
+
'_sasjs_noop',
|
|
333
|
+
new Blob([''], { type: 'text/plain' }),
|
|
334
|
+
'_sasjs_noop.txt'
|
|
335
|
+
)
|
|
336
|
+
}
|
|
337
|
+
}
|
package/src/types/SASjsConfig.ts
CHANGED
|
@@ -79,6 +79,14 @@ export class SASjsConfig {
|
|
|
79
79
|
* may affect browser performance, especially with debug (logs) enabled.
|
|
80
80
|
*/
|
|
81
81
|
requestHistoryLimit?: number = 10
|
|
82
|
+
/**
|
|
83
|
+
* Optional setting. When `true`, the request runs as a Viya execution task —
|
|
84
|
+
* appends `_executionTasks=true` to the request URL. Only applies to the Viya
|
|
85
|
+
* web jobs path, i.e. when `serverType === SASVIYA` AND
|
|
86
|
+
* `useComputeApi` is `null`/`undefined`. Has no effect when `useComputeApi`
|
|
87
|
+
* is explicitly set to `true` or `false`.
|
|
88
|
+
*/
|
|
89
|
+
runAsTask?: boolean = false
|
|
82
90
|
}
|
|
83
91
|
|
|
84
92
|
export enum LoginMechanism {
|
package/src/utils/index.ts
CHANGED
|
@@ -15,6 +15,7 @@ export * from './parseGeneratedCode'
|
|
|
15
15
|
export * from './parseSasViyaLog'
|
|
16
16
|
export * from './parseSourceCode'
|
|
17
17
|
export * from './parseViyaDebugResponse'
|
|
18
|
+
export * from './parseViyaLogDebugResponse'
|
|
18
19
|
export * from './parseWeboutResponse'
|
|
19
20
|
export * from './serialize'
|
|
20
21
|
export * from './splitChunks'
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { getValidJson } from './getValidJson'
|
|
2
|
+
import { parseWeboutResponse } from './parseWeboutResponse'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* When querying a Viya job using the Web approach with _DEBUG=128 (used when
|
|
6
|
+
* runAsTask is true), the webout JSON is inlined into the response via:
|
|
7
|
+
* var blob = new Blob([`{...}`], {type: 'application/json'});
|
|
8
|
+
* On abort/error paths the same shape is used but with text/plain and
|
|
9
|
+
* weboutBEGIN/END markers around the JSON:
|
|
10
|
+
* var blob = new Blob([`>>weboutBEGIN<<\n{...}\n>>weboutEND<<\n`], {type: 'text/plain'});
|
|
11
|
+
* No follow-up request is needed — extract and parse the JSON directly.
|
|
12
|
+
*/
|
|
13
|
+
export const parseSasViyaLogDebugResponse = async (response: any) => {
|
|
14
|
+
// If upstream already parsed the response as JSON (object), pass through.
|
|
15
|
+
if (typeof response !== 'string') {
|
|
16
|
+
return response
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const blobMatch = response.match(
|
|
20
|
+
/new Blob\(\[`([\s\S]*?)`\],\s*\{type:\s*'(?:application\/json|text\/plain)'\}\)/
|
|
21
|
+
)
|
|
22
|
+
if (!blobMatch) {
|
|
23
|
+
throw new Error('Unable to find webout blob in debug log response.')
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const blobContent = blobMatch[1]
|
|
27
|
+
const stripped = blobContent.includes('>>weboutBEGIN<<')
|
|
28
|
+
? parseWeboutResponse(blobContent)
|
|
29
|
+
: blobContent
|
|
30
|
+
|
|
31
|
+
return getValidJson(stripped)
|
|
32
|
+
}
|
package/types/SASjsConfig.d.ts
CHANGED
|
@@ -79,6 +79,14 @@ export declare class SASjsConfig {
|
|
|
79
79
|
* may affect browser performance, especially with debug (logs) enabled.
|
|
80
80
|
*/
|
|
81
81
|
requestHistoryLimit?: number;
|
|
82
|
+
/**
|
|
83
|
+
* Optional setting. When `true`, the request runs as a Viya execution task —
|
|
84
|
+
* appends `_executionTasks=true` to the request URL. Only applies to the Viya
|
|
85
|
+
* web jobs path, i.e. when `serverType === SASVIYA` AND
|
|
86
|
+
* `useComputeApi` is `null`/`undefined`. Has no effect when `useComputeApi`
|
|
87
|
+
* is explicitly set to `true` or `false`.
|
|
88
|
+
*/
|
|
89
|
+
runAsTask?: boolean;
|
|
82
90
|
}
|
|
83
91
|
export declare enum LoginMechanism {
|
|
84
92
|
Default = "Default",
|
package/utils/index.d.ts
CHANGED
|
@@ -15,6 +15,7 @@ export * from './parseGeneratedCode';
|
|
|
15
15
|
export * from './parseSasViyaLog';
|
|
16
16
|
export * from './parseSourceCode';
|
|
17
17
|
export * from './parseViyaDebugResponse';
|
|
18
|
+
export * from './parseViyaLogDebugResponse';
|
|
18
19
|
export * from './parseWeboutResponse';
|
|
19
20
|
export * from './serialize';
|
|
20
21
|
export * from './splitChunks';
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* When querying a Viya job using the Web approach with _DEBUG=128 (used when
|
|
3
|
+
* runAsTask is true), the webout JSON is inlined into the response via:
|
|
4
|
+
* var blob = new Blob([`{...}`], {type: 'application/json'});
|
|
5
|
+
* On abort/error paths the same shape is used but with text/plain and
|
|
6
|
+
* weboutBEGIN/END markers around the JSON:
|
|
7
|
+
* var blob = new Blob([`>>weboutBEGIN<<\n{...}\n>>weboutEND<<\n`], {type: 'text/plain'});
|
|
8
|
+
* No follow-up request is needed — extract and parse the JSON directly.
|
|
9
|
+
*/
|
|
10
|
+
export declare const parseSasViyaLogDebugResponse: (response: any) => Promise<any>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|