mirror of
https://github.com/sasjs/adapter.git
synced 2026-01-03 18:50:05 +00:00
Compare commits
61 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9c5ada6fa1 | ||
|
|
0f5702e21b | ||
|
|
f10d6ec80a | ||
|
|
490215df90 | ||
|
|
9d27451813 | ||
|
|
a977f59675 | ||
|
|
47be5e77e5 | ||
|
|
d517e79ec0 | ||
|
|
8714ecdde8 | ||
|
|
2cffc57209 | ||
|
|
4e43687de2 | ||
|
|
f8dab83e37 | ||
|
|
655af03cf3 | ||
|
|
0a4dd00edb | ||
|
|
55b4929c54 | ||
|
|
8eb73a6b3c | ||
|
|
0aeb201625 | ||
|
|
e0140a23c2 | ||
|
|
ff6698a9d1 | ||
|
|
843d498b72 | ||
|
|
349612a065 | ||
|
|
e48b22128d | ||
|
|
14dfe4ec51 | ||
|
|
f679b17cbe | ||
|
|
36a0f0e743 | ||
|
|
ad563b9bc8 | ||
|
|
e0051bf276 | ||
|
|
7b72998e1c | ||
|
|
893cce7f21 | ||
|
|
bf7e8fd0e6 | ||
|
|
66d02cf1d1 | ||
|
|
f2c8e40430 | ||
|
|
4b28ee8e73 | ||
|
|
c7e54cfe9f | ||
|
|
50be3acc78 | ||
|
|
66c12a69bb | ||
|
|
e2058f0c71 | ||
|
|
75a74152a5 | ||
|
|
9344c4fd35 | ||
|
|
be0fe00076 | ||
|
|
a2069ee48b | ||
|
|
907885cf85 | ||
|
|
f10ed3236e | ||
|
|
a852a0af7c | ||
|
|
03f3550774 | ||
|
|
2e8d06f9e1 | ||
|
|
7a6e6e8333 | ||
|
|
cc594eca52 | ||
|
|
3fbca2835e | ||
|
|
61ed5c4fa7 | ||
|
|
9b6ba3548f | ||
|
|
efa4c71b8a | ||
|
|
ecfc1a4bf8 | ||
|
|
246b855c76 | ||
|
|
80aa848617 | ||
|
|
acf045965e | ||
|
|
5a7f64dc35 | ||
|
|
de447b0727 | ||
|
|
ace16efd93 | ||
|
|
13ae5ae756 | ||
|
|
f1b035032f |
4
.gitignore
vendored
4
.gitignore
vendored
@@ -3,4 +3,6 @@ build
|
|||||||
|
|
||||||
.env
|
.env
|
||||||
|
|
||||||
/coverage
|
/coverage
|
||||||
|
|
||||||
|
.DS_Store
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
328
docs/classes/auth.authmanager.html
Normal file
328
docs/classes/auth.authmanager.html
Normal file
File diff suppressed because one or more lines are too long
432
docs/classes/job_execution.basejobexecutor.html
Normal file
432
docs/classes/job_execution.basejobexecutor.html
Normal file
File diff suppressed because one or more lines are too long
435
docs/classes/job_execution.computejobexecutor.html
Normal file
435
docs/classes/job_execution.computejobexecutor.html
Normal file
File diff suppressed because one or more lines are too long
435
docs/classes/job_execution.jesjobexecutor.html
Normal file
435
docs/classes/job_execution.jesjobexecutor.html
Normal file
File diff suppressed because one or more lines are too long
441
docs/classes/job_execution.webjobexecutor.html
Normal file
441
docs/classes/job_execution.webjobexecutor.html
Normal file
File diff suppressed because one or more lines are too long
231
docs/classes/reflection-817.reflection-220.fileuploader.html
Normal file
231
docs/classes/reflection-817.reflection-220.fileuploader.html
Normal file
File diff suppressed because one or more lines are too long
312
docs/classes/reflection-817.reflection-220.sas9apiclient.html
Normal file
312
docs/classes/reflection-817.reflection-220.sas9apiclient.html
Normal file
File diff suppressed because one or more lines are too long
1715
docs/classes/reflection-817.reflection-220.sasjs.html
Normal file
1715
docs/classes/reflection-817.reflection-220.sasjs.html
Normal file
File diff suppressed because one or more lines are too long
1516
docs/classes/reflection-817.reflection-220.sasviyaapiclient.html
Normal file
1516
docs/classes/reflection-817.reflection-220.sasviyaapiclient.html
Normal file
File diff suppressed because one or more lines are too long
323
docs/classes/reflection-817.reflection-220.sessionmanager.html
Normal file
323
docs/classes/reflection-817.reflection-220.sessionmanager.html
Normal file
File diff suppressed because one or more lines are too long
231
docs/classes/reflection-830.reflection-222.fileuploader.html
Normal file
231
docs/classes/reflection-830.reflection-222.fileuploader.html
Normal file
File diff suppressed because one or more lines are too long
312
docs/classes/reflection-830.reflection-222.sas9apiclient.html
Normal file
312
docs/classes/reflection-830.reflection-222.sas9apiclient.html
Normal file
File diff suppressed because one or more lines are too long
1721
docs/classes/reflection-830.reflection-222.sasjs.html
Normal file
1721
docs/classes/reflection-830.reflection-222.sasjs.html
Normal file
File diff suppressed because one or more lines are too long
1528
docs/classes/reflection-830.reflection-222.sasviyaapiclient.html
Normal file
1528
docs/classes/reflection-830.reflection-222.sasviyaapiclient.html
Normal file
File diff suppressed because one or more lines are too long
360
docs/classes/reflection-830.reflection-222.sessionmanager.html
Normal file
360
docs/classes/reflection-830.reflection-222.sessionmanager.html
Normal file
File diff suppressed because one or more lines are too long
548
docs/classes/request.requestclient.html
Normal file
548
docs/classes/request.requestclient.html
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
328
docs/classes/types.authorizeerror.html
Normal file
328
docs/classes/types.authorizeerror.html
Normal file
File diff suppressed because one or more lines are too long
346
docs/classes/types.computejobexecutionerror.html
Normal file
346
docs/classes/types.computejobexecutionerror.html
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
367
docs/classes/types.jobexecutionerror.html
Normal file
367
docs/classes/types.jobexecutionerror.html
Normal file
File diff suppressed because one or more lines are too long
301
docs/classes/types.loginrequirederror.html
Normal file
301
docs/classes/types.loginrequirederror.html
Normal file
File diff suppressed because one or more lines are too long
325
docs/classes/types.notfounderror.html
Normal file
325
docs/classes/types.notfounderror.html
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
302
docs/interfaces/job_execution.jobexecutor.html
Normal file
302
docs/interfaces/job_execution.jobexecutor.html
Normal file
File diff suppressed because one or more lines are too long
392
docs/interfaces/request.httpclient.html
Normal file
392
docs/interfaces/request.httpclient.html
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
94
docs/modules/__mocks__.html
Normal file
94
docs/modules/__mocks__.html
Normal file
File diff suppressed because one or more lines are too long
179
docs/modules/auth.html
Normal file
179
docs/modules/auth.html
Normal file
File diff suppressed because one or more lines are too long
144
docs/modules/auth_spec.html
Normal file
144
docs/modules/auth_spec.html
Normal file
File diff suppressed because one or more lines are too long
184
docs/modules/file.html
Normal file
184
docs/modules/file.html
Normal file
File diff suppressed because one or more lines are too long
171
docs/modules/job_execution.html
Normal file
171
docs/modules/job_execution.html
Normal file
File diff suppressed because one or more lines are too long
106
docs/modules/reflection-817.html
Normal file
106
docs/modules/reflection-817.html
Normal file
File diff suppressed because one or more lines are too long
128
docs/modules/reflection-817.reflection-220.html
Normal file
128
docs/modules/reflection-817.reflection-220.html
Normal file
File diff suppressed because one or more lines are too long
106
docs/modules/reflection-830.html
Normal file
106
docs/modules/reflection-830.html
Normal file
File diff suppressed because one or more lines are too long
128
docs/modules/reflection-830.reflection-222.html
Normal file
128
docs/modules/reflection-830.reflection-222.html
Normal file
File diff suppressed because one or more lines are too long
118
docs/modules/request.html
Normal file
118
docs/modules/request.html
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
17303
package-lock.json
generated
17303
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -58,8 +58,8 @@
|
|||||||
},
|
},
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^0.21.1",
|
|
||||||
"@sasjs/utils": "^2.5.0",
|
"@sasjs/utils": "^2.5.0",
|
||||||
|
"axios": "^0.21.1",
|
||||||
"form-data": "^3.0.0",
|
"form-data": "^3.0.0",
|
||||||
"https": "^1.0.0"
|
"https": "^1.0.0"
|
||||||
}
|
}
|
||||||
|
|||||||
88
sasjs-tests/package-lock.json
generated
88
sasjs-tests/package-lock.json
generated
@@ -2004,21 +2004,19 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@sasjs/adapter": {
|
"@sasjs/adapter": {
|
||||||
"version": "2.1.0",
|
"version": "file:../build/sasjs-adapter-5.0.0.tgz",
|
||||||
"resolved": "https://registry.npmjs.org/@sasjs/adapter/-/adapter-2.1.0.tgz",
|
"integrity": "sha512-1t+3LIL2BFw8HpZUPI9QM24801+JH4DCAu4eHoLLmytYhN72asMi1aVtgSDb1xiJYgpbTG7EK3qRpHIV8cEN8w==",
|
||||||
"integrity": "sha512-FdvxAPzXHHwCurH5B1RxSGeO6h+lVqDGAtrTAQDByT7HhsikAMFi6mW5dJR/1CKcI2rLOdE/479yYqjwfX8nwg==",
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"@sasjs/utils": "^2.0.2",
|
"@sasjs/utils": "^2.5.0",
|
||||||
"es6-promise": "^4.2.8",
|
"axios": "^0.21.1",
|
||||||
"form-data": "^3.0.0",
|
"form-data": "^3.0.0",
|
||||||
"https": "^1.0.0",
|
"https": "^1.0.0"
|
||||||
"isomorphic-fetch": "^2.2.1"
|
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"form-data": {
|
"form-data": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz",
|
||||||
"integrity": "sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg==",
|
"integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"asynckit": "^0.4.0",
|
"asynckit": "^0.4.0",
|
||||||
"combined-stream": "^1.0.8",
|
"combined-stream": "^1.0.8",
|
||||||
@@ -2048,10 +2046,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@sasjs/utils": {
|
"@sasjs/utils": {
|
||||||
"version": "2.2.0",
|
"version": "2.5.1",
|
||||||
"resolved": "https://registry.npmjs.org/@sasjs/utils/-/utils-2.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/@sasjs/utils/-/utils-2.5.1.tgz",
|
||||||
"integrity": "sha512-T01TYAFU+WQ1uAUaunZXg0MotQe5jn3auVuMPPbY5RU5VhIn4oVhr6qz3EHyNsYYKD1aj5pP7w2elnBzkgWhGw==",
|
"integrity": "sha512-a3ISiUX8Yz7au4XYxq2KWf9ODT6nsIDbE4FEqS+AQ3McxZkfuAk4v+REXjOmIlcyQd4R4bufEK8XoB6AROn9sA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
|
"@types/prompts": "^2.0.9",
|
||||||
"consola": "^2.15.0",
|
"consola": "^2.15.0",
|
||||||
"prompts": "^2.4.0",
|
"prompts": "^2.4.0",
|
||||||
"valid-url": "^1.0.9"
|
"valid-url": "^1.0.9"
|
||||||
@@ -2366,6 +2365,14 @@
|
|||||||
"resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.1.6.tgz",
|
"resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.1.6.tgz",
|
||||||
"integrity": "sha512-6gOkRe7OIioWAXfnO/2lFiv+SJichKVSys1mSsgyrYHSEjk8Ctv4tSR/Odvnu+HWlH2C8j53dahU03XmQdd5fA=="
|
"integrity": "sha512-6gOkRe7OIioWAXfnO/2lFiv+SJichKVSys1mSsgyrYHSEjk8Ctv4tSR/Odvnu+HWlH2C8j53dahU03XmQdd5fA=="
|
||||||
},
|
},
|
||||||
|
"@types/prompts": {
|
||||||
|
"version": "2.0.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/prompts/-/prompts-2.0.9.tgz",
|
||||||
|
"integrity": "sha512-TORZP+FSjTYMWwKadftmqEn6bziN5RnfygehByGsjxoK5ydnClddtv6GikGWPvCm24oI+YBwck5WDxIIyNxUrA==",
|
||||||
|
"requires": {
|
||||||
|
"@types/node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@types/prop-types": {
|
"@types/prop-types": {
|
||||||
"version": "15.7.3",
|
"version": "15.7.3",
|
||||||
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.3.tgz",
|
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.3.tgz",
|
||||||
@@ -3396,6 +3403,14 @@
|
|||||||
"resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.1.1.tgz",
|
||||||
"integrity": "sha512-5Kgy8Cz6LPC9DJcNb3yjAXTu3XihQgEdnIg50c//zOC/MyLP0Clg+Y8Sh9ZjjnvBrDZU4DgXS9C3T9r4/scGZQ=="
|
"integrity": "sha512-5Kgy8Cz6LPC9DJcNb3yjAXTu3XihQgEdnIg50c//zOC/MyLP0Clg+Y8Sh9ZjjnvBrDZU4DgXS9C3T9r4/scGZQ=="
|
||||||
},
|
},
|
||||||
|
"axios": {
|
||||||
|
"version": "0.21.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz",
|
||||||
|
"integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==",
|
||||||
|
"requires": {
|
||||||
|
"follow-redirects": "^1.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"axobject-query": {
|
"axobject-query": {
|
||||||
"version": "2.2.0",
|
"version": "2.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz",
|
||||||
@@ -4677,9 +4692,9 @@
|
|||||||
"integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg=="
|
"integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg=="
|
||||||
},
|
},
|
||||||
"consola": {
|
"consola": {
|
||||||
"version": "2.15.2",
|
"version": "2.15.3",
|
||||||
"resolved": "https://registry.npmjs.org/consola/-/consola-2.15.2.tgz",
|
"resolved": "https://registry.npmjs.org/consola/-/consola-2.15.3.tgz",
|
||||||
"integrity": "sha512-VxqWw5C8O/mQpZYtfaaSCDJcVK3AxyvQ26rhgvyAI4j/QJISh8DLwFS8GQU+9154u4ngyCsSlnyIAYJme9kQug=="
|
"integrity": "sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw=="
|
||||||
},
|
},
|
||||||
"console-browserify": {
|
"console-browserify": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
@@ -5722,24 +5737,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
|
||||||
"integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
|
"integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
|
||||||
},
|
},
|
||||||
"encoding": {
|
|
||||||
"version": "0.1.13",
|
|
||||||
"resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz",
|
|
||||||
"integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==",
|
|
||||||
"requires": {
|
|
||||||
"iconv-lite": "^0.6.2"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"iconv-lite": {
|
|
||||||
"version": "0.6.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.2.tgz",
|
|
||||||
"integrity": "sha512-2y91h5OpQlolefMPmUlivelittSWy0rP+oYVpn6A7GwVHNE8AWzoYOBNmlwks3LobaJxgHCYZAnyNo2GgpNRNQ==",
|
|
||||||
"requires": {
|
|
||||||
"safer-buffer": ">= 2.1.2 < 3.0.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"end-of-stream": {
|
"end-of-stream": {
|
||||||
"version": "1.4.4",
|
"version": "1.4.4",
|
||||||
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
|
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
|
||||||
@@ -5882,11 +5879,6 @@
|
|||||||
"es6-symbol": "^3.1.1"
|
"es6-symbol": "^3.1.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"es6-promise": {
|
|
||||||
"version": "4.2.8",
|
|
||||||
"resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz",
|
|
||||||
"integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w=="
|
|
||||||
},
|
|
||||||
"es6-symbol": {
|
"es6-symbol": {
|
||||||
"version": "3.1.3",
|
"version": "3.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz",
|
||||||
@@ -8584,15 +8576,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
|
||||||
"integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8="
|
"integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8="
|
||||||
},
|
},
|
||||||
"isomorphic-fetch": {
|
|
||||||
"version": "2.2.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz",
|
|
||||||
"integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=",
|
|
||||||
"requires": {
|
|
||||||
"node-fetch": "^1.0.1",
|
|
||||||
"whatwg-fetch": ">=0.10.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"isstream": {
|
"isstream": {
|
||||||
"version": "0.1.2",
|
"version": "0.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
|
||||||
@@ -11423,15 +11406,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node-fetch": {
|
|
||||||
"version": "1.7.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz",
|
|
||||||
"integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==",
|
|
||||||
"requires": {
|
|
||||||
"encoding": "^0.1.11",
|
|
||||||
"is-stream": "^1.0.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node-forge": {
|
"node-forge": {
|
||||||
"version": "0.10.0",
|
"version": "0.10.0",
|
||||||
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz",
|
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz",
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"homepage": ".",
|
"homepage": ".",
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@sasjs/adapter": "^2.1.0",
|
"@sasjs/adapter": "^2.2.4",
|
||||||
"@sasjs/test-framework": "^1.4.0",
|
"@sasjs/test-framework": "^1.4.0",
|
||||||
"@types/jest": "^26.0.20",
|
"@types/jest": "^26.0.20",
|
||||||
"@types/node": "^14.14.25",
|
"@types/node": "^14.14.25",
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
"appLoc": "/Public/app",
|
"appLoc": "/Public/app",
|
||||||
"serverType": "SASVIYA",
|
"serverType": "SASVIYA",
|
||||||
"debug": false,
|
"debug": false,
|
||||||
"contextName": "SharedCompute",
|
"contextName": "sasjs adapter compute context",
|
||||||
"useComputeApi": true
|
"useComputeApi": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ import SASjs, { SASjsConfig } from "@sasjs/adapter";
|
|||||||
import { TestSuite } from "@sasjs/test-framework";
|
import { TestSuite } from "@sasjs/test-framework";
|
||||||
import { ServerType } from "@sasjs/utils/types";
|
import { ServerType } from "@sasjs/utils/types";
|
||||||
|
|
||||||
|
const stringData: any = { table1: [{ col1: "first col value" }] };
|
||||||
|
|
||||||
const defaultConfig: SASjsConfig = {
|
const defaultConfig: SASjsConfig = {
|
||||||
serverUrl: window.location.origin,
|
serverUrl: window.location.origin,
|
||||||
pathSAS9: "/SASStoredProcess/do",
|
pathSAS9: "/SASStoredProcess/do",
|
||||||
@@ -51,6 +53,36 @@ export const basicTests = (
|
|||||||
assertion: (response: any) =>
|
assertion: (response: any) =>
|
||||||
response && response.isLoggedIn && response.userName === userName
|
response && response.isLoggedIn && response.userName === userName
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: "Trigger login callback",
|
||||||
|
description:
|
||||||
|
"Should trigger required login callback and after successful login, it should finish the request",
|
||||||
|
test: async () => {
|
||||||
|
await adapter.logOut();
|
||||||
|
|
||||||
|
return await adapter.request("common/sendArr", stringData, null, () => {
|
||||||
|
adapter.logIn(userName, password);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
assertion: (response: any) => {
|
||||||
|
return response.table1[0][0] === stringData.table1[0].col1;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Request with debug on",
|
||||||
|
description:
|
||||||
|
"Should complete successful request with debugging switched on",
|
||||||
|
test: async () => {
|
||||||
|
const config = {
|
||||||
|
debug: true
|
||||||
|
}
|
||||||
|
|
||||||
|
return await adapter.request("common/sendArr", stringData, config)
|
||||||
|
},
|
||||||
|
assertion: (response: any) => {
|
||||||
|
return response.table1[0][0] === stringData.table1[0].col1;
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: "Default config",
|
title: "Default config",
|
||||||
description:
|
description:
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import { isAuthorizeFormRequired } from './auth/isAuthorizeFormRequired'
|
|||||||
import { RequestClient } from './request/RequestClient'
|
import { RequestClient } from './request/RequestClient'
|
||||||
import { NotFoundError } from './types/NotFoundError'
|
import { NotFoundError } from './types/NotFoundError'
|
||||||
import { SasAuthResponse } from '@sasjs/utils/types'
|
import { SasAuthResponse } from '@sasjs/utils/types'
|
||||||
|
import { prefixMessage } from '@sasjs/utils/error'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A client for interfacing with the SAS Viya REST API.
|
* A client for interfacing with the SAS Viya REST API.
|
||||||
@@ -280,25 +281,24 @@ export class SASViyaApiClient {
|
|||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
}
|
}
|
||||||
|
|
||||||
if (accessToken) {
|
if (accessToken) headers.Authorization = `Bearer ${accessToken}`
|
||||||
headers.Authorization = `Bearer ${accessToken}`
|
|
||||||
}
|
|
||||||
|
|
||||||
let executionSessionId: string
|
let executionSessionId: string
|
||||||
|
|
||||||
const session = await this.sessionManager
|
const session = await this.sessionManager
|
||||||
.getSession(accessToken)
|
.getSession(accessToken)
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
throw err
|
throw prefixMessage(err, 'Error while getting session. ')
|
||||||
})
|
})
|
||||||
|
|
||||||
executionSessionId = session!.id
|
executionSessionId = session!.id
|
||||||
|
|
||||||
if (printPid) {
|
if (printPid) {
|
||||||
const { result: jobIdVariable } = await this.sessionManager.getVariable(
|
const { result: jobIdVariable } = await this.sessionManager
|
||||||
executionSessionId,
|
.getVariable(executionSessionId, 'SYSJOBID', accessToken)
|
||||||
'SYSJOBID',
|
.catch((err) => {
|
||||||
accessToken
|
throw prefixMessage(err, 'Error while getting session variable. ')
|
||||||
)
|
})
|
||||||
|
|
||||||
if (jobIdVariable && jobIdVariable.value) {
|
if (jobIdVariable && jobIdVariable.value) {
|
||||||
const relativeJobPath = this.rootFolderName
|
const relativeJobPath = this.rootFolderName
|
||||||
@@ -331,6 +331,7 @@ export class SASViyaApiClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let fileName
|
let fileName
|
||||||
|
|
||||||
if (isRelativePath(jobPath)) {
|
if (isRelativePath(jobPath)) {
|
||||||
fileName = `exec-${
|
fileName = `exec-${
|
||||||
jobPath.includes('/') ? jobPath.split('/')[1] : jobPath
|
jobPath.includes('/') ? jobPath.split('/')[1] : jobPath
|
||||||
@@ -352,7 +353,7 @@ export class SASViyaApiClient {
|
|||||||
if (data) {
|
if (data) {
|
||||||
if (JSON.stringify(data).includes(';')) {
|
if (JSON.stringify(data).includes(';')) {
|
||||||
files = await this.uploadTables(data, accessToken).catch((err) => {
|
files = await this.uploadTables(data, accessToken).catch((err) => {
|
||||||
throw err
|
throw prefixMessage(err, 'Error while uploading tables. ')
|
||||||
})
|
})
|
||||||
|
|
||||||
jobVariables['_webin_file_count'] = files.length
|
jobVariables['_webin_file_count'] = files.length
|
||||||
@@ -376,19 +377,18 @@ export class SASViyaApiClient {
|
|||||||
variables: jobVariables,
|
variables: jobVariables,
|
||||||
arguments: jobArguments
|
arguments: jobArguments
|
||||||
}
|
}
|
||||||
|
|
||||||
const { result: postedJob, etag } = await this.requestClient
|
const { result: postedJob, etag } = await this.requestClient
|
||||||
.post<Job>(
|
.post<Job>(
|
||||||
`/compute/sessions/${executionSessionId}/jobs`,
|
`/compute/sessions/${executionSessionId}/jobs`,
|
||||||
jobRequestBody,
|
jobRequestBody,
|
||||||
accessToken
|
accessToken
|
||||||
)
|
)
|
||||||
.catch((err: any) => {
|
.catch((err) => {
|
||||||
throw err
|
throw prefixMessage(err, 'Error while posting job. ')
|
||||||
})
|
})
|
||||||
|
|
||||||
if (!waitForResult) {
|
if (!waitForResult) return session
|
||||||
return session
|
|
||||||
}
|
|
||||||
|
|
||||||
if (debug) {
|
if (debug) {
|
||||||
console.log(`Job has been submitted for '${fileName}'.`)
|
console.log(`Job has been submitted for '${fileName}'.`)
|
||||||
@@ -404,7 +404,9 @@ export class SASViyaApiClient {
|
|||||||
etag,
|
etag,
|
||||||
accessToken,
|
accessToken,
|
||||||
pollOptions
|
pollOptions
|
||||||
)
|
).catch((err) => {
|
||||||
|
throw prefixMessage(err, 'Error while polling job status. ')
|
||||||
|
})
|
||||||
|
|
||||||
const { result: currentJob } = await this.requestClient
|
const { result: currentJob } = await this.requestClient
|
||||||
.get<Job>(
|
.get<Job>(
|
||||||
@@ -412,7 +414,7 @@ export class SASViyaApiClient {
|
|||||||
accessToken
|
accessToken
|
||||||
)
|
)
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
throw err
|
throw prefixMessage(err, 'Error while getting job. ')
|
||||||
})
|
})
|
||||||
|
|
||||||
let jobResult
|
let jobResult
|
||||||
@@ -427,7 +429,7 @@ export class SASViyaApiClient {
|
|||||||
res.result.items.map((i: any) => i.line).join('\n')
|
res.result.items.map((i: any) => i.line).join('\n')
|
||||||
)
|
)
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
throw err
|
throw prefixMessage(err, 'Error while getting log. ')
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -455,7 +457,7 @@ export class SASViyaApiClient {
|
|||||||
res.result.items.map((i: any) => i.line).join('\n')
|
res.result.items.map((i: any) => i.line).join('\n')
|
||||||
)
|
)
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
throw err
|
throw prefixMessage(err, 'Error while getting log. ')
|
||||||
})
|
})
|
||||||
|
|
||||||
return Promise.reject({
|
return Promise.reject({
|
||||||
@@ -464,6 +466,7 @@ export class SASViyaApiClient {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
result: JSON.stringify(e)
|
result: JSON.stringify(e)
|
||||||
}
|
}
|
||||||
@@ -473,7 +476,7 @@ export class SASViyaApiClient {
|
|||||||
await this.sessionManager
|
await this.sessionManager
|
||||||
.clearSession(executionSessionId, accessToken)
|
.clearSession(executionSessionId, accessToken)
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
throw err
|
throw prefixMessage(err, 'Error while clearing session. ')
|
||||||
})
|
})
|
||||||
|
|
||||||
return { result: jobResult?.result, log }
|
return { result: jobResult?.result, log }
|
||||||
@@ -490,7 +493,7 @@ export class SASViyaApiClient {
|
|||||||
true
|
true
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
throw e
|
throw prefixMessage(e, 'Error while executing script. ')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -814,9 +817,12 @@ export class SASViyaApiClient {
|
|||||||
? `${this.rootFolderName}/${folderPath}`
|
? `${this.rootFolderName}/${folderPath}`
|
||||||
: folderPath
|
: folderPath
|
||||||
|
|
||||||
await this.populateFolderMap(fullFolderPath, accessToken)
|
await this.populateFolderMap(fullFolderPath, accessToken).catch((err) => {
|
||||||
|
throw prefixMessage(err, 'Error while populating folder map. ')
|
||||||
|
})
|
||||||
|
|
||||||
const jobFolder = this.folderMap.get(fullFolderPath)
|
const jobFolder = this.folderMap.get(fullFolderPath)
|
||||||
|
|
||||||
if (!jobFolder) {
|
if (!jobFolder) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`The folder '${fullFolderPath}' was not found on '${this.serverUrl}'`
|
`The folder '${fullFolderPath}' was not found on '${this.serverUrl}'`
|
||||||
@@ -824,6 +830,7 @@ export class SASViyaApiClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const headers: any = { 'Content-Type': 'application/json' }
|
const headers: any = { 'Content-Type': 'application/json' }
|
||||||
|
|
||||||
if (!!accessToken) {
|
if (!!accessToken) {
|
||||||
headers.Authorization = `Bearer ${accessToken}`
|
headers.Authorization = `Bearer ${accessToken}`
|
||||||
}
|
}
|
||||||
@@ -847,10 +854,14 @@ export class SASViyaApiClient {
|
|||||||
|
|
||||||
const {
|
const {
|
||||||
result: jobDefinition
|
result: jobDefinition
|
||||||
} = await this.requestClient.get<JobDefinition>(
|
} = await this.requestClient
|
||||||
`${this.serverUrl}${jobDefinitionLink.href}`,
|
.get<JobDefinition>(
|
||||||
accessToken
|
`${this.serverUrl}${jobDefinitionLink.href}`,
|
||||||
)
|
accessToken
|
||||||
|
)
|
||||||
|
.catch((err) => {
|
||||||
|
throw prefixMessage(err, 'Error while getting job definition. ')
|
||||||
|
})
|
||||||
|
|
||||||
code = jobDefinition.code
|
code = jobDefinition.code
|
||||||
|
|
||||||
@@ -861,6 +872,7 @@ export class SASViyaApiClient {
|
|||||||
if (!code) code = ''
|
if (!code) code = ''
|
||||||
|
|
||||||
const linesToExecute = code.replace(/\r\n/g, '\n').split('\n')
|
const linesToExecute = code.replace(/\r\n/g, '\n').split('\n')
|
||||||
|
|
||||||
return await this.executeScript(
|
return await this.executeScript(
|
||||||
sasJob,
|
sasJob,
|
||||||
linesToExecute,
|
linesToExecute,
|
||||||
@@ -965,7 +977,13 @@ export class SASViyaApiClient {
|
|||||||
postJobRequestBody,
|
postJobRequestBody,
|
||||||
accessToken
|
accessToken
|
||||||
)
|
)
|
||||||
const jobStatus = await this.pollJobState(postedJob, etag, accessToken)
|
const jobStatus = await this.pollJobState(
|
||||||
|
postedJob,
|
||||||
|
etag,
|
||||||
|
accessToken
|
||||||
|
).catch((err) => {
|
||||||
|
throw prefixMessage(err, 'Error while polling job status. ')
|
||||||
|
})
|
||||||
const { result: currentJob } = await this.requestClient.get<Job>(
|
const { result: currentJob } = await this.requestClient.get<Job>(
|
||||||
`${this.serverUrl}/jobExecution/jobs/${postedJob.id}`,
|
`${this.serverUrl}/jobExecution/jobs/${postedJob.id}`,
|
||||||
accessToken
|
accessToken
|
||||||
@@ -1007,19 +1025,27 @@ export class SASViyaApiClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const url = '/folders/folders/@item?path=' + path
|
const url = '/folders/folders/@item?path=' + path
|
||||||
const { result: folder } = await this.requestClient.get<Folder>(
|
const { result: folder } = await this.requestClient
|
||||||
`${url}`,
|
.get<Folder>(`${url}`, accessToken)
|
||||||
accessToken
|
.catch((err) => {
|
||||||
)
|
throw prefixMessage(err, 'Error while getting folder. ')
|
||||||
|
})
|
||||||
|
|
||||||
if (!folder) {
|
if (!folder) {
|
||||||
throw new Error(`The path ${path} does not exist on ${this.serverUrl}`)
|
throw new Error(`The path ${path} does not exist on ${this.serverUrl}`)
|
||||||
}
|
}
|
||||||
const { result: members } = await this.requestClient.get<{ items: any[] }>(
|
|
||||||
`/folders/folders/${folder.id}/members?limit=${folder.memberCount}`,
|
const { result: members } = await this.requestClient
|
||||||
accessToken
|
.get<{ items: any[] }>(
|
||||||
)
|
`/folders/folders/${folder.id}/members?limit=${folder.memberCount}`,
|
||||||
|
accessToken
|
||||||
|
)
|
||||||
|
.catch((err) => {
|
||||||
|
throw prefixMessage(err, 'Error while getting members. ')
|
||||||
|
})
|
||||||
|
|
||||||
const itemsAtRoot = members.items
|
const itemsAtRoot = members.items
|
||||||
|
|
||||||
this.folderMap.set(path, itemsAtRoot)
|
this.folderMap.set(path, itemsAtRoot)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1052,11 +1078,15 @@ export class SASViyaApiClient {
|
|||||||
Promise.reject(`Job state link was not found.`)
|
Promise.reject(`Job state link was not found.`)
|
||||||
}
|
}
|
||||||
|
|
||||||
const { result: state } = await this.requestClient.get<string>(
|
const { result: state } = await this.requestClient
|
||||||
`${this.serverUrl}${stateLink.href}?_action=wait&wait=30`,
|
.get<string>(
|
||||||
accessToken,
|
`${this.serverUrl}${stateLink.href}?_action=wait&wait=30`,
|
||||||
'text/plain'
|
accessToken,
|
||||||
)
|
'text/plain'
|
||||||
|
)
|
||||||
|
.catch((err) => {
|
||||||
|
throw prefixMessage(err, 'Error while getting job state. ')
|
||||||
|
})
|
||||||
|
|
||||||
const currentState = state.trim()
|
const currentState = state.trim()
|
||||||
if (currentState === 'completed') {
|
if (currentState === 'completed') {
|
||||||
@@ -1073,11 +1103,15 @@ export class SASViyaApiClient {
|
|||||||
postedJobState === 'pending'
|
postedJobState === 'pending'
|
||||||
) {
|
) {
|
||||||
if (stateLink) {
|
if (stateLink) {
|
||||||
const { result: jobState } = await this.requestClient.get<string>(
|
const { result: jobState } = await this.requestClient
|
||||||
`${this.serverUrl}${stateLink.href}?_action=wait&wait=30`,
|
.get<string>(
|
||||||
accessToken,
|
`${this.serverUrl}${stateLink.href}?_action=wait&wait=30`,
|
||||||
'text/plain'
|
accessToken,
|
||||||
)
|
'text/plain'
|
||||||
|
)
|
||||||
|
.catch((err) => {
|
||||||
|
throw prefixMessage(err, 'Error while getting job state. ')
|
||||||
|
})
|
||||||
|
|
||||||
postedJobState = jobState.trim()
|
postedJobState = jobState.trim()
|
||||||
|
|
||||||
@@ -1119,19 +1153,25 @@ export class SASViyaApiClient {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const uploadResponse = await this.requestClient.uploadFile(
|
const uploadResponse = await this.requestClient
|
||||||
`${this.serverUrl}/files/files#rawUpload`,
|
.uploadFile(`${this.serverUrl}/files/files#rawUpload`, csv, accessToken)
|
||||||
csv,
|
.catch((err) => {
|
||||||
accessToken
|
throw prefixMessage(err, 'Error while uploading file. ')
|
||||||
)
|
})
|
||||||
|
|
||||||
uploadedFiles.push({ tableName, file: uploadResponse.result })
|
uploadedFiles.push({ tableName, file: uploadResponse.result })
|
||||||
}
|
}
|
||||||
return uploadedFiles
|
return uploadedFiles
|
||||||
}
|
}
|
||||||
|
|
||||||
private async getFolderUri(folderPath: string, accessToken?: string) {
|
private async getFolderDetails(
|
||||||
const url = '/folders/folders/@item?path=' + folderPath
|
folderPath: string,
|
||||||
|
accessToken?: string
|
||||||
|
): Promise<Folder | undefined> {
|
||||||
|
const url = isUri(folderPath)
|
||||||
|
? folderPath
|
||||||
|
: `/folders/folders/@item?path=${folderPath}`
|
||||||
|
|
||||||
const { result: folder } = await this.requestClient
|
const { result: folder } = await this.requestClient
|
||||||
.get<Folder>(`${this.serverUrl}${url}`, accessToken)
|
.get<Folder>(`${this.serverUrl}${url}`, accessToken)
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
@@ -1139,7 +1179,15 @@ export class SASViyaApiClient {
|
|||||||
})
|
})
|
||||||
|
|
||||||
if (!folder) return undefined
|
if (!folder) return undefined
|
||||||
return `/folders/folders/${folder.id}`
|
return folder
|
||||||
|
}
|
||||||
|
|
||||||
|
private async getFolderUri(folderPath: string, accessToken?: string) {
|
||||||
|
const folderDetails = await this.getFolderDetails(folderPath, accessToken)
|
||||||
|
|
||||||
|
if (!folderDetails) return undefined
|
||||||
|
|
||||||
|
return `/folders/folders/${folderDetails.id}`
|
||||||
}
|
}
|
||||||
|
|
||||||
private async getRecycleBinUri(accessToken: string) {
|
private async getRecycleBinUri(accessToken: string) {
|
||||||
@@ -1188,9 +1236,44 @@ export class SASViyaApiClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Moves a Viya folder to a new location. The folder may be renamed at the same time.
|
* Lists children folders for given Viya folder.
|
||||||
|
* @param sourceFolder - the full path (eg `/Public/example/myFolder`) or URI of the source folder listed. Providing URI instead of path will save one extra request.
|
||||||
|
* @param accessToken - an access token for authorizing the request.
|
||||||
|
*/
|
||||||
|
public async listFolder(
|
||||||
|
sourceFolder: string,
|
||||||
|
accessToken?: string,
|
||||||
|
limit: number = 20
|
||||||
|
) {
|
||||||
|
// checks if 'sourceFolder' is already a URI
|
||||||
|
const sourceFolderUri = isUri(sourceFolder)
|
||||||
|
? sourceFolder
|
||||||
|
: await this.getFolderUri(sourceFolder, accessToken)
|
||||||
|
|
||||||
|
const requestInfo = {
|
||||||
|
method: 'GET',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
Authorization: 'Bearer ' + accessToken
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const { result: members } = await this.requestClient.get<{ items: any[] }>(
|
||||||
|
`${this.serverUrl}${sourceFolderUri}/members?limit=${limit}`,
|
||||||
|
accessToken
|
||||||
|
)
|
||||||
|
|
||||||
|
if (members && members.items) {
|
||||||
|
return members.items.map((item: any) => item.name)
|
||||||
|
} else {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Moves Viya folder to a new location. The folder may be renamed at the same time.
|
||||||
* @param sourceFolder - the full path (eg `/Public/example/myFolder`) or URI of the source folder to be moved. Providing URI instead of path will save one extra request.
|
* @param sourceFolder - the full path (eg `/Public/example/myFolder`) or URI of the source folder to be moved. Providing URI instead of path will save one extra request.
|
||||||
* @param targetParentFolder - the full path or URI of the _parent_ folder to which the `sourceFolder` will be moved (eg `/Public/newDestination`). To move a folder, a user has to have write permissions in targetParentFolder. Providing URI instead of path will save one extra request.
|
* @param targetParentFolder - the full path or URI of the _parent_ folder to which the `sourceFolder` will be moved (eg `/Public/newDestination`). To move a folder, a user has to have write permissions in targetParentFolder. Providing URI instead of the path will save one extra request.
|
||||||
* @param targetFolderName - the name of the "moved" folder. If left blank, the original folder name will be used (eg `myFolder` in `/Public/newDestination/myFolder` for the example above). Optional field.
|
* @param targetFolderName - the name of the "moved" folder. If left blank, the original folder name will be used (eg `myFolder` in `/Public/newDestination/myFolder` for the example above). Optional field.
|
||||||
* @param accessToken - an access token for authorizing the request.
|
* @param accessToken - an access token for authorizing the request.
|
||||||
*/
|
*/
|
||||||
@@ -1200,22 +1283,35 @@ export class SASViyaApiClient {
|
|||||||
targetFolderName: string,
|
targetFolderName: string,
|
||||||
accessToken: string
|
accessToken: string
|
||||||
) {
|
) {
|
||||||
// checks if 'sourceFolder' is already a URI
|
// If target path is an existing folder, than keep source folder name, othervise rename it with given target folder name
|
||||||
const sourceFolderUri = isUri(sourceFolder)
|
const sourceFolderName = sourceFolder.split('/').pop() as string
|
||||||
? sourceFolder
|
const targetFolderDetails = await this.getFolderDetails(
|
||||||
: await this.getFolderUri(sourceFolder, accessToken)
|
targetParentFolder,
|
||||||
|
accessToken
|
||||||
|
)
|
||||||
|
|
||||||
|
if (!targetFolderDetails) {
|
||||||
|
let targetParentFolderArr = targetParentFolder.split('/')
|
||||||
|
targetParentFolderArr.splice(targetParentFolderArr.length - 1, 1)
|
||||||
|
targetParentFolder = targetParentFolderArr.join('/')
|
||||||
|
} else {
|
||||||
|
targetFolderName = sourceFolderName
|
||||||
|
}
|
||||||
|
|
||||||
|
// checks if 'sourceFolder' is already an URI
|
||||||
|
const sourceFolderUri = await this.getFolderUri(sourceFolder, accessToken)
|
||||||
|
|
||||||
// checks if 'targetParentFolder' is already a URI
|
// checks if 'targetParentFolder' is already a URI
|
||||||
const targetParentFolderUri = isUri(targetParentFolder)
|
const targetParentFolderUri = await this.getFolderUri(
|
||||||
? targetParentFolder
|
targetParentFolder,
|
||||||
: await this.getFolderUri(targetParentFolder, accessToken)
|
accessToken
|
||||||
|
)
|
||||||
|
|
||||||
const sourceFolderId = sourceFolderUri?.split('/').pop()
|
const sourceFolderId = sourceFolderUri?.split('/').pop()
|
||||||
const url = sourceFolderUri
|
|
||||||
|
|
||||||
const { result: folder } = await this.requestClient
|
const { result: folder } = await this.requestClient
|
||||||
.patch<Folder>(
|
.patch<Folder>(
|
||||||
`${this.serverUrl}${url}`,
|
`${this.serverUrl}${sourceFolderUri}`,
|
||||||
{
|
{
|
||||||
id: sourceFolderId,
|
id: sourceFolderId,
|
||||||
name: targetFolderName,
|
name: targetFolderName,
|
||||||
|
|||||||
19
src/SASjs.ts
19
src/SASjs.ts
@@ -317,6 +317,25 @@ export default class SASjs {
|
|||||||
return await this.sasViyaApiClient?.deleteFolder(folderPath, accessToken)
|
return await this.sasViyaApiClient?.deleteFolder(folderPath, accessToken)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lists children folders for given Viya folder.
|
||||||
|
* @param sourceFolder - the full path (eg `/Public/example/myFolder`) or URI of the source folder listed. Providing URI instead of path will save one extra request.
|
||||||
|
* @param accessToken - an access token for authorizing the request.
|
||||||
|
*/
|
||||||
|
public async listFolder(
|
||||||
|
sourceFolder: string,
|
||||||
|
accessToken?: string,
|
||||||
|
limit?: number
|
||||||
|
) {
|
||||||
|
this.isMethodSupported('listFolder', ServerType.SasViya)
|
||||||
|
|
||||||
|
return await this.sasViyaApiClient?.listFolder(
|
||||||
|
sourceFolder,
|
||||||
|
accessToken,
|
||||||
|
limit
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Moves folder to a new location. The folder may be renamed at the same time.
|
* Moves folder to a new location. The folder may be renamed at the same time.
|
||||||
* @param sourceFolder - the full path (eg `/Public/example/myFolder`) or URI of the source folder to be moved. Providing URI instead of path will save one extra request.
|
* @param sourceFolder - the full path (eg `/Public/example/myFolder`) or URI of the source folder to be moved. Providing URI instead of path will save one extra request.
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ export class SessionManager {
|
|||||||
this.sessions = this.sessions.filter((s) => s.id !== id)
|
this.sessions = this.sessions.filter((s) => s.id !== id)
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
throw err
|
throw prefixMessage(err, 'Error while deleting session. ')
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,35 +20,52 @@ export class ComputeJobExecutor extends BaseJobExecutor {
|
|||||||
const waitForResult = true
|
const waitForResult = true
|
||||||
const expectWebout = true
|
const expectWebout = true
|
||||||
|
|
||||||
return this.sasViyaApiClient
|
const requestPromise = new Promise((resolve, reject) => {
|
||||||
?.executeComputeJob(
|
this.sasViyaApiClient
|
||||||
sasJob,
|
?.executeComputeJob(
|
||||||
config.contextName,
|
sasJob,
|
||||||
config.debug,
|
config.contextName,
|
||||||
data,
|
config.debug,
|
||||||
accessToken,
|
data,
|
||||||
waitForResult,
|
accessToken,
|
||||||
expectWebout
|
waitForResult,
|
||||||
)
|
expectWebout
|
||||||
.then((response) => {
|
)
|
||||||
this.appendRequest(response, sasJob, config.debug)
|
.then((response) => {
|
||||||
let responseJson
|
this.appendRequest(response, sasJob, config.debug)
|
||||||
|
|
||||||
return response.result
|
resolve(response.result)
|
||||||
|
})
|
||||||
|
.catch(async (e: Error) => {
|
||||||
|
if (e instanceof ComputeJobExecutionError) {
|
||||||
|
this.appendRequest(e, sasJob, config.debug)
|
||||||
|
|
||||||
return responseJson
|
reject(new ErrorResponse(e?.message, e))
|
||||||
})
|
}
|
||||||
.catch(async (e: Error) => {
|
|
||||||
if (e instanceof ComputeJobExecutionError) {
|
if (e instanceof LoginRequiredError) {
|
||||||
this.appendRequest(e, sasJob, config.debug)
|
await loginCallback()
|
||||||
}
|
this.appendWaitingRequest(() => {
|
||||||
if (e instanceof LoginRequiredError) {
|
return this.execute(
|
||||||
await loginCallback()
|
sasJob,
|
||||||
this.appendWaitingRequest(() =>
|
data,
|
||||||
this.execute(sasJob, data, config, loginRequiredCallback)
|
config,
|
||||||
)
|
loginRequiredCallback
|
||||||
}
|
).then(
|
||||||
return Promise.reject(new ErrorResponse(e?.message, e))
|
(res: any) => {
|
||||||
})
|
resolve(res)
|
||||||
|
},
|
||||||
|
(err: any) => {
|
||||||
|
reject(err)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
reject(new ErrorResponse(e?.message, e))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
return requestPromise
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,24 +17,52 @@ export class JesJobExecutor extends BaseJobExecutor {
|
|||||||
accessToken?: string
|
accessToken?: string
|
||||||
) {
|
) {
|
||||||
const loginCallback = loginRequiredCallback || (() => Promise.resolve())
|
const loginCallback = loginRequiredCallback || (() => Promise.resolve())
|
||||||
return await this.sasViyaApiClient
|
|
||||||
?.executeJob(sasJob, config.contextName, config.debug, data, accessToken)
|
|
||||||
.then((response) => {
|
|
||||||
this.appendRequest(response, sasJob, config.debug)
|
|
||||||
|
|
||||||
return response.result
|
const requestPromise = new Promise((resolve, reject) => {
|
||||||
})
|
this.sasViyaApiClient
|
||||||
.catch(async (e: Error) => {
|
?.executeJob(
|
||||||
if (e instanceof JobExecutionError) {
|
sasJob,
|
||||||
this.appendRequest(e, sasJob, config.debug)
|
config.contextName,
|
||||||
}
|
config.debug,
|
||||||
if (e instanceof LoginRequiredError) {
|
data,
|
||||||
await loginCallback()
|
accessToken
|
||||||
this.appendWaitingRequest(() =>
|
)
|
||||||
this.execute(sasJob, data, config, loginRequiredCallback)
|
.then((response) => {
|
||||||
)
|
this.appendRequest(response, sasJob, config.debug)
|
||||||
}
|
|
||||||
return Promise.reject(new ErrorResponse(e?.message, e))
|
resolve(response.result)
|
||||||
})
|
})
|
||||||
|
.catch(async (e: Error) => {
|
||||||
|
if (e instanceof JobExecutionError) {
|
||||||
|
this.appendRequest(e, sasJob, config.debug)
|
||||||
|
|
||||||
|
reject(new ErrorResponse(e?.message, e))
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e instanceof LoginRequiredError) {
|
||||||
|
await loginCallback()
|
||||||
|
|
||||||
|
this.appendWaitingRequest(() => {
|
||||||
|
return this.execute(
|
||||||
|
sasJob,
|
||||||
|
data,
|
||||||
|
config,
|
||||||
|
loginRequiredCallback
|
||||||
|
).then(
|
||||||
|
(res: any) => {
|
||||||
|
resolve(res)
|
||||||
|
},
|
||||||
|
(err: any) => {
|
||||||
|
reject(err)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
reject(new ErrorResponse(e?.message, e))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
return requestPromise
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,11 @@ import { SASViyaApiClient } from '../SASViyaApiClient'
|
|||||||
import { isRelativePath } from '../utils'
|
import { isRelativePath } from '../utils'
|
||||||
import { BaseJobExecutor } from './JobExecutor'
|
import { BaseJobExecutor } from './JobExecutor'
|
||||||
|
|
||||||
|
export interface WaitingRequstPromise {
|
||||||
|
promise: Promise<any> | null
|
||||||
|
resolve: any
|
||||||
|
reject: any
|
||||||
|
}
|
||||||
export class WebJobExecutor extends BaseJobExecutor {
|
export class WebJobExecutor extends BaseJobExecutor {
|
||||||
constructor(
|
constructor(
|
||||||
serverUrl: string,
|
serverUrl: string,
|
||||||
@@ -80,30 +85,51 @@ export class WebJobExecutor extends BaseJobExecutor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.requestClient!.post(apiUrl, formData, undefined)
|
const requestPromise = new Promise((resolve, reject) => {
|
||||||
.then(async (res) => {
|
this.requestClient!.post(apiUrl, formData, undefined)
|
||||||
if (this.serverType === ServerType.SasViya && config.debug) {
|
.then(async (res) => {
|
||||||
const jsonResponse = await this.parseSasViyaDebugResponse(
|
if (this.serverType === ServerType.SasViya && config.debug) {
|
||||||
res.result as string
|
const jsonResponse = await this.parseSasViyaDebugResponse(
|
||||||
)
|
res.result as string
|
||||||
|
)
|
||||||
|
this.appendRequest(res, sasJob, config.debug)
|
||||||
|
resolve(jsonResponse)
|
||||||
|
}
|
||||||
this.appendRequest(res, sasJob, config.debug)
|
this.appendRequest(res, sasJob, config.debug)
|
||||||
return jsonResponse
|
resolve(res.result)
|
||||||
}
|
})
|
||||||
this.appendRequest(res, sasJob, config.debug)
|
.catch(async (e: Error) => {
|
||||||
return res.result
|
if (e instanceof JobExecutionError) {
|
||||||
})
|
this.appendRequest(e, sasJob, config.debug)
|
||||||
.catch(async (e: Error) => {
|
|
||||||
if (e instanceof JobExecutionError) {
|
reject(new ErrorResponse(e?.message, e))
|
||||||
this.appendRequest(e, sasJob, config.debug)
|
}
|
||||||
}
|
|
||||||
if (e instanceof LoginRequiredError) {
|
if (e instanceof LoginRequiredError) {
|
||||||
await loginCallback()
|
await loginCallback()
|
||||||
this.appendWaitingRequest(() =>
|
|
||||||
this.execute(sasJob, data, config, loginRequiredCallback)
|
this.appendWaitingRequest(() => {
|
||||||
)
|
return this.execute(
|
||||||
}
|
sasJob,
|
||||||
return Promise.reject(new ErrorResponse(e?.message, e))
|
data,
|
||||||
})
|
config,
|
||||||
|
loginRequiredCallback
|
||||||
|
).then(
|
||||||
|
(res: any) => {
|
||||||
|
resolve(res)
|
||||||
|
},
|
||||||
|
(err: any) => {
|
||||||
|
reject(err)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
reject(new ErrorResponse(e?.message, e))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
return requestPromise
|
||||||
}
|
}
|
||||||
|
|
||||||
private parseSasViyaDebugResponse = async (response: string) => {
|
private parseSasViyaDebugResponse = async (response: string) => {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { LoginRequiredError } from '../types'
|
|||||||
import { AuthorizeError } from '../types/AuthorizeError'
|
import { AuthorizeError } from '../types/AuthorizeError'
|
||||||
import { NotFoundError } from '../types/NotFoundError'
|
import { NotFoundError } from '../types/NotFoundError'
|
||||||
import { parseWeboutResponse } from '../utils/parseWeboutResponse'
|
import { parseWeboutResponse } from '../utils/parseWeboutResponse'
|
||||||
|
import { prefixMessage } from '@sasjs/utils/error'
|
||||||
|
|
||||||
export interface HttpClient {
|
export interface HttpClient {
|
||||||
get<T>(
|
get<T>(
|
||||||
@@ -96,8 +97,17 @@ export class RequestClient implements HttpClient {
|
|||||||
})
|
})
|
||||||
.catch(async (e) => {
|
.catch(async (e) => {
|
||||||
return await this.handleError(e, () =>
|
return await this.handleError(e, () =>
|
||||||
this.get<T>(url, accessToken, contentType, overrideHeaders)
|
this.get<T>(url, accessToken, contentType, overrideHeaders).catch(
|
||||||
)
|
(err) => {
|
||||||
|
throw prefixMessage(
|
||||||
|
err,
|
||||||
|
'Error while executing handle error callback. '
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
).catch((err) => {
|
||||||
|
throw prefixMessage(err, 'Error while handling error. ')
|
||||||
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -331,35 +341,59 @@ export class RequestClient implements HttpClient {
|
|||||||
|
|
||||||
private handleError = async (e: any, callback: any) => {
|
private handleError = async (e: any, callback: any) => {
|
||||||
const response = e.response as AxiosResponse
|
const response = e.response as AxiosResponse
|
||||||
|
|
||||||
if (e instanceof AuthorizeError) {
|
if (e instanceof AuthorizeError) {
|
||||||
const res = await this.httpClient.get(e.confirmUrl, {
|
const res = await this.httpClient
|
||||||
responseType: 'text',
|
.get(e.confirmUrl, {
|
||||||
headers: { 'Content-Type': 'text/plain', Accept: '*/*' }
|
responseType: 'text',
|
||||||
})
|
headers: { 'Content-Type': 'text/plain', Accept: '*/*' }
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
throw prefixMessage(err, 'Error while getting error confirmUrl. ')
|
||||||
|
})
|
||||||
|
|
||||||
if (isAuthorizeFormRequired(res?.data as string)) {
|
if (isAuthorizeFormRequired(res?.data as string)) {
|
||||||
await this.authorize(res.data as string)
|
await this.authorize(res.data as string).catch((err) => {
|
||||||
|
throw prefixMessage(err, 'Error while authorizing request. ')
|
||||||
|
})
|
||||||
}
|
}
|
||||||
return await callback()
|
|
||||||
|
return await callback().catch((err: any) => {
|
||||||
|
throw prefixMessage(
|
||||||
|
err,
|
||||||
|
'Error while executing callback in handleError. '
|
||||||
|
)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if (e instanceof LoginRequiredError) {
|
if (e instanceof LoginRequiredError) {
|
||||||
this.clearCsrfTokens()
|
this.clearCsrfTokens()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (response?.status === 403 || response?.status === 449) {
|
if (response?.status === 403 || response?.status === 449) {
|
||||||
this.parseAndSetCsrfToken(response)
|
this.parseAndSetCsrfToken(response)
|
||||||
|
|
||||||
if (this.csrfToken.headerName && this.csrfToken.value) {
|
if (this.csrfToken.headerName && this.csrfToken.value) {
|
||||||
return await callback()
|
return await callback().catch((err: any) => {
|
||||||
|
throw prefixMessage(
|
||||||
|
err,
|
||||||
|
'Error while executing callback in handleError. '
|
||||||
|
)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
throw e
|
throw e
|
||||||
} else if (response?.status === 404) {
|
} else if (response?.status === 404) {
|
||||||
throw new NotFoundError(response.config.url!)
|
throw new NotFoundError(response.config.url!)
|
||||||
}
|
}
|
||||||
|
|
||||||
throw e
|
throw e
|
||||||
}
|
}
|
||||||
|
|
||||||
private async parseResponse<T>(response: AxiosResponse<any>) {
|
private parseResponse<T>(response: AxiosResponse<any>) {
|
||||||
const etag = response?.headers ? response.headers['etag'] : ''
|
const etag = response?.headers ? response.headers['etag'] : ''
|
||||||
let parsedResponse
|
let parsedResponse
|
||||||
|
let includeSAS9Log: boolean = false
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (typeof response.data === 'string') {
|
if (typeof response.data === 'string') {
|
||||||
@@ -373,11 +407,20 @@ export class RequestClient implements HttpClient {
|
|||||||
} catch {
|
} catch {
|
||||||
parsedResponse = response.data
|
parsedResponse = response.data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
includeSAS9Log = true
|
||||||
}
|
}
|
||||||
return {
|
|
||||||
|
let responseToReturn: { result: T; etag: any; log?: string } = {
|
||||||
result: parsedResponse as T,
|
result: parsedResponse as T,
|
||||||
etag
|
etag
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (includeSAS9Log) {
|
||||||
|
responseToReturn.log = response.data
|
||||||
|
}
|
||||||
|
|
||||||
|
return responseToReturn
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
83
src/test/FolderOperations.spec.ts
Normal file
83
src/test/FolderOperations.spec.ts
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
import { RequestClient } from '../request/RequestClient'
|
||||||
|
import { SASViyaApiClient } from '../SASViyaApiClient'
|
||||||
|
import axios from 'axios'
|
||||||
|
jest.mock('axios')
|
||||||
|
const mockedAxios = axios as jest.Mocked<typeof axios>
|
||||||
|
|
||||||
|
describe('FolderOperations', () => {
|
||||||
|
const sasViyaApiClient = new SASViyaApiClient(
|
||||||
|
'https://sample.server.com',
|
||||||
|
'/Public',
|
||||||
|
'Context',
|
||||||
|
new RequestClient('https://sample.server.com')
|
||||||
|
)
|
||||||
|
|
||||||
|
beforeEach(() => {})
|
||||||
|
|
||||||
|
it('should move and rename folder', async (done) => {
|
||||||
|
mockFetchResponse(false)
|
||||||
|
|
||||||
|
let res: any = await sasViyaApiClient.moveFolder(
|
||||||
|
'/Test/fromFolder/oldName',
|
||||||
|
'/Test/toFolder/newName',
|
||||||
|
'newName',
|
||||||
|
'token'
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(res.folder.name).toEqual('newName')
|
||||||
|
expect(res.folder.parentFolderUri.split('=')[1]).toEqual('/Test/toFolder')
|
||||||
|
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should move and keep the name of folder', async (done) => {
|
||||||
|
mockFetchResponse(true)
|
||||||
|
|
||||||
|
let res: any = await sasViyaApiClient.moveFolder(
|
||||||
|
'/Test/fromFolder/oldName',
|
||||||
|
'/Test/toFolder',
|
||||||
|
'toFolder',
|
||||||
|
'token'
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(res.folder.name).toEqual('oldName')
|
||||||
|
expect(res.folder.parentFolderUri.split('=')[1]).toEqual('/Test/toFolder')
|
||||||
|
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should only rename folder', async (done) => {
|
||||||
|
mockFetchResponse(false)
|
||||||
|
|
||||||
|
let res: any = await sasViyaApiClient.moveFolder(
|
||||||
|
'/Test/toFolder/oldName',
|
||||||
|
'/Test/toFolder/newName',
|
||||||
|
'newName',
|
||||||
|
'token'
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(res.folder.name).toEqual('newName')
|
||||||
|
expect(res.folder.parentFolderUri.split('=')[1]).toEqual('/Test/toFolder')
|
||||||
|
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
const mockFetchResponse = (targetFolderExists: boolean) => {
|
||||||
|
mockedAxios.patch.mockImplementation((url: any, request: any) => {
|
||||||
|
return Promise.resolve({ status: 200, data: { folder: request } })
|
||||||
|
})
|
||||||
|
|
||||||
|
mockedAxios.get.mockImplementation((url: any, request: any) => {
|
||||||
|
if (!targetFolderExists && url.includes('newName')) {
|
||||||
|
return Promise.resolve(undefined)
|
||||||
|
}
|
||||||
|
|
||||||
|
return Promise.resolve({
|
||||||
|
status: 200,
|
||||||
|
data: {
|
||||||
|
id: url
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -29,7 +29,10 @@ describe('SessionManager', () => {
|
|||||||
Promise.resolve({ data: sampleResponse })
|
Promise.resolve({ data: sampleResponse })
|
||||||
)
|
)
|
||||||
|
|
||||||
const expectedResponse = { etag: '', result: sampleResponse }
|
const expectedResponse = {
|
||||||
|
etag: '',
|
||||||
|
result: sampleResponse
|
||||||
|
}
|
||||||
|
|
||||||
await expect(
|
await expect(
|
||||||
sessionManager.getVariable(
|
sessionManager.getVariable(
|
||||||
|
|||||||
Reference in New Issue
Block a user