mirror of
https://github.com/sasjs/adapter.git
synced 2025-12-11 01:14:36 +00:00
Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
619833db29 | ||
|
|
a587d9f6de | ||
|
|
83fb89f779 | ||
|
|
6b98bbce7c | ||
|
|
3c2487e423 | ||
|
|
0d52af5375 | ||
|
|
d0da343efc | ||
|
|
54f401a319 | ||
|
|
5efcb11b7d | ||
|
|
929d7b993b | ||
|
|
688221c042 |
8
.github/workflows/build.yml
vendored
8
.github/workflows/build.yml
vendored
@@ -21,7 +21,11 @@ jobs:
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
- run: npm ci
|
||||
- run: npm run package:lib
|
||||
- name: Install Dependencies
|
||||
run: npm ci
|
||||
- name: Check code style
|
||||
run: npm run lint
|
||||
- name: Build Package
|
||||
run: npm run package:lib
|
||||
env:
|
||||
CI: true
|
||||
|
||||
2
.github/workflows/npmpublish.yml
vendored
2
.github/workflows/npmpublish.yml
vendored
@@ -16,6 +16,8 @@ jobs:
|
||||
uses: actions/checkout@v2
|
||||
- name: Install Dependencies
|
||||
run: npm ci
|
||||
- name: Check code style
|
||||
run: npm run lint
|
||||
- name: Build Project
|
||||
run: npm run build
|
||||
- name: Semantic Release
|
||||
|
||||
6
.prettierrc
Normal file
6
.prettierrc
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"trailingComma": "none",
|
||||
"tabWidth": 2,
|
||||
"semi": true,
|
||||
"singleQuote": false
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<script src="https://cdn.jsdelivr.net/combine/npm/chart.js@2.9.3,npm/jquery@3.5.1,npm/@sasjs/adapter@1.0.6"></script>
|
||||
<script src="https://cdn.jsdelivr.net/combine/npm/chart.js@2.9.3,npm/jquery@3.5.1,npm/@sasjs/adapter@1"></script>
|
||||
<script>
|
||||
var sasJs = new SASjs.default({
|
||||
appLoc: "/Public/app/readme"
|
||||
@@ -106,4 +106,4 @@
|
||||
<canvas id="myChart" style="display: none;"></canvas>
|
||||
</div>
|
||||
</body>
|
||||
</head>
|
||||
</head>
|
||||
|
||||
12
package-lock.json
generated
12
package-lock.json
generated
@@ -12495,9 +12495,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"prettier": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.0.5.tgz",
|
||||
"integrity": "sha512-7PtVymN48hGcO4fGjybyBSIWDsLU4H4XlvOHfq91pz9kkGlonzwTfYkaIEwiRg/dAJF9YlbsduBAgtYLi+8cFg==",
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.1.1.tgz",
|
||||
"integrity": "sha512-9bY+5ZWCfqj3ghYBLxApy2zf6m+NJo5GzmLTpr9FsApsfjriNnS2dahWReHMi7qNPhhHl9SYHJs2cHZLgexNIw==",
|
||||
"dev": true
|
||||
},
|
||||
"pretty-format": {
|
||||
@@ -14258,9 +14258,9 @@
|
||||
}
|
||||
},
|
||||
"ts-loader": {
|
||||
"version": "8.0.2",
|
||||
"resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-8.0.2.tgz",
|
||||
"integrity": "sha512-oYT7wOTUawYXQ8XIDsRhziyW0KUEV38jISYlE+9adP6tDtG+O5GkRe4QKQXrHVH4mJJ88DysvEtvGP65wMLlhg==",
|
||||
"version": "8.0.3",
|
||||
"resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-8.0.3.tgz",
|
||||
"integrity": "sha512-wsqfnVdB7xQiqhqbz2ZPLGHLPZbHVV5Qn/MNFZkCFxRU1miDyxKORucDGxKtsQJ63Rfza0udiUxWF5nHY6bpdQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"chalk": "^2.3.0",
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
"build": "rimraf build && webpack",
|
||||
"package:lib": "npm run build && cp ./package.json build && cd build && npm version \"5.0.0\" && npm pack",
|
||||
"publish:lib": "npm run build && cd build && npm publish",
|
||||
"format": "prettier --write \"src/**/*.ts\" \"src/**/*.js\"",
|
||||
"lint": "tslint -p tsconfig.json",
|
||||
"lint:fix": "npx prettier --write 'src/**/*.{ts,tsx,js,jsx,html,css,sass,less,json,yml,md,graphql}'",
|
||||
"lint": "npx prettier --check 'src/**/*.{ts,tsx,js,jsx,html,css,sass,less,json,yml,md,graphql}'",
|
||||
"test": "jest",
|
||||
"prepublishOnly": "cp -r ./build/* . && rm -rf ./build",
|
||||
"postpublish": "git clean -fd",
|
||||
@@ -41,11 +41,10 @@
|
||||
"cp": "^0.2.0",
|
||||
"jest": "^25.5.4",
|
||||
"path": "^0.12.7",
|
||||
"prettier": "^2.0.5",
|
||||
"rimraf": "^3.0.2",
|
||||
"semantic-release": "^17.1.1",
|
||||
"ts-jest": "^25.5.1",
|
||||
"ts-loader": "^8.0.2",
|
||||
"ts-loader": "^8.0.3",
|
||||
"tslint": "^6.1.3",
|
||||
"tslint-config-prettier": "^1.18.0",
|
||||
"typedoc": "^0.17.8",
|
||||
|
||||
6
sasjs-tests/.prettierrc
Normal file
6
sasjs-tests/.prettierrc
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"trailingComma": "none",
|
||||
"tabWidth": 2,
|
||||
"semi": true,
|
||||
"singleQuote": false
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
import React from 'react';
|
||||
import { render } from '@testing-library/react';
|
||||
import App from './App';
|
||||
import React from "react";
|
||||
import { render } from "@testing-library/react";
|
||||
import App from "./App";
|
||||
|
||||
test('renders learn react link', () => {
|
||||
test("renders learn react link", () => {
|
||||
const { getByText } = render(<App />);
|
||||
const linkElement = getByText(/learn react/i);
|
||||
expect(linkElement).toBeInTheDocument();
|
||||
|
||||
@@ -17,7 +17,7 @@ const App = (): ReactElement<{}> => {
|
||||
sendArrTests(adapter),
|
||||
sendObjTests(adapter),
|
||||
specialCaseTests(adapter),
|
||||
sasjsRequestTests(adapter),
|
||||
sasjsRequestTests(adapter)
|
||||
]);
|
||||
}
|
||||
}, [adapter, config]);
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
|
||||
"Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
|
||||
sans-serif;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans",
|
||||
"Droid Sans", "Helvetica Neue", sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
background-color: #1f2027;
|
||||
@@ -10,8 +9,7 @@ body {
|
||||
}
|
||||
|
||||
* {
|
||||
font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",
|
||||
monospace;
|
||||
font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace;
|
||||
}
|
||||
|
||||
input {
|
||||
|
||||
@@ -11,9 +11,9 @@
|
||||
// opt-in, read https://bit.ly/CRA-PWA
|
||||
|
||||
const isLocalhost = Boolean(
|
||||
window.location.hostname === 'localhost' ||
|
||||
window.location.hostname === "localhost" ||
|
||||
// [::1] is the IPv6 localhost address.
|
||||
window.location.hostname === '[::1]' ||
|
||||
window.location.hostname === "[::1]" ||
|
||||
// 127.0.0.0/8 are considered localhost for IPv4.
|
||||
window.location.hostname.match(
|
||||
/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
|
||||
@@ -21,7 +21,7 @@ const isLocalhost = Boolean(
|
||||
);
|
||||
|
||||
export function register(config) {
|
||||
if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
|
||||
if (process.env.NODE_ENV === "production" && "serviceWorker" in navigator) {
|
||||
// The URL constructor is available in all browsers that support SW.
|
||||
const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);
|
||||
if (publicUrl.origin !== window.location.origin) {
|
||||
@@ -31,7 +31,7 @@ export function register(config) {
|
||||
return;
|
||||
}
|
||||
|
||||
window.addEventListener('load', () => {
|
||||
window.addEventListener("load", () => {
|
||||
const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
|
||||
|
||||
if (isLocalhost) {
|
||||
@@ -42,8 +42,8 @@ export function register(config) {
|
||||
// service worker/PWA documentation.
|
||||
navigator.serviceWorker.ready.then(() => {
|
||||
console.log(
|
||||
'This web app is being served cache-first by a service ' +
|
||||
'worker. To learn more, visit https://bit.ly/CRA-PWA'
|
||||
"This web app is being served cache-first by a service " +
|
||||
"worker. To learn more, visit https://bit.ly/CRA-PWA"
|
||||
);
|
||||
});
|
||||
} else {
|
||||
@@ -57,21 +57,21 @@ export function register(config) {
|
||||
function registerValidSW(swUrl, config) {
|
||||
navigator.serviceWorker
|
||||
.register(swUrl)
|
||||
.then(registration => {
|
||||
.then((registration) => {
|
||||
registration.onupdatefound = () => {
|
||||
const installingWorker = registration.installing;
|
||||
if (installingWorker == null) {
|
||||
return;
|
||||
}
|
||||
installingWorker.onstatechange = () => {
|
||||
if (installingWorker.state === 'installed') {
|
||||
if (installingWorker.state === "installed") {
|
||||
if (navigator.serviceWorker.controller) {
|
||||
// At this point, the updated precached content has been fetched,
|
||||
// but the previous service worker will still serve the older
|
||||
// content until all client tabs are closed.
|
||||
console.log(
|
||||
'New content is available and will be used when all ' +
|
||||
'tabs for this page are closed. See https://bit.ly/CRA-PWA.'
|
||||
"New content is available and will be used when all " +
|
||||
"tabs for this page are closed. See https://bit.ly/CRA-PWA."
|
||||
);
|
||||
|
||||
// Execute callback
|
||||
@@ -82,7 +82,7 @@ function registerValidSW(swUrl, config) {
|
||||
// At this point, everything has been precached.
|
||||
// It's the perfect time to display a
|
||||
// "Content is cached for offline use." message.
|
||||
console.log('Content is cached for offline use.');
|
||||
console.log("Content is cached for offline use.");
|
||||
|
||||
// Execute callback
|
||||
if (config && config.onSuccess) {
|
||||
@@ -93,25 +93,25 @@ function registerValidSW(swUrl, config) {
|
||||
};
|
||||
};
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error during service worker registration:', error);
|
||||
.catch((error) => {
|
||||
console.error("Error during service worker registration:", error);
|
||||
});
|
||||
}
|
||||
|
||||
function checkValidServiceWorker(swUrl, config) {
|
||||
// Check if the service worker can be found. If it can't reload the page.
|
||||
fetch(swUrl, {
|
||||
headers: { 'Service-Worker': 'script' },
|
||||
headers: { "Service-Worker": "script" }
|
||||
})
|
||||
.then(response => {
|
||||
.then((response) => {
|
||||
// Ensure service worker exists, and that we really are getting a JS file.
|
||||
const contentType = response.headers.get('content-type');
|
||||
const contentType = response.headers.get("content-type");
|
||||
if (
|
||||
response.status === 404 ||
|
||||
(contentType != null && contentType.indexOf('javascript') === -1)
|
||||
(contentType != null && contentType.indexOf("javascript") === -1)
|
||||
) {
|
||||
// No service worker found. Probably a different app. Reload the page.
|
||||
navigator.serviceWorker.ready.then(registration => {
|
||||
navigator.serviceWorker.ready.then((registration) => {
|
||||
registration.unregister().then(() => {
|
||||
window.location.reload();
|
||||
});
|
||||
@@ -123,18 +123,18 @@ function checkValidServiceWorker(swUrl, config) {
|
||||
})
|
||||
.catch(() => {
|
||||
console.log(
|
||||
'No internet connection found. App is running in offline mode.'
|
||||
"No internet connection found. App is running in offline mode."
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
export function unregister() {
|
||||
if ('serviceWorker' in navigator) {
|
||||
if ("serviceWorker" in navigator) {
|
||||
navigator.serviceWorker.ready
|
||||
.then(registration => {
|
||||
.then((registration) => {
|
||||
registration.unregister();
|
||||
})
|
||||
.catch(error => {
|
||||
.catch((error) => {
|
||||
console.error(error.message);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
// allows you to do things like:
|
||||
// expect(element).toHaveTextContent(/react/i)
|
||||
// learn more: https://github.com/testing-library/jest-dom
|
||||
import '@testing-library/jest-dom/extend-expect';
|
||||
import "@testing-library/jest-dom/extend-expect";
|
||||
|
||||
@@ -9,7 +9,7 @@ const defaultConfig: SASjsConfig = {
|
||||
serverType: ServerType.SASViya,
|
||||
debug: true,
|
||||
contextName: "SAS Job Execution compute context",
|
||||
useComputeApi: false,
|
||||
useComputeApi: false
|
||||
};
|
||||
|
||||
const customConfig = {
|
||||
@@ -18,7 +18,7 @@ const customConfig = {
|
||||
pathSASViya: "viya",
|
||||
appLoc: "/Public/seedapp",
|
||||
serverType: ServerType.SAS9,
|
||||
debug: false,
|
||||
debug: false
|
||||
};
|
||||
|
||||
export const basicTests = (
|
||||
@@ -35,7 +35,7 @@ export const basicTests = (
|
||||
return adapter.logIn(userName, password);
|
||||
},
|
||||
assertion: (response: any) =>
|
||||
response && response.isLoggedIn && response.userName === userName,
|
||||
response && response.isLoggedIn && response.userName === userName
|
||||
},
|
||||
{
|
||||
title: "Default config",
|
||||
@@ -54,7 +54,7 @@ export const basicTests = (
|
||||
sasjsConfig.serverType === defaultConfig.serverType &&
|
||||
sasjsConfig.debug === defaultConfig.debug
|
||||
);
|
||||
},
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "Custom config",
|
||||
@@ -72,7 +72,7 @@ export const basicTests = (
|
||||
sasjsConfig.serverType === customConfig.serverType &&
|
||||
sasjsConfig.debug === customConfig.debug
|
||||
);
|
||||
},
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "Config overrides",
|
||||
@@ -92,7 +92,7 @@ export const basicTests = (
|
||||
sasjsConfig.serverType === defaultConfig.serverType &&
|
||||
sasjsConfig.debug === false
|
||||
);
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
@@ -4,7 +4,7 @@ import { TestSuite } from "@sasjs/test-framework";
|
||||
const stringData: any = { table1: [{ col1: "first col value" }] };
|
||||
const numericData: any = { table1: [{ col1: 3.14159265 }] };
|
||||
const multiColumnData: any = {
|
||||
table1: [{ col1: 42, col2: 1.618, col3: "x", col4: "x" }],
|
||||
table1: [{ col1: 42, col2: 1.618, col3: "x", col4: "x" }]
|
||||
};
|
||||
const multipleRowsWithNulls: any = {
|
||||
table1: [
|
||||
@@ -12,8 +12,8 @@ const multipleRowsWithNulls: any = {
|
||||
{ col1: 42, col2: null, col3: "x", col4: "" },
|
||||
{ col1: 42, col2: null, col3: "x", col4: "" },
|
||||
{ col1: 42, col2: 1.62, col3: "x", col4: "x" },
|
||||
{ col1: 42, col2: 1.62, col3: "x", col4: "x" },
|
||||
],
|
||||
{ col1: 42, col2: 1.62, col3: "x", col4: "x" }
|
||||
]
|
||||
};
|
||||
const multipleColumnsWithNulls: any = {
|
||||
table1: [
|
||||
@@ -21,8 +21,8 @@ const multipleColumnsWithNulls: any = {
|
||||
{ col1: 42, col2: null, col3: "x", col4: null },
|
||||
{ col1: 42, col2: null, col3: "x", col4: null },
|
||||
{ col1: 42, col2: null, col3: "x", col4: "" },
|
||||
{ col1: 42, col2: null, col3: "x", col4: "" },
|
||||
],
|
||||
{ col1: 42, col2: null, col3: "x", col4: "" }
|
||||
]
|
||||
};
|
||||
|
||||
const getLongStringData = (length = 32764) => {
|
||||
@@ -55,7 +55,7 @@ export const sendArrTests = (adapter: SASjs): TestSuite => ({
|
||||
},
|
||||
assertion: (res: any) => {
|
||||
return res.table1[0][0] === stringData.table1[0].col1;
|
||||
},
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "Long string value",
|
||||
@@ -67,7 +67,7 @@ export const sendArrTests = (adapter: SASjs): TestSuite => ({
|
||||
assertion: (res: any) => {
|
||||
const longStringData = getLongStringData();
|
||||
return res.table1[0][0] === longStringData.table1[0].col1;
|
||||
},
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "Overly long string value",
|
||||
@@ -79,7 +79,7 @@ export const sendArrTests = (adapter: SASjs): TestSuite => ({
|
||||
},
|
||||
assertion: (error: any) => {
|
||||
return !!error && !!error.MESSAGE;
|
||||
},
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "Single numeric value",
|
||||
@@ -89,7 +89,7 @@ export const sendArrTests = (adapter: SASjs): TestSuite => ({
|
||||
},
|
||||
assertion: (res: any) => {
|
||||
return res.table1[0][0] === numericData.table1[0].col1;
|
||||
},
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "Multiple columns",
|
||||
@@ -104,7 +104,7 @@ export const sendArrTests = (adapter: SASjs): TestSuite => ({
|
||||
res.table1[0][2] === multiColumnData.table1[0].col3 &&
|
||||
res.table1[0][3] === multiColumnData.table1[0].col4
|
||||
);
|
||||
},
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "Multiple rows with nulls",
|
||||
@@ -129,7 +129,7 @@ export const sendArrTests = (adapter: SASjs): TestSuite => ({
|
||||
res.table1[index][3] === multipleRowsWithNulls.table1[index].col4;
|
||||
});
|
||||
return result;
|
||||
},
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "Multiple columns with nulls",
|
||||
@@ -158,9 +158,9 @@ export const sendArrTests = (adapter: SASjs): TestSuite => ({
|
||||
(multipleColumnsWithNulls.table1[index].col4 || "");
|
||||
});
|
||||
return result;
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
export const sendObjTests = (adapter: SASjs): TestSuite => ({
|
||||
@@ -171,11 +171,11 @@ export const sendObjTests = (adapter: SASjs): TestSuite => ({
|
||||
description: "Should throw an error",
|
||||
test: async () => {
|
||||
const invalidData: any = {
|
||||
"1 invalid table": [{ col1: 42 }],
|
||||
"1 invalid table": [{ col1: 42 }]
|
||||
};
|
||||
return adapter.request("common/sendObj", invalidData).catch((e) => e);
|
||||
},
|
||||
assertion: (error: any) => !!error && !!error.MESSAGE,
|
||||
assertion: (error: any) => !!error && !!error.MESSAGE
|
||||
},
|
||||
{
|
||||
title: "Single string value",
|
||||
@@ -185,7 +185,7 @@ export const sendObjTests = (adapter: SASjs): TestSuite => ({
|
||||
},
|
||||
assertion: (res: any) => {
|
||||
return res.table1[0].COL1 === stringData.table1[0].col1;
|
||||
},
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "Long string value",
|
||||
@@ -197,7 +197,7 @@ export const sendObjTests = (adapter: SASjs): TestSuite => ({
|
||||
assertion: (res: any) => {
|
||||
const longStringData = getLongStringData();
|
||||
return res.table1[0].COL1 === longStringData.table1[0].col1;
|
||||
},
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "Overly long string value",
|
||||
@@ -210,7 +210,7 @@ export const sendObjTests = (adapter: SASjs): TestSuite => ({
|
||||
},
|
||||
assertion: (error: any) => {
|
||||
return !!error && !!error.MESSAGE;
|
||||
},
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "Single numeric value",
|
||||
@@ -220,7 +220,7 @@ export const sendObjTests = (adapter: SASjs): TestSuite => ({
|
||||
},
|
||||
assertion: (res: any) => {
|
||||
return res.table1[0].COL1 === numericData.table1[0].col1;
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
@@ -232,7 +232,7 @@ export const sendObjTests = (adapter: SASjs): TestSuite => ({
|
||||
assertion: (res: any) => {
|
||||
const data = getLargeObjectData();
|
||||
return res.table1[9000].BIG === data.table1[9000].big;
|
||||
},
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "Multiple columns",
|
||||
@@ -247,7 +247,7 @@ export const sendObjTests = (adapter: SASjs): TestSuite => ({
|
||||
res.table1[0].COL3 === multiColumnData.table1[0].col3 &&
|
||||
res.table1[0].COL4 === multiColumnData.table1[0].col4
|
||||
);
|
||||
},
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "Multiple rows with nulls",
|
||||
@@ -272,7 +272,7 @@ export const sendObjTests = (adapter: SASjs): TestSuite => ({
|
||||
res.table1[index].COL4 === multipleRowsWithNulls.table1[index].col4;
|
||||
});
|
||||
return result;
|
||||
},
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "Multiple columns with nulls",
|
||||
@@ -301,7 +301,7 @@ export const sendObjTests = (adapter: SASjs): TestSuite => ({
|
||||
(multipleColumnsWithNulls.table1[index].col4 || "");
|
||||
});
|
||||
return result;
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
@@ -19,28 +19,32 @@ export const sasjsRequestTests = (adapter: SASjs): TestSuite => ({
|
||||
} else {
|
||||
return requests[0].SASWORK === null;
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "Make error and capture log",
|
||||
description: "Should make an error and capture log",
|
||||
test: async () => {
|
||||
return new Promise( async (resolve, reject) => {
|
||||
adapter.request("common/makeErr", data)
|
||||
.then((res) => {
|
||||
//no action here, this request must throw error
|
||||
})
|
||||
.catch((err) => {
|
||||
let sasRequests = adapter.getSasRequests();
|
||||
let makeErrRequest = sasRequests.find(req => req.serviceLink.includes('makeErr')) || null;
|
||||
return new Promise(async (resolve, reject) => {
|
||||
adapter
|
||||
.request("common/makeErr", data)
|
||||
.then((res) => {
|
||||
//no action here, this request must throw error
|
||||
})
|
||||
.catch((err) => {
|
||||
let sasRequests = adapter.getSasRequests();
|
||||
let makeErrRequest =
|
||||
sasRequests.find((req) =>
|
||||
req.serviceLink.includes("makeErr")
|
||||
) || null;
|
||||
|
||||
resolve(!!makeErrRequest);
|
||||
})
|
||||
})
|
||||
resolve(!!makeErrRequest);
|
||||
});
|
||||
});
|
||||
},
|
||||
assertion: (response) => {
|
||||
return response;
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
@@ -13,9 +13,9 @@ const specialCharData: any = {
|
||||
doubleQuote: '"',
|
||||
crlf: "\r\n",
|
||||
euro: "€euro",
|
||||
banghash: "!#banghash",
|
||||
},
|
||||
],
|
||||
banghash: "!#banghash"
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
const moreSpecialCharData: any = {
|
||||
@@ -31,9 +31,9 @@ const moreSpecialCharData: any = {
|
||||
sigma: "Σsigma",
|
||||
at: "@at",
|
||||
serbian: "Српски",
|
||||
dollar: "$",
|
||||
},
|
||||
],
|
||||
dollar: "$"
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
const getWideData = () => {
|
||||
@@ -43,7 +43,7 @@ const getWideData = () => {
|
||||
}
|
||||
|
||||
const data: any = {
|
||||
table1: [cols],
|
||||
table1: [cols]
|
||||
};
|
||||
|
||||
return data;
|
||||
@@ -67,7 +67,7 @@ const getLargeDataset = () => {
|
||||
}
|
||||
|
||||
const data: any = {
|
||||
table1: rows,
|
||||
table1: rows
|
||||
};
|
||||
|
||||
return data;
|
||||
@@ -75,7 +75,7 @@ const getLargeDataset = () => {
|
||||
|
||||
const errorAndCsrfData: any = {
|
||||
error: [{ col1: "q", col2: "w", col3: "e", col4: "r" }],
|
||||
_csrf: [{ col1: "q", col2: "w", col3: "e", col4: "r" }],
|
||||
_csrf: [{ col1: "q", col2: "w", col3: "e", col4: "r" }]
|
||||
};
|
||||
|
||||
export const specialCaseTests = (adapter: SASjs): TestSuite => ({
|
||||
@@ -100,7 +100,7 @@ export const specialCaseTests = (adapter: SASjs): TestSuite => ({
|
||||
res.table1[0][8] === specialCharData.table1[0].euro &&
|
||||
res.table1[0][9] === specialCharData.table1[0].banghash
|
||||
);
|
||||
},
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "Other special characters",
|
||||
@@ -122,7 +122,7 @@ export const specialCaseTests = (adapter: SASjs): TestSuite => ({
|
||||
res.table1[0][9] === moreSpecialCharData.table1[0].serbian &&
|
||||
res.table1[0][10] === moreSpecialCharData.table1[0].dollar
|
||||
);
|
||||
},
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "Wide table with sendArr",
|
||||
@@ -138,7 +138,7 @@ export const specialCaseTests = (adapter: SASjs): TestSuite => ({
|
||||
result && res.table1[0][i] === data.table1[0]["col" + (i + 1)];
|
||||
}
|
||||
return result;
|
||||
},
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "Wide table with sendObj",
|
||||
@@ -155,7 +155,7 @@ export const specialCaseTests = (adapter: SASjs): TestSuite => ({
|
||||
res.table1[0]["COL" + (i + 1)] === data.table1[0]["col" + (i + 1)];
|
||||
}
|
||||
return result;
|
||||
},
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "Multiple tables",
|
||||
@@ -175,7 +175,7 @@ export const specialCaseTests = (adapter: SASjs): TestSuite => ({
|
||||
res.table50[0][2] === data.table50[0].col3 &&
|
||||
res.table50[0][3] === data.table50[0].col4
|
||||
);
|
||||
},
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "Large dataset with sendObj",
|
||||
@@ -190,7 +190,7 @@ export const specialCaseTests = (adapter: SASjs): TestSuite => ({
|
||||
result = result && res.table1[i][0] === data.table1[i][0];
|
||||
}
|
||||
return result;
|
||||
},
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "Large dataset with sendArr",
|
||||
@@ -206,7 +206,7 @@ export const specialCaseTests = (adapter: SASjs): TestSuite => ({
|
||||
result && res.table1[i][0] === Object.values(data.table1[i])[0];
|
||||
}
|
||||
return result;
|
||||
},
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "Error and _csrf tables with sendArr",
|
||||
@@ -225,7 +225,7 @@ export const specialCaseTests = (adapter: SASjs): TestSuite => ({
|
||||
res._csrf[0][2] === errorAndCsrfData._csrf[0].col3 &&
|
||||
res._csrf[0][3] === errorAndCsrfData._csrf[0].col4
|
||||
);
|
||||
},
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "Error and _csrf tables with sendObj",
|
||||
@@ -244,7 +244,7 @@ export const specialCaseTests = (adapter: SASjs): TestSuite => ({
|
||||
res._csrf[0].COL3 === errorAndCsrfData._csrf[0].col3 &&
|
||||
res._csrf[0].COL4 === errorAndCsrfData._csrf[0].col4
|
||||
);
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
@@ -10,7 +10,7 @@ export class FileUploader {
|
||||
private serverUrl: string,
|
||||
private jobsPath: string,
|
||||
private setCsrfTokenWeb: any,
|
||||
private csrfToken: CsrfToken | null = null,
|
||||
private csrfToken: CsrfToken | null = null
|
||||
) {}
|
||||
private retryCount = 0;
|
||||
|
||||
@@ -33,7 +33,7 @@ export class FileUploader {
|
||||
}${paramsString}`;
|
||||
|
||||
const headers = {
|
||||
"cache-control": "no-cache",
|
||||
"cache-control": "no-cache"
|
||||
};
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
@@ -49,7 +49,7 @@ export class FileUploader {
|
||||
method: "POST",
|
||||
body: formData,
|
||||
referrerPolicy: "same-origin",
|
||||
headers,
|
||||
headers
|
||||
})
|
||||
.then(async (response) => {
|
||||
if (!response.ok) {
|
||||
@@ -60,7 +60,7 @@ export class FileUploader {
|
||||
const token = response.headers.get(tokenHeader);
|
||||
this.csrfToken = {
|
||||
headerName: tokenHeader,
|
||||
value: token || "",
|
||||
value: token || ""
|
||||
};
|
||||
|
||||
this.setCsrfTokenWeb(this.csrfToken);
|
||||
|
||||
@@ -10,7 +10,7 @@ export class SAS9ApiClient {
|
||||
*/
|
||||
public getConfig() {
|
||||
return {
|
||||
serverUrl: this.serverUrl,
|
||||
serverUrl: this.serverUrl
|
||||
};
|
||||
}
|
||||
|
||||
@@ -37,9 +37,9 @@ export class SAS9ApiClient {
|
||||
const executeScriptRequest = {
|
||||
method: "PUT",
|
||||
headers: {
|
||||
Accept: "application/json",
|
||||
Accept: "application/json"
|
||||
},
|
||||
body: `command=${requestPayload}`,
|
||||
body: `command=${requestPayload}`
|
||||
};
|
||||
const executeScriptResponse = await fetch(
|
||||
`${this.serverUrl}/sas/servers/${serverName}/cmd?repositoryName=${repositoryName}`,
|
||||
|
||||
@@ -2,7 +2,7 @@ import {
|
||||
isAuthorizeFormRequired,
|
||||
parseAndSubmitAuthorizeForm,
|
||||
convertToCSV,
|
||||
makeRequest,
|
||||
makeRequest
|
||||
} from "./utils";
|
||||
import * as NodeFormData from "form-data";
|
||||
import * as path from "path";
|
||||
@@ -53,7 +53,7 @@ export class SASViyaApiClient {
|
||||
public getConfig() {
|
||||
return {
|
||||
serverUrl: this.serverUrl,
|
||||
rootFolderName: this.rootFolderName,
|
||||
rootFolderName: this.rootFolderName
|
||||
};
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ export class SASViyaApiClient {
|
||||
*/
|
||||
public async getAllContexts(accessToken?: string) {
|
||||
const headers: any = {
|
||||
"Content-Type": "application/json",
|
||||
"Content-Type": "application/json"
|
||||
};
|
||||
if (accessToken) {
|
||||
headers.Authorization = `Bearer ${accessToken}`;
|
||||
@@ -88,7 +88,7 @@ export class SASViyaApiClient {
|
||||
id: context.id,
|
||||
name: context.name,
|
||||
version: context.version,
|
||||
attributes: {},
|
||||
attributes: {}
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -98,7 +98,7 @@ export class SASViyaApiClient {
|
||||
*/
|
||||
public async getExecutableContexts(accessToken?: string) {
|
||||
const headers: any = {
|
||||
"Content-Type": "application/json",
|
||||
"Content-Type": "application/json"
|
||||
};
|
||||
if (accessToken) {
|
||||
headers.Authorization = `Bearer ${accessToken}`;
|
||||
@@ -139,8 +139,8 @@ export class SASViyaApiClient {
|
||||
name: contextsList[index].name,
|
||||
version: contextsList[index].version,
|
||||
attributes: {
|
||||
sysUserId,
|
||||
},
|
||||
sysUserId
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -155,7 +155,7 @@ export class SASViyaApiClient {
|
||||
*/
|
||||
public async createSession(contextName: string, accessToken?: string) {
|
||||
const headers: any = {
|
||||
"Content-Type": "application/json",
|
||||
"Content-Type": "application/json"
|
||||
};
|
||||
|
||||
if (accessToken) {
|
||||
@@ -178,8 +178,8 @@ export class SASViyaApiClient {
|
||||
method: "POST",
|
||||
headers: {
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
};
|
||||
const { result: createdSession } = await this.request<Session>(
|
||||
`${this.serverUrl}/compute/contexts/${executionContext.id}/sessions`,
|
||||
@@ -210,7 +210,7 @@ export class SASViyaApiClient {
|
||||
silent = !debug;
|
||||
try {
|
||||
const headers: any = {
|
||||
"Content-Type": "application/json",
|
||||
"Content-Type": "application/json"
|
||||
};
|
||||
|
||||
if (accessToken) {
|
||||
@@ -227,7 +227,7 @@ export class SASViyaApiClient {
|
||||
_OMITJSONLOG: true,
|
||||
_OMITSESSIONRESULTS: true,
|
||||
_OMITTEXTLISTING: true,
|
||||
_OMITTEXTLOG: true,
|
||||
_OMITTEXTLOG: true
|
||||
};
|
||||
|
||||
if (debug) {
|
||||
@@ -242,7 +242,7 @@ export class SASViyaApiClient {
|
||||
|
||||
let jobVariables: any = {
|
||||
SYS_JES_JOB_URI: "",
|
||||
_program: this.rootFolderName + "/" + jobName,
|
||||
_program: this.rootFolderName + "/" + jobName
|
||||
};
|
||||
|
||||
let files: any[] = [];
|
||||
@@ -271,8 +271,8 @@ export class SASViyaApiClient {
|
||||
description: "Powered by SASjs",
|
||||
code: linesOfCode,
|
||||
variables: jobVariables,
|
||||
arguments: jobArguments,
|
||||
}),
|
||||
arguments: jobArguments
|
||||
})
|
||||
};
|
||||
|
||||
const { result: postedJob, etag } = await this.request<Job>(
|
||||
@@ -309,7 +309,7 @@ export class SASViyaApiClient {
|
||||
log = await this.request<any>(
|
||||
`${this.serverUrl}${logLink.href}/content?limit=10000`,
|
||||
{
|
||||
headers,
|
||||
headers
|
||||
}
|
||||
).then((res: any) =>
|
||||
res.result.items.map((i: any) => i.line).join("\n")
|
||||
@@ -327,7 +327,7 @@ export class SASViyaApiClient {
|
||||
{ headers },
|
||||
"text"
|
||||
).catch((e) => ({
|
||||
result: JSON.stringify(e),
|
||||
result: JSON.stringify(e)
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -401,8 +401,8 @@ export class SASViyaApiClient {
|
||||
method: "POST",
|
||||
body: JSON.stringify({
|
||||
name: folderName,
|
||||
type: "folder",
|
||||
}),
|
||||
type: "folder"
|
||||
})
|
||||
};
|
||||
|
||||
createFolderRequest.headers = { "Content-Type": "application/json" };
|
||||
@@ -449,7 +449,7 @@ export class SASViyaApiClient {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/vnd.sas.job.definition+json",
|
||||
Accept: "application/vnd.sas.job.definition+json",
|
||||
Accept: "application/vnd.sas.job.definition+json"
|
||||
},
|
||||
body: JSON.stringify({
|
||||
name: jobName,
|
||||
@@ -457,18 +457,18 @@ export class SASViyaApiClient {
|
||||
{
|
||||
name: "_addjesbeginendmacros",
|
||||
type: "CHARACTER",
|
||||
defaultValue: "false",
|
||||
},
|
||||
defaultValue: "false"
|
||||
}
|
||||
],
|
||||
type: "Compute",
|
||||
code,
|
||||
}),
|
||||
code
|
||||
})
|
||||
};
|
||||
|
||||
if (accessToken) {
|
||||
createJobDefinitionRequest!.headers = {
|
||||
...createJobDefinitionRequest.headers,
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
Authorization: `Bearer ${accessToken}`
|
||||
};
|
||||
}
|
||||
|
||||
@@ -487,7 +487,7 @@ export class SASViyaApiClient {
|
||||
|
||||
const authCode = await fetch(authUrl, {
|
||||
referrerPolicy: "same-origin",
|
||||
credentials: "include",
|
||||
credentials: "include"
|
||||
})
|
||||
.then((response) => response.text())
|
||||
.then(async (response) => {
|
||||
@@ -543,7 +543,7 @@ export class SASViyaApiClient {
|
||||
token = Buffer.from(clientId + ":" + clientSecret).toString("base64");
|
||||
}
|
||||
const headers = {
|
||||
Authorization: "Basic " + token,
|
||||
Authorization: "Basic " + token
|
||||
};
|
||||
|
||||
let formData;
|
||||
@@ -562,7 +562,7 @@ export class SASViyaApiClient {
|
||||
credentials: "include",
|
||||
headers,
|
||||
body: formData as any,
|
||||
referrerPolicy: "same-origin",
|
||||
referrerPolicy: "same-origin"
|
||||
}).then((res) => res.json());
|
||||
|
||||
return authResponse;
|
||||
@@ -587,7 +587,7 @@ export class SASViyaApiClient {
|
||||
token = Buffer.from(clientId + ":" + clientSecret).toString("base64");
|
||||
}
|
||||
const headers = {
|
||||
Authorization: "Basic " + token,
|
||||
Authorization: "Basic " + token
|
||||
};
|
||||
|
||||
let formData;
|
||||
@@ -606,7 +606,7 @@ export class SASViyaApiClient {
|
||||
credentials: "include",
|
||||
headers,
|
||||
body: formData as any,
|
||||
referrerPolicy: "same-origin",
|
||||
referrerPolicy: "same-origin"
|
||||
}).then((res) => res.json());
|
||||
|
||||
return authResponse;
|
||||
@@ -626,7 +626,7 @@ export class SASViyaApiClient {
|
||||
const deleteResponse = await this.request(url, {
|
||||
method: "DELETE",
|
||||
credentials: "include",
|
||||
headers,
|
||||
headers
|
||||
});
|
||||
|
||||
return deleteResponse;
|
||||
@@ -675,20 +675,30 @@ export class SASViyaApiClient {
|
||||
const jobName = sasJob.split("/")[1];
|
||||
const jobFolder = this.rootFolderMap.get(folderName);
|
||||
const jobToExecute = jobFolder?.find((item) => item.name === jobName);
|
||||
const jobDefinitionLink = jobToExecute?.links.find(
|
||||
(l) => l.rel === "getResource"
|
||||
);
|
||||
if (!jobDefinitionLink) {
|
||||
console.error("Job definition URI was not found.");
|
||||
throw new Error("Job definition URI was not found.");
|
||||
if (!jobToExecute) {
|
||||
throw new Error("Job was not found.");
|
||||
}
|
||||
const { result: jobDefinition } = await this.request<JobDefinition>(
|
||||
`${this.serverUrl}${jobDefinitionLink.href}`,
|
||||
headers
|
||||
);
|
||||
const linesToExecute = jobDefinition.code
|
||||
.replace(/\r\n/g, "\n")
|
||||
.split("\n");
|
||||
|
||||
let code = jobToExecute?.code;
|
||||
if (!code) {
|
||||
const jobDefinitionLink = jobToExecute?.links.find(
|
||||
(l) => l.rel === "getResource"
|
||||
);
|
||||
if (!jobDefinitionLink) {
|
||||
console.error("Job definition URI was not found.");
|
||||
throw new Error("Job definition URI was not found.");
|
||||
}
|
||||
const { result: jobDefinition } = await this.request<JobDefinition>(
|
||||
`${this.serverUrl}${jobDefinitionLink.href}`,
|
||||
headers
|
||||
);
|
||||
|
||||
code = jobDefinition.code;
|
||||
|
||||
// Add code to existing job definition
|
||||
jobToExecute.code = code;
|
||||
}
|
||||
const linesToExecute = code.replace(/\r\n/g, "\n").split("\n");
|
||||
return await this.executeScript(
|
||||
sasJob,
|
||||
linesToExecute,
|
||||
@@ -745,7 +755,7 @@ export class SASViyaApiClient {
|
||||
(l) => l.rel === "getResource"
|
||||
)?.href;
|
||||
const requestInfo: any = {
|
||||
method: "GET",
|
||||
method: "GET"
|
||||
};
|
||||
const headers: any = { "Content-Type": "application/json" };
|
||||
if (!!accessToken) {
|
||||
@@ -765,7 +775,7 @@ export class SASViyaApiClient {
|
||||
_OMITJSONLOG: true,
|
||||
_OMITSESSIONRESULTS: true,
|
||||
_OMITTEXTLISTING: true,
|
||||
_OMITTEXTLOG: true,
|
||||
_OMITTEXTLOG: true
|
||||
};
|
||||
|
||||
if (debug) {
|
||||
@@ -788,8 +798,8 @@ export class SASViyaApiClient {
|
||||
name: `exec-${jobName}`,
|
||||
description: "Powered by SASjs",
|
||||
jobDefinition,
|
||||
arguments: jobArguments,
|
||||
}),
|
||||
arguments: jobArguments
|
||||
})
|
||||
};
|
||||
const { result: postedJob, etag } = await this.request<Job>(
|
||||
`${this.serverUrl}/jobExecution/jobs?_action=wait`,
|
||||
@@ -823,7 +833,7 @@ export class SASViyaApiClient {
|
||||
log = await this.request<any>(
|
||||
`${this.serverUrl}${logLink.href}/content`,
|
||||
{
|
||||
headers,
|
||||
headers
|
||||
}
|
||||
).then((res: any) =>
|
||||
res.result.items.map((i: any) => i.line).join("\n")
|
||||
@@ -841,7 +851,7 @@ export class SASViyaApiClient {
|
||||
const allItems = new Map<string, Job[]>();
|
||||
const url = "/folders/folders/@item?path=" + this.rootFolderName;
|
||||
const requestInfo: any = {
|
||||
method: "GET",
|
||||
method: "GET"
|
||||
};
|
||||
if (accessToken) {
|
||||
requestInfo.headers = { Authorization: `Bearer ${accessToken}` };
|
||||
@@ -893,7 +903,7 @@ export class SASViyaApiClient {
|
||||
private async populateRootFolder(accessToken?: string) {
|
||||
const url = "/folders/folders/@item?path=" + this.rootFolderName;
|
||||
const requestInfo: RequestInit = {
|
||||
method: "GET",
|
||||
method: "GET"
|
||||
};
|
||||
if (accessToken) {
|
||||
requestInfo.headers = { Authorization: `Bearer ${accessToken}` };
|
||||
@@ -922,12 +932,29 @@ export class SASViyaApiClient {
|
||||
let pollCount = 0;
|
||||
const headers: any = {
|
||||
"Content-Type": "application/json",
|
||||
"If-None-Match": etag,
|
||||
"If-None-Match": etag
|
||||
};
|
||||
if (accessToken) {
|
||||
headers.Authorization = `Bearer ${accessToken}`;
|
||||
}
|
||||
const stateLink = postedJob.links.find((l: any) => l.rel === "state");
|
||||
if (!stateLink) {
|
||||
Promise.reject("Job state link was not found.");
|
||||
}
|
||||
|
||||
const { result: state } = await this.request<string>(
|
||||
`${this.serverUrl}${stateLink.href}?_action=wait&wait=30`,
|
||||
{
|
||||
headers
|
||||
},
|
||||
"text"
|
||||
);
|
||||
|
||||
const currentState = state.trim();
|
||||
if (currentState === "completed") {
|
||||
return Promise.resolve(currentState);
|
||||
}
|
||||
|
||||
return new Promise(async (resolve, _) => {
|
||||
const interval = setInterval(async () => {
|
||||
if (
|
||||
@@ -942,7 +969,7 @@ export class SASViyaApiClient {
|
||||
const { result: jobState } = await this.request<string>(
|
||||
`${this.serverUrl}${stateLink.href}?_action=wait&wait=30`,
|
||||
{
|
||||
headers,
|
||||
headers
|
||||
},
|
||||
"text"
|
||||
);
|
||||
@@ -974,7 +1001,7 @@ export class SASViyaApiClient {
|
||||
let pollCount = 0;
|
||||
const headers: any = {
|
||||
"Content-Type": "application/json",
|
||||
"If-None-Match": etag,
|
||||
"If-None-Match": etag
|
||||
};
|
||||
if (accessToken) {
|
||||
headers.Authorization = `Bearer ${accessToken}`;
|
||||
@@ -989,7 +1016,7 @@ export class SASViyaApiClient {
|
||||
const { result: state } = await this.request<string>(
|
||||
`${this.serverUrl}${stateLink.href}?wait=30`,
|
||||
{
|
||||
headers,
|
||||
headers
|
||||
},
|
||||
"text"
|
||||
);
|
||||
@@ -1010,7 +1037,7 @@ export class SASViyaApiClient {
|
||||
private async uploadTables(data: any, accessToken?: string) {
|
||||
const uploadedFiles = [];
|
||||
const headers: any = {
|
||||
"Content-Type": "application/json",
|
||||
"Content-Type": "application/json"
|
||||
};
|
||||
if (accessToken) {
|
||||
headers.Authorization = `Bearer ${accessToken}`;
|
||||
@@ -1027,7 +1054,7 @@ export class SASViyaApiClient {
|
||||
const createFileRequest = {
|
||||
method: "POST",
|
||||
body: csv,
|
||||
headers,
|
||||
headers
|
||||
};
|
||||
|
||||
const uploadResponse = await this.request<any>(
|
||||
@@ -1043,7 +1070,7 @@ export class SASViyaApiClient {
|
||||
private async getFolderUri(folderPath: string, accessToken?: string) {
|
||||
const url = "/folders/folders/@item?path=" + folderPath;
|
||||
const requestInfo: any = {
|
||||
method: "GET",
|
||||
method: "GET"
|
||||
};
|
||||
if (accessToken) {
|
||||
requestInfo.headers = { Authorization: `Bearer ${accessToken}` };
|
||||
@@ -1072,7 +1099,7 @@ export class SASViyaApiClient {
|
||||
if (this.csrfToken) {
|
||||
options.headers = {
|
||||
...options.headers,
|
||||
[this.csrfToken.headerName]: this.csrfToken.value,
|
||||
[this.csrfToken.headerName]: this.csrfToken.value
|
||||
};
|
||||
}
|
||||
return await makeRequest<T>(
|
||||
|
||||
@@ -2,7 +2,7 @@ import SASjs from "./index";
|
||||
|
||||
const adapter = new SASjs();
|
||||
|
||||
it("should parse SAS9 source code", async done => {
|
||||
it("should parse SAS9 source code", async (done) => {
|
||||
expect(sampleResponse).toBeTruthy();
|
||||
const parsedSourceCode = (adapter as any).parseSAS9SourceCode(sampleResponse);
|
||||
expect(parsedSourceCode).toBeTruthy();
|
||||
@@ -16,7 +16,7 @@ it("should parse SAS9 source code", async done => {
|
||||
done();
|
||||
});
|
||||
|
||||
it("should parse generated code", async done => {
|
||||
it("should parse generated code", async (done) => {
|
||||
expect(sampleResponse).toBeTruthy();
|
||||
const parsedGeneratedCode = (adapter as any).parseGeneratedCode(
|
||||
sampleResponse
|
||||
|
||||
62
src/SASjs.ts
62
src/SASjs.ts
@@ -21,7 +21,7 @@ import {
|
||||
parseGeneratedCode,
|
||||
parseWeboutResponse,
|
||||
needsRetry,
|
||||
asyncForEach,
|
||||
asyncForEach
|
||||
} from "./utils";
|
||||
import {
|
||||
SASjsConfig,
|
||||
@@ -29,7 +29,7 @@ import {
|
||||
SASjsWaitingRequest,
|
||||
ServerType,
|
||||
CsrfToken,
|
||||
UploadFile,
|
||||
UploadFile
|
||||
} from "./types";
|
||||
import { SASViyaApiClient } from "./SASViyaApiClient";
|
||||
import { SAS9ApiClient } from "./SAS9ApiClient";
|
||||
@@ -43,7 +43,7 @@ const defaultConfig: SASjsConfig = {
|
||||
serverType: ServerType.SASViya,
|
||||
debug: true,
|
||||
contextName: "SAS Job Execution compute context",
|
||||
useComputeApi: false,
|
||||
useComputeApi: false
|
||||
};
|
||||
|
||||
const requestRetryLimit = 5;
|
||||
@@ -72,7 +72,7 @@ export default class SASjs {
|
||||
constructor(config?: any) {
|
||||
this.sasjsConfig = {
|
||||
...defaultConfig,
|
||||
...config,
|
||||
...config
|
||||
};
|
||||
|
||||
this.setupConfiguration();
|
||||
@@ -270,7 +270,7 @@ export default class SASjs {
|
||||
public async setSASjsConfig(config: SASjsConfig) {
|
||||
this.sasjsConfig = {
|
||||
...this.sasjsConfig,
|
||||
...config,
|
||||
...config
|
||||
};
|
||||
await this.setupConfiguration();
|
||||
}
|
||||
@@ -295,7 +295,7 @@ export default class SASjs {
|
||||
|
||||
return Promise.resolve({
|
||||
isLoggedIn,
|
||||
userName: this.userName,
|
||||
userName: this.userName
|
||||
});
|
||||
}
|
||||
|
||||
@@ -308,7 +308,7 @@ export default class SASjs {
|
||||
const loginParams: any = {
|
||||
_service: "default",
|
||||
username,
|
||||
password,
|
||||
password
|
||||
};
|
||||
|
||||
this.userName = loginParams.username;
|
||||
@@ -319,7 +319,7 @@ export default class SASjs {
|
||||
|
||||
return Promise.resolve({
|
||||
isLoggedIn,
|
||||
userName: this.userName,
|
||||
userName: this.userName
|
||||
});
|
||||
}
|
||||
|
||||
@@ -336,8 +336,8 @@ export default class SASjs {
|
||||
referrerPolicy: "same-origin",
|
||||
body: loginParamsStr,
|
||||
headers: new Headers({
|
||||
"Content-Type": "application/x-www-form-urlencoded",
|
||||
}),
|
||||
"Content-Type": "application/x-www-form-urlencoded"
|
||||
})
|
||||
})
|
||||
.then((response) => response.text())
|
||||
.then(async (responseText) => {
|
||||
@@ -364,7 +364,7 @@ export default class SASjs {
|
||||
|
||||
return {
|
||||
isLoggedIn: loggedIn,
|
||||
userName: this.userName,
|
||||
userName: this.userName
|
||||
};
|
||||
})
|
||||
.catch((e) => Promise.reject(e));
|
||||
@@ -402,7 +402,7 @@ export default class SASjs {
|
||||
this.setCsrfTokenWeb,
|
||||
this.csrfTokenWeb
|
||||
);
|
||||
|
||||
|
||||
return fileUploader.uploadFile(sasJob, files, params);
|
||||
}
|
||||
|
||||
@@ -435,7 +435,7 @@ export default class SASjs {
|
||||
|
||||
config = {
|
||||
...this.sasjsConfig,
|
||||
...config,
|
||||
...config
|
||||
};
|
||||
|
||||
sasJob = sasJob.startsWith("/") ? sasJob.replace("/", "") : sasJob;
|
||||
@@ -526,13 +526,15 @@ export default class SASjs {
|
||||
|
||||
// members of type 'folder' should be processed first
|
||||
if (serviceJson.members[0].members) {
|
||||
serviceJson.members[0].members.sort((member: {type: string}) => member.type === 'folder' ? -1 : 1)
|
||||
serviceJson.members[0].members.sort((member: { type: string }) =>
|
||||
member.type === "folder" ? -1 : 1
|
||||
);
|
||||
}
|
||||
|
||||
const members =
|
||||
serviceJson.members[0].name === "services"
|
||||
? serviceJson.members[0].members
|
||||
: serviceJson.members
|
||||
: serviceJson.members;
|
||||
|
||||
await this.createFoldersAndServices(
|
||||
appLoc,
|
||||
@@ -553,10 +555,10 @@ export default class SASjs {
|
||||
requestPromise: {
|
||||
promise: null,
|
||||
resolve: null,
|
||||
reject: null,
|
||||
reject: null
|
||||
},
|
||||
SASjob: sasJob,
|
||||
data,
|
||||
data
|
||||
};
|
||||
|
||||
sasjsWaitingRequest.requestPromise.promise = new Promise(
|
||||
@@ -588,7 +590,7 @@ export default class SASjs {
|
||||
})
|
||||
.catch(async (response) => {
|
||||
let error = response.error || response;
|
||||
|
||||
|
||||
if (needsRetry(JSON.stringify(error))) {
|
||||
if (this.retryCountComputeApi < requestRetryLimit) {
|
||||
let retryResponse = await this.executeJobViaComputeApi(
|
||||
@@ -636,10 +638,10 @@ export default class SASjs {
|
||||
requestPromise: {
|
||||
promise: null,
|
||||
resolve: null,
|
||||
reject: null,
|
||||
reject: null
|
||||
},
|
||||
SASjob: sasJob,
|
||||
data,
|
||||
data
|
||||
};
|
||||
|
||||
sasjsWaitingRequest.requestPromise.promise = new Promise(
|
||||
@@ -720,10 +722,10 @@ export default class SASjs {
|
||||
requestPromise: {
|
||||
promise: null,
|
||||
resolve: null,
|
||||
reject: null,
|
||||
reject: null
|
||||
},
|
||||
SASjob: sasJob,
|
||||
data,
|
||||
data
|
||||
};
|
||||
const program = config.appLoc
|
||||
? config.appLoc.replace(/\/?$/, "/") + sasJob.replace(/^\//, "")
|
||||
@@ -737,7 +739,7 @@ export default class SASjs {
|
||||
}`;
|
||||
|
||||
const requestParams = {
|
||||
...this.getRequestParamsWeb(config),
|
||||
...this.getRequestParamsWeb(config)
|
||||
};
|
||||
|
||||
const formData = new FormData();
|
||||
@@ -766,7 +768,7 @@ export default class SASjs {
|
||||
}
|
||||
|
||||
const file = new Blob([csv], {
|
||||
type: "application/csv",
|
||||
type: "application/csv"
|
||||
});
|
||||
|
||||
formData.append(name, file, `${name}.csv`);
|
||||
@@ -823,7 +825,7 @@ export default class SASjs {
|
||||
method: "POST",
|
||||
body: formData,
|
||||
referrerPolicy: "same-origin",
|
||||
headers,
|
||||
headers
|
||||
})
|
||||
.then(async (response) => {
|
||||
if (!response.ok) {
|
||||
@@ -834,7 +836,7 @@ export default class SASjs {
|
||||
const token = response.headers.get(tokenHeader);
|
||||
this.csrfTokenWeb = {
|
||||
headerName: tokenHeader,
|
||||
value: token || "",
|
||||
value: token || ""
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -880,7 +882,7 @@ export default class SASjs {
|
||||
resolve(JSON.parse(jsonResponseText));
|
||||
} else {
|
||||
reject({
|
||||
MESSAGE: this.parseSAS9ErrorResponse(responseText),
|
||||
MESSAGE: this.parseSAS9ErrorResponse(responseText)
|
||||
});
|
||||
}
|
||||
} else if (
|
||||
@@ -924,7 +926,7 @@ export default class SASjs {
|
||||
|
||||
return sasjsWaitingRequest.requestPromise.promise;
|
||||
}
|
||||
|
||||
|
||||
private setCsrfTokenWeb = (csrfToken: CsrfToken) => {
|
||||
this.csrfTokenWeb = csrfToken;
|
||||
};
|
||||
@@ -1056,7 +1058,7 @@ export default class SASjs {
|
||||
private fetchLogFileContent(logLink: string) {
|
||||
return new Promise((resolve, reject) => {
|
||||
fetch(logLink, {
|
||||
method: "GET",
|
||||
method: "GET"
|
||||
})
|
||||
.then((response: any) => response.text())
|
||||
.then((response: any) => resolve(response))
|
||||
@@ -1100,7 +1102,7 @@ export default class SASjs {
|
||||
timestamp: new Date(),
|
||||
sourceCode,
|
||||
generatedCode,
|
||||
SASWORK: sasWork,
|
||||
SASWORK: sasWork
|
||||
});
|
||||
|
||||
if (this.sasjsRequests.length > 20) {
|
||||
|
||||
@@ -33,7 +33,7 @@ export class SessionManager {
|
||||
async clearSession(id: string, accessToken?: string) {
|
||||
const deleteSessionRequest = {
|
||||
method: "DELETE",
|
||||
headers: this.getHeaders(accessToken),
|
||||
headers: this.getHeaders(accessToken)
|
||||
};
|
||||
return await this.request<Session>(
|
||||
`${this.serverUrl}/compute/sessions/${id}`,
|
||||
@@ -58,7 +58,7 @@ export class SessionManager {
|
||||
private async createAndWaitForSession(accessToken?: string) {
|
||||
const createSessionRequest = {
|
||||
method: "POST",
|
||||
headers: this.getHeaders(accessToken),
|
||||
headers: this.getHeaders(accessToken)
|
||||
};
|
||||
const { result: createdSession, etag } = await this.request<Session>(
|
||||
`${this.serverUrl}/compute/contexts/${this.currentContext!.id}/sessions`,
|
||||
@@ -75,7 +75,7 @@ export class SessionManager {
|
||||
const { result: contexts } = await this.request<{
|
||||
items: Context[];
|
||||
}>(`${this.serverUrl}/compute/contexts`, {
|
||||
headers: this.getHeaders(accessToken),
|
||||
headers: this.getHeaders(accessToken)
|
||||
});
|
||||
|
||||
const contextsList =
|
||||
@@ -99,7 +99,7 @@ export class SessionManager {
|
||||
|
||||
private getHeaders(accessToken?: string) {
|
||||
const headers: any = {
|
||||
"Content-Type": "application/json",
|
||||
"Content-Type": "application/json"
|
||||
};
|
||||
if (accessToken) {
|
||||
headers.Authorization = `Bearer ${accessToken}`;
|
||||
@@ -117,7 +117,7 @@ export class SessionManager {
|
||||
let sessionState = session.state;
|
||||
const headers: any = {
|
||||
...this.getHeaders(accessToken),
|
||||
"If-None-Match": etag,
|
||||
"If-None-Match": etag
|
||||
};
|
||||
const stateLink = session.links.find((l: any) => l.rel === "state");
|
||||
return new Promise(async (resolve, _) => {
|
||||
@@ -129,7 +129,7 @@ export class SessionManager {
|
||||
const { result: state } = await this.request<string>(
|
||||
`${this.serverUrl}${stateLink.href}?wait=30`,
|
||||
{
|
||||
headers,
|
||||
headers
|
||||
},
|
||||
"text"
|
||||
);
|
||||
@@ -154,7 +154,7 @@ export class SessionManager {
|
||||
if (this.csrfToken) {
|
||||
options.headers = {
|
||||
...options.headers,
|
||||
[this.csrfToken.headerName]: this.csrfToken.value,
|
||||
[this.csrfToken.headerName]: this.csrfToken.value
|
||||
};
|
||||
}
|
||||
return await makeRequest<T>(
|
||||
|
||||
@@ -6,6 +6,7 @@ export interface Job {
|
||||
name: string;
|
||||
uri: string;
|
||||
createdBy: string;
|
||||
code?: string;
|
||||
links: Link[];
|
||||
results: JobResult;
|
||||
error?: any;
|
||||
|
||||
@@ -4,5 +4,5 @@
|
||||
*/
|
||||
export enum ServerType {
|
||||
SASViya = "SASVIYA",
|
||||
SAS9 = "SAS9",
|
||||
SAS9 = "SAS9"
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
*
|
||||
*/
|
||||
export interface UploadFile {
|
||||
file: File;
|
||||
fileName: string;
|
||||
file: File;
|
||||
fileName: string;
|
||||
}
|
||||
|
||||
@@ -29,12 +29,12 @@ export async function makeRequest<T>(
|
||||
const token = response.headers.get(tokenHeader);
|
||||
callback({
|
||||
headerName: tokenHeader,
|
||||
value: token || "",
|
||||
value: token || ""
|
||||
});
|
||||
|
||||
retryRequest = {
|
||||
...request,
|
||||
headers: { ...request.headers, [tokenHeader]: token },
|
||||
headers: { ...request.headers, [tokenHeader]: token }
|
||||
};
|
||||
return fetch(url, retryRequest).then((res) => {
|
||||
etag = res.headers.get("ETag");
|
||||
|
||||
@@ -36,7 +36,7 @@ export const parseAndSubmitAuthorizeForm = async (
|
||||
method: "POST",
|
||||
credentials: "include",
|
||||
body: formData,
|
||||
referrerPolicy: "same-origin",
|
||||
referrerPolicy: "same-origin"
|
||||
})
|
||||
.then((res) => res.text())
|
||||
.then((res) => {
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
export const parseWeboutResponse = (response: string) => {
|
||||
let sasResponse = "";
|
||||
let sasResponse = "";
|
||||
|
||||
if (response.includes(">>weboutBEGIN<<")) {
|
||||
try {
|
||||
sasResponse = response
|
||||
.split(">>weboutBEGIN<<")[1]
|
||||
.split(">>weboutEND<<")[0];
|
||||
} catch (e) {
|
||||
sasResponse = "";
|
||||
console.error(e);
|
||||
}
|
||||
if (response.includes(">>weboutBEGIN<<")) {
|
||||
try {
|
||||
sasResponse = response
|
||||
.split(">>weboutBEGIN<<")[1]
|
||||
.split(">>weboutEND<<")[0];
|
||||
} catch (e) {
|
||||
sasResponse = "";
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
return sasResponse;
|
||||
}
|
||||
return sasResponse;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user