1
0
mirror of https://github.com/sasjs/adapter.git synced 2026-01-11 06:10:05 +00:00
This commit is contained in:
mulahasanovic
2025-10-17 09:55:03 +00:00
parent f03105bb1e
commit ce4e556400
58 changed files with 344 additions and 344 deletions

View File

@@ -17,10 +17,9 @@
<h1>@sasjs/adapter</h1>
</a>
<p><a href="http://npmjs.org/package/@sasjs/adapter"><img src="https://img.shields.io/npm/v/@sasjs/adapter.svg" alt="npm package"></a>
<a href="https://github.com/sasjs/adapter/blob/main/.github/workflows/build.yml"><img src="https://github.com/sasjs/adapter/actions/workflows/build.yml/badge.svg" alt="Github Workflow"></a>
<a href="https://github.com/sasjs/adapter/blob/main/.github/workflows/build.yml"><img src="https://github.com/sasjs/adapter/actions/workflows/build-unit-tests.yml/badge.svg" alt="Github Workflow"></a>
<a href=""><img src="https://img.shields.io/npm/dt/@sasjs/adapter" alt="npm"></a>
<img src="https://img.shields.io/snyk/vulnerabilities/npm/@sasjs/adapter" alt="Snyk Vulnerabilities for npm package">
<a href="/LICENSE"><img src="https://img.shields.io/apm/l/atomic-design-ui.svg" alt="License"></a>
<img src="https://img.shields.io/github/license/sasjs/adapter" alt="GitHub License">
<img src="https://img.shields.io/github/languages/top/sasjs/adapter" alt="GitHub top language">
<img src="https://img.shields.io/github/issues/sasjs/adapter" alt="GitHub issues">
<a href="https://gitpod.io/#https://github.com/sasjs/adapter"><img src="https://img.shields.io/badge/Gitpod-ready--to--code-908a85?logo=gitpod" alt="Gitpod ready-to-code"></a></p>
@@ -55,16 +54,16 @@
<h3>JS Request / Response</h3>
</a>
<p>To install the library you can simply run <code>npm i @sasjs/adapter</code> or include a <code>&lt;script&gt;</code> tag with a reference to our <a href="https://www.jsdelivr.com/package/npm/@sasjs/adapter">CDN</a>.</p>
<p>Full technical documentation is available <a href="https://adapter.sasjs.io">here</a>. The main parts are:</p>
<p>Full technical documentation is available <a href="https://adapter.sasjs.io">here</a>. The main parts are:</p>
<a href="#instantiation" id="instantiation" style="color: inherit; text-decoration: none;">
<h3>Instantiation</h3>
</a>
<p>The following code will instantiate an instance of the adapter:</p>
<pre><code class="language-javascript"><span class="hl-1">let</span><span class="hl-0"> </span><span class="hl-2">sasJs</span><span class="hl-0"> = </span><span class="hl-1">new</span><span class="hl-0"> </span><span class="hl-2">SASjs</span><span class="hl-0">.</span><span class="hl-3">default</span><span class="hl-0">(</span><br/><span class="hl-0"> {</span><br/><span class="hl-0"> </span><span class="hl-2">appLoc:</span><span class="hl-0"> </span><span class="hl-4">&quot;/Your/SAS/Folder&quot;</span><span class="hl-0">,</span><br/><span class="hl-0"> </span><span class="hl-2">serverType:</span><span class="hl-4">&quot;SAS9&quot;</span><br/><span class="hl-0"> }</span><br/><span class="hl-0">);</span>
<pre><code class="language-javascript"><span class="hl-1">let</span><span class="hl-0"> </span><span class="hl-2">sasJs</span><span class="hl-0"> = </span><span class="hl-1">new</span><span class="hl-0"> </span><span class="hl-2">SASjs</span><span class="hl-0">.</span><span class="hl-3">default</span><span class="hl-0">({</span><br/><span class="hl-0"> </span><span class="hl-2">appLoc:</span><span class="hl-0"> </span><span class="hl-4">&#39;/Your/SAS/Folder&#39;</span><span class="hl-0">,</span><br/><span class="hl-0"> </span><span class="hl-2">serverType:</span><span class="hl-0"> </span><span class="hl-4">&#39;SAS9&#39;</span><br/><span class="hl-0">})</span>
</code></pre>
<p>If you&#39;ve installed it via NPM, you can import it as a default import like so:</p>
<pre><code class="language-js"><span class="hl-0"> </span><span class="hl-5">import</span><span class="hl-0"> </span><span class="hl-2">SASjs</span><span class="hl-0"> </span><span class="hl-5">from</span><span class="hl-0"> </span><span class="hl-4">&#39;@sasjs/adapter&#39;</span><span class="hl-0">;</span>
<pre><code class="language-js"><span class="hl-5">import</span><span class="hl-0"> </span><span class="hl-2">SASjs</span><span class="hl-0"> </span><span class="hl-5">from</span><span class="hl-0"> </span><span class="hl-4">&#39;@sasjs/adapter&#39;</span>
</code></pre>
<p>You can then instantiate it with:</p>
<pre><code class="language-js"><span class="hl-1">const</span><span class="hl-0"> </span><span class="hl-6">sasJs</span><span class="hl-0"> = </span><span class="hl-1">new</span><span class="hl-0"> </span><span class="hl-3">SASjs</span><span class="hl-0">({your </span><span class="hl-2">config</span><span class="hl-0">})</span>
@@ -74,10 +73,10 @@
<a href="#sas-logon" id="sas-logon" style="color: inherit; text-decoration: none;">
<h3>SAS Logon</h3>
</a>
<p>All authentication from the adapter is done against SASLogon. There are two approaches that can be taken, which are configured using the <code>loginMechanism</code> attribute of the sasJs config object (above):</p>
<p>All authentication from the adapter is done against SASLogon. There are two approaches that can be taken, which are configured using the <code>loginMechanism</code> attribute of the sasJs config object (above):</p>
<ul>
<li><code>loginMechanism:&#39;Redirected&#39;</code> - this approach enables authentication through a SASLogon window, supporting complex authentication flows (such as 2FA) and avoids the need to handle passwords in the application itself. The styling of the window can be modified using CSS.</li>
<li><code>loginMechanism:&#39;Default&#39;</code> - this approach requires that the username and password are captured, and used within the <code>.login()</code> method. This can be helpful for development, or automated testing.</li>
<li><code>loginMechanism:&#39;Redirected&#39;</code> - this approach enables authentication through a SASLogon window, supporting complex authentication flows (such as 2FA) and avoids the need to handle passwords in the application itself. The styling of the window can be modified using CSS.</li>
<li><code>loginMechanism:&#39;Default&#39;</code> - this approach requires that the username and password are captured, and used within the <code>.login()</code> method. This can be helpful for development, or automated testing.</li>
</ul>
<p>Sample code for logging in with the <code>Default</code> approach:</p>
<pre><code class="language-javascript"><span class="hl-2">sasJs</span><span class="hl-0">.</span><span class="hl-3">logIn</span><span class="hl-0">(</span><span class="hl-4">&#39;USERNAME&#39;</span><span class="hl-0">,</span><span class="hl-4">&#39;PASSWORD&#39;</span><br/><span class="hl-0"> ).</span><span class="hl-3">then</span><span class="hl-0">((</span><span class="hl-2">response</span><span class="hl-0">) </span><span class="hl-1">=&gt;</span><span class="hl-0"> {</span><br/><span class="hl-0"> </span><span class="hl-5">if</span><span class="hl-0"> (</span><span class="hl-2">response</span><span class="hl-0">.</span><span class="hl-2">isLoggedIn</span><span class="hl-0"> === </span><span class="hl-1">true</span><span class="hl-0">) {</span><br/><span class="hl-0"> </span><span class="hl-2">console</span><span class="hl-0">.</span><span class="hl-3">log</span><span class="hl-0">(</span><span class="hl-4">&#39;do stuff&#39;</span><span class="hl-0">)</span><br/><span class="hl-0"> } </span><span class="hl-5">else</span><span class="hl-0"> {</span><br/><span class="hl-0"> </span><span class="hl-2">console</span><span class="hl-0">.</span><span class="hl-3">log</span><span class="hl-0">(</span><span class="hl-4">&#39;do other stuff&#39;</span><span class="hl-0">)</span><br/><span class="hl-0"> }</span><br/><span class="hl-0">}</span>
@@ -88,16 +87,16 @@
<h3>Request / Response</h3>
</a>
<p>A simple request can be sent to SAS in the following fashion:</p>
<pre><code class="language-javascript"><span class="hl-2">sasJs</span><span class="hl-0">.</span><span class="hl-3">request</span><span class="hl-0">(</span><span class="hl-4">&quot;/path/to/my/service&quot;</span><span class="hl-0">, </span><span class="hl-2">dataObject</span><span class="hl-0">)</span><br/><span class="hl-0"> .</span><span class="hl-3">then</span><span class="hl-0">((</span><span class="hl-2">response</span><span class="hl-0">) </span><span class="hl-1">=&gt;</span><span class="hl-0"> {</span><br/><span class="hl-0"> </span><span class="hl-7">// all tables are in the response object, eg:</span><br/><span class="hl-0"> </span><span class="hl-2">console</span><span class="hl-0">.</span><span class="hl-3">log</span><span class="hl-0">(</span><span class="hl-2">response</span><span class="hl-0">.</span><span class="hl-2">tablewith2cols1row</span><span class="hl-0">[</span><span class="hl-8">0</span><span class="hl-0">].</span><span class="hl-6">COL1</span><span class="hl-0">.</span><span class="hl-2">value</span><span class="hl-0">)</span><br/><span class="hl-0"> })</span>
<pre><code class="language-javascript"><span class="hl-2">sasJs</span><span class="hl-0">.</span><span class="hl-3">request</span><span class="hl-0">(</span><span class="hl-4">&#39;/path/to/my/service&#39;</span><span class="hl-0">, </span><span class="hl-2">dataObject</span><span class="hl-0">).</span><span class="hl-3">then</span><span class="hl-0">((</span><span class="hl-2">response</span><span class="hl-0">) </span><span class="hl-1">=&gt;</span><span class="hl-0"> {</span><br/><span class="hl-0"> </span><span class="hl-7">// all tables are in the response object, eg:</span><br/><span class="hl-0"> </span><span class="hl-2">console</span><span class="hl-0">.</span><span class="hl-3">log</span><span class="hl-0">(</span><span class="hl-2">response</span><span class="hl-0">.</span><span class="hl-2">tablewith2cols1row</span><span class="hl-0">[</span><span class="hl-8">0</span><span class="hl-0">].</span><span class="hl-6">COL1</span><span class="hl-0">.</span><span class="hl-2">value</span><span class="hl-0">)</span><br/><span class="hl-0">})</span>
</code></pre>
<p>We supply the path to the SAS service, and a data object.</p>
<p>If the path starts with a <code>/</code> then it should be a full path to the service. If there is no leading <code>/</code> then it is relative to the <code>appLoc</code>.</p>
<p>If the path starts with a <code>/</code> then it should be a full path to the service. If there is no leading <code>/</code> then it is relative to the <code>appLoc</code>.</p>
<p>The data object can be null (for services with no input), or can contain one or more &quot;tables&quot; in the following format:</p>
<pre><code class="language-javascript"><span class="hl-1">let</span><span class="hl-0"> </span><span class="hl-2">dataObject</span><span class="hl-0">={</span><br/><span class="hl-0"> </span><span class="hl-4">&quot;tablewith2cols1row&quot;</span><span class="hl-2">:</span><span class="hl-0"> [{</span><br/><span class="hl-0"> </span><span class="hl-4">&quot;col1&quot;</span><span class="hl-2">:</span><span class="hl-0"> </span><span class="hl-4">&quot;val1&quot;</span><span class="hl-0">,</span><br/><span class="hl-0"> </span><span class="hl-4">&quot;col2&quot;</span><span class="hl-2">:</span><span class="hl-0"> </span><span class="hl-8">42</span><br/><span class="hl-0"> }],</span><br/><span class="hl-0"> </span><span class="hl-4">&quot;tablewith1col2rows&quot;</span><span class="hl-2">:</span><span class="hl-0"> [{</span><br/><span class="hl-0"> </span><span class="hl-4">&quot;col&quot;</span><span class="hl-2">:</span><span class="hl-0"> </span><span class="hl-4">&quot;row1&quot;</span><br/><span class="hl-0"> }, {</span><br/><span class="hl-0"> </span><span class="hl-4">&quot;col&quot;</span><span class="hl-2">:</span><span class="hl-0"> </span><span class="hl-4">&quot;row2&quot;</span><br/><span class="hl-0"> }]</span><br/><span class="hl-0">};</span>
<pre><code class="language-javascript"><span class="hl-1">let</span><span class="hl-0"> </span><span class="hl-2">dataObject</span><span class="hl-0"> = {</span><br/><span class="hl-0"> </span><span class="hl-2">tablewith2cols1row:</span><span class="hl-0"> [</span><br/><span class="hl-0"> {</span><br/><span class="hl-0"> </span><span class="hl-2">col1:</span><span class="hl-0"> </span><span class="hl-4">&#39;val1&#39;</span><span class="hl-0">,</span><br/><span class="hl-0"> </span><span class="hl-2">col2:</span><span class="hl-0"> </span><span class="hl-8">42</span><br/><span class="hl-0"> }</span><br/><span class="hl-0"> ],</span><br/><span class="hl-0"> </span><span class="hl-2">tablewith1col2rows:</span><span class="hl-0"> [</span><br/><span class="hl-0"> {</span><br/><span class="hl-0"> </span><span class="hl-2">col:</span><span class="hl-0"> </span><span class="hl-4">&#39;row1&#39;</span><br/><span class="hl-0"> },</span><br/><span class="hl-0"> {</span><br/><span class="hl-0"> </span><span class="hl-2">col:</span><span class="hl-0"> </span><span class="hl-4">&#39;row2&#39;</span><br/><span class="hl-0"> }</span><br/><span class="hl-0"> ]</span><br/><span class="hl-0">}</span>
</code></pre>
<p>These tables (<code>tablewith2cols1row</code> and <code>tablewith1col2rows</code>) will be created in SAS WORK after running <code>%webout(FETCH)</code> in your SAS service.</p>
<p>The <code>request()</code> method also has optional parameters such as a config object and a callback login function.</p>
<p>The response object will contain returned tables and columns. Table names are always lowercase, and column names uppercase.</p>
<p>The response object will contain returned tables and columns. Table names are always lowercase, and column names uppercase.</p>
<p>The adapter will also cache the logs (if debug enabled) and even the work tables. For performance, it is best to keep debug mode off.</p>
<a href="#verbose-mode" id="verbose-mode" style="color: inherit; text-decoration: none;">
@@ -123,7 +122,7 @@
<li>If the values are numeric, the SAS type is numeric</li>
<li>If the values are all string, the SAS type is character</li>
<li>If the values contain a single character (a-Z + underscore + .) AND a numeric, then the SAS type is numeric (with special missing values).</li>
<li><code>null</code> is set to either &#39;.&#39; or &#39;&#39; depending on the assigned or derived type per the above rules. If entire column is <code>null</code> then the type will be numeric.</li>
<li><code>null</code> is set to either &#39;.&#39; or &#39;&#39; depending on the assigned or derived type per the above rules. If entire column is <code>null</code> then the type will be numeric.</li>
</ul>
<p>The following table illustrates the formats applied to columns under various scenarios:</p>
<table>
@@ -182,7 +181,7 @@
<td>best.</td>
</tr>
</tbody></table>
<p>Validation is also performed on the values. The following combinations will throw errors:</p>
<p>Validation is also performed on the values. The following combinations will throw errors:</p>
<table>
<thead>
<tr>
@@ -200,7 +199,7 @@
</tr>
<tr>
<td>1.1, &#39;.&#39;, 0</td>
<td>Error: mixed types. For regular nulls, use <code>null</code></td>
<td>Error: mixed types. For regular nulls, use <code>null</code></td>
</tr>
</tbody></table>
@@ -213,13 +212,13 @@
<li>A numeric column containing only special missing values (is considered character)</li>
</ul>
<p>To cater for these scenarios, an optional array of formats can be passed along with the data to ensure that SAS will read them in correctly.</p>
<p>To understand these formats, it should be noted that the JSON data is NOT passed directly (as JSON) to SAS. It is first converted into CSV, and the header row is actually an <code>infile</code> statement in disguise. It looks a bit like this:</p>
<p>To understand these formats, it should be noted that the JSON data is NOT passed directly (as JSON) to SAS. It is first converted into CSV, and the header row is actually an <code>infile</code> statement in disguise. It looks a bit like this:</p>
<pre><code class="language-csv">CHARVAR1:$char4. CHARVAR2:$char1. NUMVAR:best.
LOAD,,0
ABCD,X,.
</code></pre>
<p>To provide overrides to this header row, the tables object can be constructed as follows (with a leading &#39;$&#39; in the table name):</p>
<pre><code class="language-javascript"><span class="hl-1">let</span><span class="hl-0"> </span><span class="hl-2">specialData</span><span class="hl-0">={</span><br/><span class="hl-0"> </span><span class="hl-4">&quot;tablewith2cols2rows&quot;</span><span class="hl-2">:</span><span class="hl-0"> [</span><br/><span class="hl-0"> {</span><span class="hl-4">&quot;col1&quot;</span><span class="hl-2">:</span><span class="hl-0"> </span><span class="hl-4">&quot;val1&quot;</span><span class="hl-0">,</span><span class="hl-4">&quot;specialMissingsCol&quot;</span><span class="hl-2">:</span><span class="hl-0"> </span><span class="hl-4">&quot;A&quot;</span><span class="hl-0">},</span><br/><span class="hl-0"> {</span><span class="hl-4">&quot;col1&quot;</span><span class="hl-2">:</span><span class="hl-0"> </span><span class="hl-4">&quot;val2&quot;</span><span class="hl-0">,</span><span class="hl-4">&quot;specialMissingsCol&quot;</span><span class="hl-2">:</span><span class="hl-0"> </span><span class="hl-4">&quot;_&quot;</span><span class="hl-0">}</span><br/><span class="hl-0"> ],</span><br/><span class="hl-0"> </span><span class="hl-4">&quot;$tablewith2cols2rows&quot;</span><span class="hl-2">:</span><span class="hl-0">{</span><span class="hl-4">&quot;formats&quot;</span><span class="hl-2">:</span><span class="hl-0">{</span><span class="hl-4">&quot;specialMissingsCol&quot;</span><span class="hl-2">:</span><span class="hl-4">&quot;best.&quot;</span><span class="hl-0">}</span><br/><span class="hl-0"> }</span><br/><span class="hl-0">};</span>
<pre><code class="language-javascript"><span class="hl-1">let</span><span class="hl-0"> </span><span class="hl-2">specialData</span><span class="hl-0"> = {</span><br/><span class="hl-0"> </span><span class="hl-2">tablewith2cols2rows:</span><span class="hl-0"> [</span><br/><span class="hl-0"> { </span><span class="hl-2">col1:</span><span class="hl-0"> </span><span class="hl-4">&#39;val1&#39;</span><span class="hl-0">, </span><span class="hl-2">specialMissingsCol:</span><span class="hl-0"> </span><span class="hl-4">&#39;A&#39;</span><span class="hl-0"> },</span><br/><span class="hl-0"> { </span><span class="hl-2">col1:</span><span class="hl-0"> </span><span class="hl-4">&#39;val2&#39;</span><span class="hl-0">, </span><span class="hl-2">specialMissingsCol:</span><span class="hl-0"> </span><span class="hl-4">&#39;_&#39;</span><span class="hl-0"> }</span><br/><span class="hl-0"> ],</span><br/><span class="hl-0"> </span><span class="hl-2">$tablewith2cols2rows:</span><span class="hl-0"> { </span><span class="hl-2">formats:</span><span class="hl-0"> { </span><span class="hl-2">specialMissingsCol:</span><span class="hl-0"> </span><span class="hl-4">&#39;best.&#39;</span><span class="hl-0"> } }</span><br/><span class="hl-0">}</span>
</code></pre>
<p>It is not necessary to provide formats for ALL the columns, only the ones that need to be overridden.</p>
@@ -230,11 +229,11 @@ ABCD,X,.
<p>The following snippet shows the process of SAS tables arriving / leaving:</p>
<pre><code class="language-sas"><span class="hl-7">/* convert frontend input tables from into SASWORK datasets */</span><br/><span class="hl-0">%webout(FETCH)</span><br/><br/><span class="hl-7">/* some sas code */</span><br/><span class="hl-0">data a b c;</span><br/><span class="hl-0"> set from js;</span><br/><span class="hl-0">run;</span><br/><br/><span class="hl-0">%webout(OPEN) /* Open the JSON to be returned */</span><br/><span class="hl-0">%webout(OBJ,a) /* Rows in table `a` are objects (easy to use) */</span><br/><span class="hl-0">%webout(ARR,b) /* Rows in table `b` are arrays (compact) */</span><br/><span class="hl-0">%webout(OBJ,c,fmt=N) /* Table `c` is sent unformatted (raw) */</span><br/><span class="hl-0">%webout(OBJ,c,dslabel=d) /* Rename table as `d` in output JSON */</span><br/><span class="hl-0">%webout(OBJ,c,dslabel=e, maxobs=10) /* send only 10 rows back */</span><br/><span class="hl-0">%webout(CLOSE) /* Close the JSON and add default variables */</span>
</code></pre>
<p>By default, special SAS numeric missings (_a-Z) are converted to <code>null</code> in the JSON. If you&#39;d like to preserve these, use the <code>missing=STRING</code> option as follows:</p>
<p>By default, special SAS numeric missings (_a-Z) are converted to <code>null</code> in the JSON. If you&#39;d like to preserve these, use the <code>missing=STRING</code> option as follows:</p>
<pre><code class="language-sas"><span class="hl-0">%webout(OBJ,a,missing=STRING)</span>
</code></pre>
<p>In this case, special missings (such as <code>.a</code>, <code>.b</code>) are converted to javascript string values (<code>&#39;A&#39;, &#39;B&#39;</code>).</p>
<p>Where an entire column is made up of special missing numerics, there would be no way to distinguish it from a single-character column by looking at the values. To cater for this scenario, it is possible to export the variable types (and other attributes such as label and format) by adding a <code>showmeta</code> param to the <code>webout()</code> macro as follows:</p>
<p>Where an entire column is made up of special missing numerics, there would be no way to distinguish it from a single-character column by looking at the values. To cater for this scenario, it is possible to export the variable types (and other attributes such as label and format) by adding a <code>showmeta</code> param to the <code>webout()</code> macro as follows:</p>
<pre><code class="language-sas"><span class="hl-0">%webout(OBJ,a,missing=STRING,showmeta=YES)</span>
</code></pre>
<p>The <code>%webout()</code> macro itself is just a wrapper for the <a href="https://core.sasjs.io/mp__jsonout_8sas.html">mp_jsonout</a> macro.</p>
@@ -242,24 +241,24 @@ ABCD,X,.
<a href="#configuration" id="configuration" style="color: inherit; text-decoration: none;">
<h2>Configuration</h2>
</a>
<p>Configuration on the client side involves passing an object on startup, which can also be passed with each request. Technical documentation on the SASjsConfig class is available <a href="https://adapter.sasjs.io/classes/types.sasjsconfig.html">here</a>. The main config items are:</p>
<p>Configuration on the client side involves passing an object on startup, which can also be passed with each request. Technical documentation on the SASjsConfig class is available <a href="https://github.com/sasjs/adapter/blob/master/src/types/SASjsConfig.ts">here</a>. The main config items are:</p>
<ul>
<li><code>appLoc</code> - this is the folder (eg in metadata or SAS Drive) under which the SAS services are created.</li>
<li><code>serverType</code> - either <code>SAS9</code>, <code>SASVIYA</code> or <code>SASJS</code>. The <code>SASJS</code> server type is for use with <a href="https://github.com/sasjs/server">sasjs/server</a>.</li>
<li><code>serverType</code> - either <code>SAS9</code>, <code>SASVIYA</code> or <code>SASJS</code>. The <code>SASJS</code> server type is for use with <a href="https://github.com/sasjs/server">sasjs/server</a>.</li>
<li><code>serverUrl</code> - the location (including http protocol and port) of the SAS Server. Can be omitted, eg if serving directly from the SAS Web Server, or in streaming mode.</li>
<li><code>debug</code> - if <code>true</code> then SAS Logs and extra debug information is returned.</li>
<li><code>verbose</code> - optional, if <code>true</code> then a summary of every HTTP response is logged.</li>
<li><code>loginMechanism</code> - either <code>Default</code> or <code>Redirected</code>. See <a href="#sas-logon">SAS Logon</a> section.</li>
<li><code>useComputeApi</code> - Only relevant when the serverType is <code>SASVIYA</code>. If <code>true</code> the <a href="#using-the-compute-api">Compute API</a> is used. If <code>false</code> the <a href="#using-the-jes-api">JES API</a> is used. If <code>null</code> or <code>undefined</code> the <a href="#using-jes-web-app">Web</a> approach is used.</li>
<li><code>contextName</code> - Compute context on which the requests will be called. If missing or not provided, defaults to <code>Job Execution Compute context</code>.</li>
<li><code>requestHistoryLimit</code> - Request history limit. Increasing this limit may affect browser performance, especially with debug (logs) enabled. Default is 10.</li>
<li><code>loginMechanism</code> - either <code>Default</code> or <code>Redirected</code>. See <a href="#sas-logon">SAS Logon</a> section.</li>
<li><code>useComputeApi</code> - Only relevant when the serverType is <code>SASVIYA</code>. If <code>true</code> the <a href="#using-the-compute-api">Compute API</a> is used. If <code>false</code> the <a href="#using-the-jes-api">JES API</a> is used. If <code>null</code> or <code>undefined</code> the <a href="#using-jes-web-app">Web</a> approach is used.</li>
<li><code>contextName</code> - Compute context on which the requests will be called. If missing or not provided, defaults to <code>Job Execution Compute context</code>.</li>
<li><code>requestHistoryLimit</code> - Request history limit. Increasing this limit may affect browser performance, especially with debug (logs) enabled. Default is 10.</li>
</ul>
<p>The adapter supports a number of approaches for interfacing with Viya (<code>serverType</code> is <code>SASVIYA</code>). For maximum performance, be sure to <a href="https://sasjs.io/guide-viya/#shared-account-and-server-re-use">configure your compute context</a> with <code>reuseServerProcesses</code> as <code>true</code> and a system account in <code>runServerAs</code>. This functionality is available since Viya 3.5. This configuration is supported when <a href="https://sasjs.io/sasjs-cli-context/#sasjs-context-create">creating contexts using the CLI</a>.</p>
<p>The adapter supports a number of approaches for interfacing with Viya (<code>serverType</code> is <code>SASVIYA</code>). For maximum performance, be sure to <a href="https://sasjs.io/guide-viya/#shared-account-and-server-re-use">configure your compute context</a> with <code>reuseServerProcesses</code> as <code>true</code> and a system account in <code>runServerAs</code>. This functionality is available since Viya 3.5. This configuration is supported when <a href="https://sasjs.io/sasjs-cli-context/#sasjs-context-create">creating contexts using the CLI</a>.</p>
<a href="#using-jes-web-app" id="using-jes-web-app" style="color: inherit; text-decoration: none;">
<h3>Using JES Web App</h3>
</a>
<p>In this setup, all requests are routed through the JES web app, at <code>YOURSERVER/SASJobExecution?_program=/your/program</code>. This is the most reliable method, and also the slowest. One request is made to the JES app, and remaining requests (getting job uri, session spawning, passing parameters, running the program, fetching the log) are handled by the SAS server inside the JES app.</p>
<p>In this setup, all requests are routed through the JES web app, at <code>YOURSERVER/SASJobExecution?_program=/your/program</code>. This is the most reliable method, and also the slowest. One request is made to the JES app, and remaining requests (getting job uri, session spawning, passing parameters, running the program, fetching the log) are handled by the SAS server inside the JES app.</p>
<pre><code><span class="hl-0">{</span><br/><span class="hl-0"> </span><span class="hl-9">appLoc</span><span class="hl-0">:</span><span class="hl-4">&quot;/Your/Path&quot;</span><span class="hl-0">,</span><br/><span class="hl-0"> </span><span class="hl-9">serverType</span><span class="hl-0">:</span><span class="hl-4">&quot;SASVIYA&quot;</span><span class="hl-0">,</span><br/><span class="hl-0"> </span><span class="hl-9">contextName</span><span class="hl-0">: </span><span class="hl-4">&#39;yourComputeContext&#39;</span><br/><span class="hl-0">}</span>
</code></pre>
<p>Note - to use the web approach, the <code>useComputeApi</code> property must be <code>undefined</code> or <code>null</code>.</p>
@@ -267,17 +266,17 @@ ABCD,X,.
<a href="#using-the-jes-api" id="using-the-jes-api" style="color: inherit; text-decoration: none;">
<h3>Using the JES API</h3>
</a>
<p>Here we are running Jobs using the Job Execution Service except this time we are making the requests directly using the REST API instead of through the JES Web App. This is helpful when we need to call web services outside of a browser (eg with the SASjs CLI or other commandline tools). To save one network request, the adapter prefetches the JOB URIs and passes them in the <code>__job</code> parameter. Depending on your network bandwidth, it may or may not be faster than the JES Web approach.</p>
<p>Here we are running Jobs using the Job Execution Service except this time we are making the requests directly using the REST API instead of through the JES Web App. This is helpful when we need to call web services outside of a browser (eg with the SASjs CLI or other commandline tools). To save one network request, the adapter prefetches the JOB URIs and passes them in the <code>__job</code> parameter. Depending on your network bandwidth, it may or may not be faster than the JES Web approach.</p>
<p>This approach (<code>useComputeApi: false</code>) also ensures that jobs are displayed in Environment Manager.</p>
<pre><code class="language-json"><span class="hl-0">{</span><br/><span class="hl-0"> </span><span class="hl-10">appLoc</span><span class="hl-0">:</span><span class="hl-4">&quot;/Your/Path&quot;</span><span class="hl-0">,</span><br/><span class="hl-0"> </span><span class="hl-10">serverType</span><span class="hl-0">:</span><span class="hl-4">&quot;SASVIYA&quot;</span><span class="hl-0">,</span><br/><span class="hl-0"> </span><span class="hl-10">useComputeApi</span><span class="hl-0">: </span><span class="hl-1">false</span><span class="hl-0">,</span><br/><span class="hl-0"> </span><span class="hl-10">contextName</span><span class="hl-0">: </span><span class="hl-10">&#39;yourComputeContext&#39;</span><br/><span class="hl-0">}</span>
<pre><code class="language-json"><span class="hl-0">{</span><br/><span class="hl-0"> </span><span class="hl-10">&quot;appLoc&quot;</span><span class="hl-0">: </span><span class="hl-4">&quot;/Your/Path&quot;</span><span class="hl-0">,</span><br/><span class="hl-0"> </span><span class="hl-10">&quot;serverType&quot;</span><span class="hl-0">: </span><span class="hl-4">&quot;SASVIYA&quot;</span><span class="hl-0">,</span><br/><span class="hl-0"> </span><span class="hl-10">&quot;useComputeApi&quot;</span><span class="hl-0">: </span><span class="hl-1">false</span><span class="hl-0">,</span><br/><span class="hl-0"> </span><span class="hl-10">&quot;contextName&quot;</span><span class="hl-0">: </span><span class="hl-4">&quot;yourComputeContext&quot;</span><br/><span class="hl-0">}</span>
</code></pre>
<a href="#using-the-compute-api" id="using-the-compute-api" style="color: inherit; text-decoration: none;">
<h3>Using the Compute API</h3>
</a>
<p>This approach is by far the fastest, as a result of the optimisations we have built into the adapter. With this configuration, in the first sasjs request, we take a URI map of the services in the target folder, and create a session manager. This manager will spawn a additional session every time a request is made. Subsequent requests will use the existing &#39;hot&#39; session, if it exists. Sessions are always deleted after every use, which actually makes this <em>less</em> resource intensive than a typical JES web app, in which all sessions are kept alive by default for 15 minutes.</p>
<p>This approach is by far the fastest, as a result of the optimisations we have built into the adapter. With this configuration, in the first sasjs request, we take a URI map of the services in the target folder, and create a session manager. This manager will spawn a additional session every time a request is made. Subsequent requests will use the existing &#39;hot&#39; session, if it exists. Sessions are always deleted after every use, which actually makes this <em>less</em> resource intensive than a typical JES web app, in which all sessions are kept alive by default for 15 minutes.</p>
<p>With this approach (<code>useComputeApi: true</code>), the requests/logs will <em>not</em> appear in the list in Environment manager.</p>
<pre><code class="language-json"><span class="hl-0">{</span><br/><span class="hl-0"> </span><span class="hl-10">appLoc</span><span class="hl-0">:</span><span class="hl-4">&quot;/Your/Path&quot;</span><span class="hl-0">,</span><br/><span class="hl-0"> </span><span class="hl-10">serverType</span><span class="hl-0">:</span><span class="hl-4">&quot;SASVIYA&quot;</span><span class="hl-0">,</span><br/><span class="hl-0"> </span><span class="hl-10">useComputeApi</span><span class="hl-0">: </span><span class="hl-1">true</span><span class="hl-0">,</span><br/><span class="hl-0"> </span><span class="hl-10">contextName</span><span class="hl-0">: </span><span class="hl-4">&quot;yourComputeContext&quot;</span><br/><span class="hl-0">}</span>
<pre><code class="language-json"><span class="hl-0">{</span><br/><span class="hl-0"> </span><span class="hl-10">&quot;appLoc&quot;</span><span class="hl-0">: </span><span class="hl-4">&quot;/Your/Path&quot;</span><span class="hl-0">,</span><br/><span class="hl-0"> </span><span class="hl-10">&quot;serverType&quot;</span><span class="hl-0">: </span><span class="hl-4">&quot;SASVIYA&quot;</span><span class="hl-0">,</span><br/><span class="hl-0"> </span><span class="hl-10">&quot;useComputeApi&quot;</span><span class="hl-0">: </span><span class="hl-1">true</span><span class="hl-0">,</span><br/><span class="hl-0"> </span><span class="hl-10">&quot;contextName&quot;</span><span class="hl-0">: </span><span class="hl-4">&quot;yourComputeContext&quot;</span><br/><span class="hl-0">}</span>
</code></pre>
<a href="#more-resources" id="more-resources" style="color: inherit; text-decoration: none;">
@@ -297,6 +296,7 @@ ABCD,X,.
<h2>Contributors ✨</h2>
</a>
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
<p><a href="#contributors-"><img src="https://img.shields.io/badge/all_contributors-9-orange.svg?style=flat-square" alt="All Contributors"></a></p>
<!-- ALL-CONTRIBUTORS-BADGE:END -->