-
-
Demo Seed App for SASjs
-
-
-
-
-
-
+
+
+
+
\ No newline at end of file
diff --git a/src/SAS9ApiClient.ts b/src/SAS9ApiClient.ts
index 8894b6e..ebedd80 100644
--- a/src/SAS9ApiClient.ts
+++ b/src/SAS9ApiClient.ts
@@ -3,49 +3,49 @@
*
*/
export class SAS9ApiClient {
- constructor(private serverUrl: string) {}
+ constructor(private serverUrl: string) {}
- /**
- * returns on object containing the server URL
- */
- public getConfig() {
- return {
- serverUrl: this.serverUrl,
- };
- }
+ /**
+ * @returns an object containing the server URL
+ */
+ public getConfig() {
+ return {
+ serverUrl: this.serverUrl,
+ }
+ }
- /**
- * Updates serverurl which is not null
- * @param serverUrl - the URL of the server.
- */
- public setConfig(serverUrl: string) {
- if (serverUrl) this.serverUrl = serverUrl;
- }
+ /**
+ * Updates serverUrl which is not null
+ * @param serverUrl - the URL of the server.
+ */
+ public setConfig(serverUrl: string) {
+ if (serverUrl) this.serverUrl = serverUrl
+ }
- /**
- * Executes code on a SAS9 server.
- * @param linesOfCode - an array of lines of code to execute
- * @param serverName - the server to execute the code on
- * @param repositoryName - the repository to execute the code on
- */
- public async executeScript(
- linesOfCode: string[],
- serverName: string,
- repositoryName: string
- ) {
- const requestPayload = linesOfCode.join("\n");
- const executeScriptRequest = {
- method: "PUT",
- headers: {
- Accept: "application/json",
- },
- body: `command=${requestPayload}`,
- };
- const executeScriptResponse = await fetch(
- `${this.serverUrl}/sas/servers/${serverName}/cmd?repositoryName=${repositoryName}`,
- executeScriptRequest
- ).then((res) => res.text());
+ /**
+ * Executes code on a SAS9 server.
+ * @param linesOfCode - an array of lines of code to execute
+ * @param serverName - the server to execute the code on
+ * @param repositoryName - the repository to execute the code on
+ */
+ public async executeScript(
+ linesOfCode: string[], // FIXME: rename
+ serverName: string,
+ repositoryName: string
+ ) {
+ const requestPayload = linesOfCode.join('\n')
+ const executeScriptRequest = {
+ method: 'PUT',
+ headers: {Accept: 'application/json'},
+ body: `command=${requestPayload}`,
+ }
+ // FIXME: use axios instead of fetch
+ const executeScriptResponse = await fetch(
+ `${this.serverUrl}/sas/servers/${serverName}/cmd?repositoryName=${repositoryName}`,
+ executeScriptRequest
+ ).then((res) => res.text())
+ // FIXME: no catch block
- return executeScriptResponse;
- }
-}
+ return executeScriptResponse
+ }
+}
\ No newline at end of file
diff --git a/src/SASViyaApiClient.ts b/src/SASViyaApiClient.ts
index 535fb04..145472c 100644
--- a/src/SASViyaApiClient.ts
+++ b/src/SASViyaApiClient.ts
@@ -1,3 +1,13 @@
+/**
+ * TODO: needs to be split into logical blocks:
+ * - Folder
+ * - Config
+ * - Context
+ * - Session
+ * - Job
+ * - Auth
+ */
+
import {
isAuthorizeFormRequired,
parseAndSubmitAuthorizeForm,
@@ -32,7 +42,7 @@ export class SASViyaApiClient {
if (this.rootFolderMap.size) {
return this.rootFolderMap;
}
-
+
this.populateRootFolderMap();
return this.rootFolderMap;
}
diff --git a/src/SASjs.spec.ts b/src/SASjs.spec.ts
index 70f200a..a1f0bd6 100644
--- a/src/SASjs.spec.ts
+++ b/src/SASjs.spec.ts
@@ -2,6 +2,7 @@ import SASjs from "./index";
const adapter = new SASjs();
+// FIXME: adapter doesn't have 'parseSAS9SourceCode' and 'parseGeneratedCode'
it("should parse SAS9 source code", async done => {
expect(sampleResponse).toBeTruthy();
const parsedSourceCode = (adapter as any).parseSAS9SourceCode(sampleResponse);
diff --git a/src/SASjs.ts b/src/SASjs.ts
index b6d953d..418f17c 100644
--- a/src/SASjs.ts
+++ b/src/SASjs.ts
@@ -1,3 +1,16 @@
+/**
+ * TODO: needs to be split into logical blocks:
+ * - Execute
+ * - Context
+ * - Session
+ * - Folder and services
+ * - Job
+ * - Auth
+ * - Config
+ * - Debug
+ * - Response
+ */
+
import "isomorphic-fetch";
import * as e6p from "es6-promise";
(e6p as any).polyfill();
@@ -839,6 +852,7 @@ export default class SASjs {
}
}
+ // FIXME: this method never used
private fetchLogFileContent(logLink: string) {
return new Promise((resolve, reject) => {
fetch(logLink, {
@@ -1038,4 +1052,4 @@ export default class SASjs {
);
});
}
-}
+}
\ No newline at end of file
diff --git a/src/index.ts b/src/index.ts
index 39459c6..bc5ceae 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1,5 +1,7 @@
-import SASjs from "./SASjs";
-export * from "./types";
-export * from "./SASViyaApiClient";
-export * from "./SAS9ApiClient";
-export default SASjs;
+import SASjs from './SASjs'
+
+export * from './types'
+export * from './SASViyaApiClient'
+export * from './SAS9ApiClient'
+
+export default SASjs
\ No newline at end of file
diff --git a/src/types/Context.ts b/src/types/Context.ts
index c5ca093..37bbc1f 100644
--- a/src/types/Context.ts
+++ b/src/types/Context.ts
@@ -3,4 +3,4 @@ export interface Context {
id: string;
createdBy: string;
version: number;
-}
+}
\ No newline at end of file
diff --git a/src/types/CsrfToken.ts b/src/types/CsrfToken.ts
index 7161982..ce4b275 100644
--- a/src/types/CsrfToken.ts
+++ b/src/types/CsrfToken.ts
@@ -1,4 +1,4 @@
export interface CsrfToken {
headerName: string;
value: string;
-}
+}
\ No newline at end of file
diff --git a/src/types/Folder.ts b/src/types/Folder.ts
index 849dc7c..d5716ef 100644
--- a/src/types/Folder.ts
+++ b/src/types/Folder.ts
@@ -4,4 +4,4 @@ export interface Folder {
id: string;
uri: string;
links: Link[];
-}
+}
\ No newline at end of file
diff --git a/src/types/Job.ts b/src/types/Job.ts
index f6b93d9..7e81e0d 100644
--- a/src/types/Job.ts
+++ b/src/types/Job.ts
@@ -8,4 +8,4 @@ export interface Job {
createdBy: string;
links: Link[];
results: JobResult;
-}
+}
\ No newline at end of file
diff --git a/src/types/JobResult.ts b/src/types/JobResult.ts
index 624ac08..074105e 100644
--- a/src/types/JobResult.ts
+++ b/src/types/JobResult.ts
@@ -1,3 +1,3 @@
export interface JobResult {
"_webout.json": string;
-}
+}
\ No newline at end of file
diff --git a/src/types/Link.ts b/src/types/Link.ts
index 7f8c5a3..658a1f7 100644
--- a/src/types/Link.ts
+++ b/src/types/Link.ts
@@ -4,4 +4,4 @@ export interface Link {
href: string;
uri: string;
type: string;
-}
+}
\ No newline at end of file
diff --git a/src/types/SASjsConfig.ts b/src/types/SASjsConfig.ts
index ee40745..f82d86c 100644
--- a/src/types/SASjsConfig.ts
+++ b/src/types/SASjsConfig.ts
@@ -10,6 +10,7 @@ export class SASjsConfig {
* Can be omitted, eg if serving directly from the SAS Web Server or being
* streamed.
*/
+ // TODO: we should clarify what location we are talking about
serverUrl: string = "";
pathSAS9: string = "";
pathSASViya: string = "";
diff --git a/src/types/SASjsRequest.ts b/src/types/SASjsRequest.ts
index 941b5ec..55b6372 100644
--- a/src/types/SASjsRequest.ts
+++ b/src/types/SASjsRequest.ts
@@ -9,4 +9,4 @@ export interface SASjsRequest {
generatedCode: string;
logFile: string;
SASWORK: any;
-}
+}
\ No newline at end of file
diff --git a/src/types/SASjsWaitingRequest.ts b/src/types/SASjsWaitingRequest.ts
index f3c289d..4c8b8d6 100644
--- a/src/types/SASjsWaitingRequest.ts
+++ b/src/types/SASjsWaitingRequest.ts
@@ -2,6 +2,8 @@
* Represents requests that are queued, pending a signon event
*
*/
+
+ // FIXME: be more specific on type declaration
export interface SASjsWaitingRequest {
requestPromise: {
promise: any;
diff --git a/src/types/ServerType.ts b/src/types/ServerType.ts
index 21fbc81..df7b323 100644
--- a/src/types/ServerType.ts
+++ b/src/types/ServerType.ts
@@ -5,4 +5,4 @@
export enum ServerType {
SASViya = "SASVIYA",
SAS9 = "SAS9",
-}
+}
\ No newline at end of file
diff --git a/src/types/Session.ts b/src/types/Session.ts
index 8734fdf..51a9cc0 100644
--- a/src/types/Session.ts
+++ b/src/types/Session.ts
@@ -1,3 +1,3 @@
export interface Session {
id: string;
-}
+}
\ No newline at end of file
diff --git a/src/types/index.ts b/src/types/index.ts
index ad95d88..e0b2721 100644
--- a/src/types/index.ts
+++ b/src/types/index.ts
@@ -7,4 +7,4 @@ export * from "./SASjsConfig";
export * from "./SASjsRequest";
export * from "./SASjsWaitingRequest";
export * from "./ServerType";
-export * from "./Session";
+export * from "./Session";
\ No newline at end of file
diff --git a/src/utils/asyncForEach.ts b/src/utils/asyncForEach.ts
index 9d71542..ee396b0 100644
--- a/src/utils/asyncForEach.ts
+++ b/src/utils/asyncForEach.ts
@@ -1,5 +1,6 @@
+// FIXME: use ES6
export async function asyncForEach(array: any[], callback: any) {
for (let index = 0; index < array.length; index++) {
await callback(array[index], index, array);
}
-}
+}
\ No newline at end of file
diff --git a/src/utils/compareTimestamps.ts b/src/utils/compareTimestamps.ts
index b7a5800..88fea6f 100644
--- a/src/utils/compareTimestamps.ts
+++ b/src/utils/compareTimestamps.ts
@@ -2,7 +2,6 @@ import { SASjsRequest } from "../types/SASjsRequest";
/**
* Comparator for SASjs request timestamps
- *
*/
export const compareTimestamps = (a: SASjsRequest, b: SASjsRequest) => {
return b.timestamp.getTime() - a.timestamp.getTime();
diff --git a/src/utils/convertToCsv.ts b/src/utils/convertToCsv.ts
index bfe0e01..9bcb359 100644
--- a/src/utils/convertToCsv.ts
+++ b/src/utils/convertToCsv.ts
@@ -3,43 +3,43 @@
* @param data - the JSON object to convert.
*/
export const convertToCSV = (data: any) => {
- const replacer = (key: any, value: any) => (value === null ? "" : value);
- const headerFields = Object.keys(data[0]);
+ const replacer = (key: any, value: any) => (value === null ? "" : value); // FIXME: 'key' parameter was not used, why do we compare with null (undefined, NaN)?
+ const headerFields = Object.keys(data[0]); // FIXME: data can be of any type, but we are working with it as with object
let csvTest;
let invalidString = false;
const headers = headerFields.map((field) => {
let firstFoundType: string | null = null;
- let hasMixedTypes: boolean = false;
- let rowNumError: number = -1;
+ let hasMixedTypes: boolean = false; // FIXME: unnecessary type declaration
+ let rowNumError: number = -1; // FIXME: unnecessary type declaration
const longestValueForField = data
- .map((row: any, index: number) => {
+ .map((row: any, index: number) => { // FIXME: row should be of type string | number
if (row[field] || row[field] === "") {
if (firstFoundType) {
- let currentFieldType =
- row[field] === "" || typeof row[field] === "string"
+ let currentFieldType = // FIXME: use const
+ row[field] === "" || typeof row[field] === "string" // FIXME: "" is also of type string
? "chars"
: "number";
if (!hasMixedTypes) {
hasMixedTypes = currentFieldType !== firstFoundType;
- rowNumError = hasMixedTypes ? index + 1 : -1;
+ rowNumError = hasMixedTypes ? index + 1 : -1; // TODO: refactor
}
} else {
if (row[field] === "") {
firstFoundType = "chars";
} else {
firstFoundType =
- typeof row[field] === "string" ? "chars" : "number";
+ typeof row[field] === "string" ? "chars" : "number"; // TODO: refactor
}
}
let byteSize;
if (typeof row[field] === "string") {
- let doubleQuotesFound = row[field]
+ let doubleQuotesFound = row[field] // FIXME: use const
.split("")
- .filter((char: any) => char === '"');
+ .filter((char: any) => char === '"'); // FIXME: why char is of type any?
byteSize = getByteSize(row[field]);
@@ -52,16 +52,18 @@ export const convertToCSV = (data: any) => {
}
})
.sort((a: number, b: number) => b - a)[0];
- if (longestValueForField && longestValueForField > 32765) {
+
+ if (longestValueForField && longestValueForField > 32765) { // FIXME: longestValueForField is an array and it is not comparable to a number
invalidString = true;
}
+
if (hasMixedTypes) {
console.error(
`Row (${rowNumError}), Column (${field}) has mixed types: ERROR`
);
}
- return `${field}:${firstFoundType === "chars" ? "$" : ""}${
+ return `${field}:${firstFoundType === "chars" ? "$" : ""}${ // TODO: format return string before return statement
longestValueForField
? longestValueForField
: firstFoundType === "chars"
@@ -73,10 +75,11 @@ export const convertToCSV = (data: any) => {
if (invalidString) {
return "ERROR: LARGE STRING LENGTH";
}
+
csvTest = data.map((row: any) => {
const fields = Object.keys(row).map((fieldName, index) => {
let value;
- let containsSpecialChar = false;
+ let containsSpecialChar = false; // FIXME: should be const
const currentCell = row[fieldName];
if (JSON.stringify(currentCell).search(/(\\t|\\n|\\r)/gm) > -1) {
@@ -89,7 +92,7 @@ export const convertToCSV = (data: any) => {
value = value.replace(/\\\\/gm, "\\");
if (containsSpecialChar) {
- if (value.includes(",") || value.includes('"')) {
+ if (value.includes(",") || value.includes('"')) { // FIXME: use `"`
value = '"' + value + '"';
}
} else {
@@ -112,6 +115,7 @@ export const convertToCSV = (data: any) => {
return value;
});
+
return fields.join(",");
});
@@ -121,6 +125,7 @@ export const convertToCSV = (data: any) => {
return finalCSV;
};
+// TODO: refactor
const getByteSize = (str: string) => {
let byteSize = str.length;
for (let i = str.length - 1; i >= 0; i--) {
@@ -130,4 +135,4 @@ const getByteSize = (str: string) => {
if (code >= 0xdc00 && code <= 0xdfff) i--; //trail surrogate
}
return byteSize;
-};
+};
\ No newline at end of file
diff --git a/src/utils/isAuthorizeFormRequired.ts b/src/utils/isAuthorizeFormRequired.ts
index a1d5b38..403f593 100644
--- a/src/utils/isAuthorizeFormRequired.ts
+++ b/src/utils/isAuthorizeFormRequired.ts
@@ -1,3 +1,3 @@
export const isAuthorizeFormRequired = (response: string): boolean => {
return /
/gm.test(response);
-};
+};
\ No newline at end of file
diff --git a/src/utils/isLoginRequired.ts b/src/utils/isLoginRequired.ts
index 65448bc..e7a929b 100644
--- a/src/utils/isLoginRequired.ts
+++ b/src/utils/isLoginRequired.ts
@@ -1,5 +1,6 @@
export const isLogInRequired = (response: string): boolean => {
- const pattern: RegExp = //gm;
+ const pattern: RegExp = //gm; // FIXME: unnecessary type declaration
const matches = pattern.test(response);
+
return matches;
-};
+};
\ No newline at end of file
diff --git a/src/utils/isLoginSuccess.ts b/src/utils/isLoginSuccess.ts
index 40d46d2..bffeaff 100644
--- a/src/utils/isLoginSuccess.ts
+++ b/src/utils/isLoginSuccess.ts
@@ -1,2 +1 @@
-export const isLogInSuccess = (response: string): boolean =>
- /You have signed in/gm.test(response);
+export const isLogInSuccess = (response: string): boolean => /You have signed in/gm.test(response); // TODO: maybe we have more reliable way to verify that login was successful?
\ No newline at end of file
diff --git a/src/utils/makeRequest.ts b/src/utils/makeRequest.ts
index 1d28c23..135b477 100644
--- a/src/utils/makeRequest.ts
+++ b/src/utils/makeRequest.ts
@@ -2,30 +2,33 @@ import { CsrfToken } from "../types";
export async function makeRequest(
url: string,
- request: RequestInit,
+ request: RequestInit, // Where 'RequestInit' is coming from?
callback: (value: CsrfToken) => any,
contentType: "text" | "json" = "json"
): Promise {
- const responseTransform =
- contentType === "json"
- ? (res: Response) => res.json()
- : (res: Response) => res.text();
- const result = await fetch(url, request).then((response) => {
- if (!response.ok) {
+ const responseTransform = contentType === "json" ?
+ (res: Response) => res.json()
+ :
+ (res: Response) => res.text();
+
+ const result = await fetch(url, request).then((response) => { // FIXME: use axios instead of fetch
+ if (!response.ok) { // FIXME we can just check if status === 403
if (response.status === 403) {
const tokenHeader = response.headers.get("X-CSRF-HEADER");
if (tokenHeader) {
- const token = response.headers.get(tokenHeader);
+ const token = response.headers.get(tokenHeader) || ''; // TODO: refactor
+
callback({
headerName: tokenHeader,
- value: token || "",
+ value: token,
});
const retryRequest = {
...request,
headers: { ...request.headers, [tokenHeader]: token },
};
+
return fetch(url, retryRequest).then(responseTransform);
}
}
@@ -33,5 +36,6 @@ export async function makeRequest(
return responseTransform(response);
}
});
+
return result;
}
diff --git a/src/utils/needsRetry.ts b/src/utils/needsRetry.ts
index cb70c6c..01e9899 100644
--- a/src/utils/needsRetry.ts
+++ b/src/utils/needsRetry.ts
@@ -1,3 +1,4 @@
+// TODO: refactor
export const needsRetry = (responseText: string): boolean => {
return (
(responseText.includes('"errorCode":403') &&
@@ -8,4 +9,4 @@ export const needsRetry = (responseText: string): boolean => {
(responseText.includes('"status":449') &&
responseText.includes("Authentication success, retry original request"))
);
-};
+};
\ No newline at end of file
diff --git a/src/utils/parseAndSubmitAuthorizeForm.ts b/src/utils/parseAndSubmitAuthorizeForm.ts
index 7a3bf96..411581c 100644
--- a/src/utils/parseAndSubmitAuthorizeForm.ts
+++ b/src/utils/parseAndSubmitAuthorizeForm.ts
@@ -6,7 +6,7 @@ export const parseAndSubmitAuthorizeForm = async (
const params: any = {};
const responseBody = response.split("")[1].split("")[0];
- const bodyElement = document.createElement("div");
+ const bodyElement = document.createElement("div"); // TODO: rename
bodyElement.innerHTML = responseBody;
const form = bodyElement.querySelector("#application_authorization");
@@ -24,7 +24,7 @@ export const parseAndSubmitAuthorizeForm = async (
const formData = new FormData();
- for (const key in params) {
+ for (const key in params) { // TODO: use forEach
if (params.hasOwnProperty(key)) {
formData.append(key, params[key]);
}
@@ -32,7 +32,7 @@ export const parseAndSubmitAuthorizeForm = async (
return new Promise((resolve, reject) => {
if (authUrl) {
- fetch(authUrl, {
+ fetch(authUrl, { // TODO use axios instead of fetch
method: "POST",
credentials: "include",
body: formData,
@@ -46,4 +46,4 @@ export const parseAndSubmitAuthorizeForm = async (
reject("Auth form url is null");
}
});
-};
+};
\ No newline at end of file
diff --git a/src/utils/parseGeneratedCode.ts b/src/utils/parseGeneratedCode.ts
index 74acce8..ffb3d25 100644
--- a/src/utils/parseGeneratedCode.ts
+++ b/src/utils/parseGeneratedCode.ts
@@ -1,7 +1,7 @@
export const parseGeneratedCode = (log: string) => {
const startsWith = "MPRINT";
- const isGeneratedCodeLine = (line: string) =>
- line.trim().startsWith(startsWith);
+ const isGeneratedCodeLine = (line: string) => line.trim().startsWith(startsWith);
const logLines = log.split("\n").filter(isGeneratedCodeLine);
+
return logLines.join("\r\n");
};
diff --git a/src/utils/parseSasViyaLog.ts b/src/utils/parseSasViyaLog.ts
index 2a29d78..62c6ec8 100644
--- a/src/utils/parseSasViyaLog.ts
+++ b/src/utils/parseSasViyaLog.ts
@@ -1,12 +1,15 @@
-export const parseSasViyaLog = (logResponse: { items: any[] }) => {
+export const parseSasViyaLog = (logResponse: { items: any[] }) => { // TODO: be more specific on type declaration
let log;
+
try {
log = logResponse.items
? logResponse.items.map((i) => i.line).join("\n")
: JSON.stringify(logResponse);
- } catch (e) {
+ } catch (e) { // TODO: rename parameter to err or error
console.error("An error has occurred while parsing the log response", e);
+
log = logResponse;
}
+
return log;
};
diff --git a/src/utils/parseSourceCode.ts b/src/utils/parseSourceCode.ts
index d5b8ac6..1ad5f71 100644
--- a/src/utils/parseSourceCode.ts
+++ b/src/utils/parseSourceCode.ts
@@ -1,6 +1,6 @@
export const parseSourceCode = (log: string): string => {
- const isSourceCodeLine = (line: string) =>
- line.trim().substring(0, 10).trimStart().match(/^\d/);
+ const isSourceCodeLine = (line: string) => line.trim().substring(0, 10).trimStart().match(/^\d/);
const logLines = log.split("\n").filter(isSourceCodeLine);
+
return logLines.join("\r\n");
};
diff --git a/src/utils/serialize.ts b/src/utils/serialize.ts
index 4816a5a..97c8775 100644
--- a/src/utils/serialize.ts
+++ b/src/utils/serialize.ts
@@ -1,6 +1,7 @@
-export const serialize = (obj: any) => {
+export const serialize = (obj: any) => { // TODO: be more specific on type declaration
const str: any[] = [];
- for (const p in obj) {
+
+ for (const p in obj) { // FIXME: name variables properly
if (obj.hasOwnProperty(p)) {
if (obj[p] instanceof Array) {
for (let i = 0, n = obj[p].length; i < n; i++) {
@@ -11,5 +12,6 @@ export const serialize = (obj: any) => {
}
}
}
+
return str.join("&");
-};
+};
\ No newline at end of file