{"id":41824596,"url":"https://github.com/sasjs/adapter","last_synced_at":"2026-01-25T08:06:59.204Z","repository":{"id":37207112,"uuid":"277894695","full_name":"sasjs/adapter","owner":"sasjs","description":"An adapter for bidirectional SAS® \u003c-\u003e Javascript communication","archived":false,"fork":false,"pushed_at":"2025-12-12T16:54:11.000Z","size":13504,"stargazers_count":41,"open_issues_count":24,"forks_count":3,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-12-14T05:14:00.695Z","etag":null,"topics":["sas","sasjs","viya"],"latest_commit_sha":null,"homepage":"https://adapter.sasjs.io","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sasjs.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":".github/CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":".github/CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2020-07-07T18:36:05.000Z","updated_at":"2025-11-25T09:02:53.000Z","dependencies_parsed_at":"2024-06-18T22:32:12.706Z","dependency_job_id":"b5033e38-d2ca-48e6-9edc-bb8ab82884bb","html_url":"https://github.com/sasjs/adapter","commit_stats":{"total_commits":1038,"total_committers":19,"mean_commits":54.63157894736842,"dds":0.7909441233140655,"last_synced_commit":"da7579a2bb3421c421775fde8399defc647d24f5"},"previous_names":[],"tags_count":252,"template":false,"template_full_name":null,"purl":"pkg:github/sasjs/adapter","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sasjs%2Fadapter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sasjs%2Fadapter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sasjs%2Fadapter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sasjs%2Fadapter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sasjs","download_url":"https://codeload.github.com/sasjs/adapter/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sasjs%2Fadapter/sbom","scorecard":{"id":728022,"data":{"date":"2025-08-11","repo":{"name":"github.com/sasjs/adapter","commit":"8a10c229d63af1a1095dd90175fc502c2ddd296a"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":5,"checks":[{"name":"Code-Review","score":10,"reason":"all changesets reviewed","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Maintained","score":10,"reason":"13 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/assign-reviewer.yml:1","Warn: no topLevel permission defined: .github/workflows/build-unit-tests.yml:1","Warn: no topLevel permission defined: .github/workflows/generateDocs.yml:1","Warn: no topLevel permission defined: .github/workflows/npmpublish.yml:1","Warn: no topLevel permission defined: .github/workflows/server-tests.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Pinned-Dependencies","score":2,"reason":"dependency not pinned by hash detected -- score normalized to 2","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/assign-reviewer.yml:10: update your workflow using https://app.stepsecurity.io/secureworkflow/sasjs/adapter/assign-reviewer.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/assign-reviewer.yml:11: update your workflow using https://app.stepsecurity.io/secureworkflow/sasjs/adapter/assign-reviewer.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build-unit-tests.yml:18: update your workflow using https://app.stepsecurity.io/secureworkflow/sasjs/adapter/build-unit-tests.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build-unit-tests.yml:20: update your workflow using https://app.stepsecurity.io/secureworkflow/sasjs/adapter/build-unit-tests.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build-unit-tests.yml:26: update your workflow using https://app.stepsecurity.io/secureworkflow/sasjs/adapter/build-unit-tests.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/build-unit-tests.yml:56: update your workflow using https://app.stepsecurity.io/secureworkflow/sasjs/adapter/build-unit-tests.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/generateDocs.yml:18: update your workflow using https://app.stepsecurity.io/secureworkflow/sasjs/adapter/generateDocs.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/generateDocs.yml:21: update your workflow using https://app.stepsecurity.io/secureworkflow/sasjs/adapter/generateDocs.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/generateDocs.yml:27: update your workflow using https://app.stepsecurity.io/secureworkflow/sasjs/adapter/generateDocs.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/generateDocs.yml:47: update your workflow using https://app.stepsecurity.io/secureworkflow/sasjs/adapter/generateDocs.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/npmpublish.yml:20: update your workflow using https://app.stepsecurity.io/secureworkflow/sasjs/adapter/npmpublish.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/npmpublish.yml:22: update your workflow using https://app.stepsecurity.io/secureworkflow/sasjs/adapter/npmpublish.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/npmpublish.yml:28: update your workflow using https://app.stepsecurity.io/secureworkflow/sasjs/adapter/npmpublish.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/npmpublish.yml:46: update your workflow using https://app.stepsecurity.io/secureworkflow/sasjs/adapter/npmpublish.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/server-tests.yml:18: update your workflow using https://app.stepsecurity.io/secureworkflow/sasjs/adapter/server-tests.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/server-tests.yml:20: update your workflow using https://app.stepsecurity.io/secureworkflow/sasjs/adapter/server-tests.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/server-tests.yml:26: update your workflow using https://app.stepsecurity.io/secureworkflow/sasjs/adapter/server-tests.yml/master?enable=pin","Warn: npmCommand not pinned by hash: .github/workflows/build-unit-tests.yml:42","Warn: npmCommand not pinned by hash: .github/workflows/server-tests.yml:39","Warn: npmCommand not pinned by hash: .github/workflows/server-tests.yml:76","Warn: npmCommand not pinned by hash: .github/workflows/server-tests.yml:82","Warn: npmCommand not pinned by hash: .github/workflows/server-tests.yml:85","Info:   0 out of  13 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   4 third-party GitHubAction dependencies pinned","Info:   4 out of   9 npmCommand dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 30 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":0,"reason":"54 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-968p-4wvh-cqc8","Warn: Project is vulnerable to: GHSA-p8p7-x288-28g6","Warn: Project is vulnerable to: GHSA-h5c3-5r3r-rr8q","Warn: Project is vulnerable to: GHSA-rmvr-2pp2-xj38","Warn: Project is vulnerable to: GHSA-xx4v-prfh-6cgc","Warn: Project is vulnerable to: GHSA-qwcr-r2fm-qrc7","Warn: Project is vulnerable to: GHSA-v6h2-p8h4-qcjw","Warn: Project is vulnerable to: GHSA-pxg6-pf52-xh8x","Warn: Project is vulnerable to: GHSA-rv95-896h-c2vc","Warn: Project is vulnerable to: GHSA-qw6h-vgh9-j6wx","Warn: Project is vulnerable to: GHSA-fjxv-7rqg-78g4","Warn: Project is vulnerable to: GHSA-78xj-cgh5-2h22","Warn: Project is vulnerable to: GHSA-2p57-rm9w-gvfp","Warn: Project is vulnerable to: GHSA-9wv6-86v2-598j","Warn: Project is vulnerable to: GHSA-rhx6-c78j-4q9w","Warn: Project is vulnerable to: GHSA-h7cp-r72f-jxh6","Warn: Project is vulnerable to: GHSA-v62p-rq8g-8h59","Warn: Project is vulnerable to: GHSA-c2qf-rxjj-qqgw","Warn: Project is vulnerable to: GHSA-m6fv-jmcg-4jfg","Warn: Project is vulnerable to: GHSA-cm22-4g7w-348p","Warn: Project is vulnerable to: GHSA-f5x3-32g6-xq36","Warn: Project is vulnerable to: GHSA-52f5-9888-hmc6","Warn: Project is vulnerable to: GHSA-4vvj-4cpr-p986","Warn: Project is vulnerable to: GHSA-whgm-jr23-g3j9","Warn: Project is vulnerable to: GHSA-jr5f-v2jv-69x6","Warn: Project is vulnerable to: GHSA-grv7-fg5c-xmjg","Warn: Project is vulnerable to: GHSA-w8qv-6jwh-64r5","Warn: Project is vulnerable to: GHSA-3xgq-45jj-v275","Warn: Project is vulnerable to: GHSA-phwq-j96m-2c2q","Warn: Project is vulnerable to: GHSA-ghr5-ch3p-vcr6","Warn: Project is vulnerable to: GHSA-c7qv-q95q-8v27","Warn: Project is vulnerable to: GHSA-33f9-j839-rf8h","Warn: Project is vulnerable to: GHSA-c36v-fmgq-m8hx","Warn: Project is vulnerable to: GHSA-76p3-8jx3-jpfq","Warn: Project is vulnerable to: GHSA-3rfm-jhwj-7488","Warn: Project is vulnerable to: GHSA-hhq3-ff78-jv3g","Warn: Project is vulnerable to: GHSA-35jh-r3h4-6jhm","Warn: Project is vulnerable to: GHSA-952p-6rrq-rcjv","Warn: Project is vulnerable to: GHSA-f8q6-p94x-37v3","Warn: Project is vulnerable to: GHSA-5rrq-pxf6-6jx5","Warn: Project is vulnerable to: GHSA-8fr3-hfg3-gpgp","Warn: Project is vulnerable to: GHSA-gf8q-jrpm-jvxq","Warn: Project is vulnerable to: GHSA-2r2c-g63r-vccr","Warn: Project is vulnerable to: GHSA-cfm4-qjh2-4765","Warn: Project is vulnerable to: GHSA-x4jg-mjrx-434g","Warn: Project is vulnerable to: GHSA-rp65-9cf3-cjxr","Warn: Project is vulnerable to: GHSA-76c9-3jph-rj3q","Warn: Project is vulnerable to: GHSA-7fh5-64p2-3v2j","Warn: Project is vulnerable to: GHSA-x7hr-w5r2-h6wg","Warn: Project is vulnerable to: GHSA-gcx4-mw62-g8wm","Warn: Project is vulnerable to: GHSA-g4rg-993r-mgx7","Warn: Project is vulnerable to: GHSA-wr3j-pwj9-hqq6","Warn: Project is vulnerable to: GHSA-4v9v-hfq4-rm2v","Warn: Project is vulnerable to: GHSA-9jgg-88mc-972h"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-22T13:28:00.596Z","repository_id":37207112,"created_at":"2025-08-22T13:28:00.596Z","updated_at":"2025-08-22T13:28:00.596Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28748573,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-25T07:58:02.558Z","status":"ssl_error","status_checked_at":"2026-01-25T07:57:57.153Z","response_time":113,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["sas","sasjs","viya"],"created_at":"2026-01-25T08:06:59.129Z","updated_at":"2026-01-25T08:06:59.182Z","avatar_url":"https://github.com/sasjs.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# @sasjs/adapter\n\n[![npm package][npm-image]][npm-url]\n[![Github Workflow][githubworkflow-image]][githubworkflow-url]\n[![npm](https://img.shields.io/npm/dt/@sasjs/adapter)]()\n![GitHub License](https://img.shields.io/github/license/sasjs/adapter)\n![GitHub top language](https://img.shields.io/github/languages/top/sasjs/adapter)\n![GitHub issues](https://img.shields.io/github/issues/sasjs/adapter)\n[![Gitpod ready-to-code](https://img.shields.io/badge/Gitpod-ready--to--code-908a85?logo=gitpod)](https://gitpod.io/#https://github.com/sasjs/adapter)\n\n[npm-image]: https://img.shields.io/npm/v/@sasjs/adapter.svg\n[npm-url]: http://npmjs.org/package/@sasjs/adapter\n[githubworkflow-image]: https://github.com/sasjs/adapter/actions/workflows/build-unit-tests.yml/badge.svg\n[githubworkflow-url]: https://github.com/sasjs/adapter/blob/main/.github/workflows/build.yml\n[dependency-image]: https://david-dm.org/sasjs/adapter.svg\n\nSASjs is a open-source framework for building Web Apps on SAS® platforms. You can use as much or as little of it as you like. This repository contains the JS adapter, the part that handles the to/from SAS communication on the client side. There are 3 ways to install it:\n\n1 - `npm install @sasjs/adapter` - for use in a nodeJS project (recommended)\n\n2 - [Download](https://cdn.jsdelivr.net/npm/@sasjs/adapter@4/index.min.js) and use a copy of the latest JS file\n\n3 - Reference directly from the CDN - in which case click [here](https://www.jsdelivr.com/package/npm/@sasjs/adapter?tab=collection) and select \"SRI\" to get the script tag with the integrity hash.\n\nIf you are short on time and just need to build an app quickly, then check out [this video](https://vimeo.com/393161794) and the [react-seed-app](https://github.com/sasjs/react-seed-app) which provides some boilerplate.\n\nFor more information on building web apps with SAS, check out [sasjs.io](https://sasjs.io)\n\n## None of this makes sense. How do I build an app with it?\n\nOk ok. Deploy this [example.html](https://raw.githubusercontent.com/sasjs/adapter/master/example.html) file to your web server, and update `servertype` to `SAS9`, `SASVIYA`, or `SASJS` depending on your backend.\n\nThe backend part can be deployed as follows:\n\n```sas\n%let appLoc=/Public/app/readme;  /* Metadata or Viya Folder per SASjs config */\nfilename mc url \"https://raw.githubusercontent.com/sasjs/core/main/all.sas\";\n%inc mc; /* compile macros (can also be downloaded \u0026 compiled seperately) */\nfilename ft15f001 temp;\nparmcards4;\n  %webout(FETCH) /* receive all data as SAS datasets */\n  proc sql;\n  create table areas as select make,mean(invoice) as avprice\n    from sashelp.cars\n    where type in (select type from work.fromjs)\n    group by 1;\n  %webout(OPEN)\n  %webout(OBJ,areas)\n  %webout(CLOSE)\n;;;;\n%mx_createwebservice(path=\u0026appLoc/common,name=getdata)\n```\n\nYou now have a simple web app with a backend service!\n\n## Detailed Overview\n\nThe SASjs adapter is a JS library and a set of SAS Macros that handle the communication between the frontend app and backend SAS services.\n\nThere are three parts to consider:\n\n1. JS request / response\n2. SAS inputs / outputs\n3. Configuration\n\n### JS Request / Response\n\nTo install the library you can simply run `npm i @sasjs/adapter` or include a `\u003cscript\u003e` tag with a reference to our [CDN](https://www.jsdelivr.com/package/npm/@sasjs/adapter).\n\nFull technical documentation is available [here](https://adapter.sasjs.io). The main parts are:\n\n### Instantiation\n\nThe following code will instantiate an instance of the adapter:\n\n```javascript\nlet sasJs = new SASjs.default({\n  appLoc: '/Your/SAS/Folder',\n  serverType: 'SAS9'\n})\n```\n\nIf you've installed it via NPM, you can import it as a default import like so:\n\n```js\nimport SASjs from '@sasjs/adapter'\n```\n\nYou can then instantiate it with:\n\n```js\nconst sasJs = new SASjs({your config})\n```\n\nMore on the config later.\n\n### SAS Logon\n\nAll authentication from the adapter is done against SASLogon. There are two approaches that can be taken, which are configured using the `loginMechanism` attribute of the sasJs config object (above):\n\n- `loginMechanism:'Redirected'` - 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.\n- `loginMechanism:'Default'` - this approach requires that the username and password are captured, and used within the `.login()` method. This can be helpful for development, or automated testing.\n\nSample code for logging in with the `Default` approach:\n\n```javascript\nsasJs.logIn('USERNAME','PASSWORD'\n  ).then((response) =\u003e {\n  if (response.isLoggedIn === true) {\n    console.log('do stuff')\n  } else {\n    console.log('do other stuff')\n  }\n}\n```\n\nMore examples of using authentication, and more, can be found in the [SASjs Seed Apps](https://github.com/search?q=topic%3Asasjs-app+org%3Asasjs+fork%3Atrue) on github.\n\n### Request / Response\n\nA simple request can be sent to SAS in the following fashion:\n\n```javascript\nsasJs.request('/path/to/my/service', dataObject).then((response) =\u003e {\n  // all tables are in the response object, eg:\n  console.log(response.tablewith2cols1row[0].COL1.value)\n})\n```\n\nWe supply the path to the SAS service, and a data object.\n\nIf the path starts with a `/` then it should be a full path to the service. If there is no leading `/` then it is relative to the `appLoc`.\n\nThe data object can be null (for services with no input), or can contain one or more \"tables\" in the following format:\n\n```javascript\nlet dataObject = {\n  tablewith2cols1row: [\n    {\n      col1: 'val1',\n      col2: 42\n    }\n  ],\n  tablewith1col2rows: [\n    {\n      col: 'row1'\n    },\n    {\n      col: 'row2'\n    }\n  ]\n}\n```\n\nThese tables (`tablewith2cols1row` and `tablewith1col2rows`) will be created in SAS WORK after running `%webout(FETCH)` in your SAS service.\n\nThe `request()` method also has optional parameters such as a config object and a callback login function.\n\nThe response object will contain returned tables and columns. Table names are always lowercase, and column names uppercase.\n\nThe adapter will also cache the logs (if debug enabled) and even the work tables. For performance, it is best to keep debug mode off.\n\n### Verbose Mode\n\nSet `verbose` to `true` to enable verbose mode that logs a summary of every HTTP response. Verbose mode can be disabled by calling `disableVerboseMode` method or enabled by `enableVerboseMode` method. Verbose mode also supports `bleached` mode that disables extra colors in req/res summary. To enable `bleached` verbose mode, pass `verbose` equal to `bleached` while instantiating an instance of `RequestClient` or to `setVerboseMode` method. Verbose mode can also be enabled/disabled by `startComputeJob` method.\n\n### Session Manager\n\nTo execute a script on Viya a session has to be created first which is time-consuming (~15sec). That is why a Session Manager has been created which is implementing the following logic:\n\n1. When the first session is requested, we also create one more session (hot session) for future requests. Please notice two pending POST requests to create a session within the same context: ![the first session request](./screenshots/session-manager-first-request.png)\n2. When a subsequent request for a session is received and there is a hot session available (not expired), this session is returned and an asynchronous request to create another hot session is sent. Please notice that there is a pending POST request to create a new session while a job has been already finished execution (POST request with status 201): ![subsequent session request](./screenshots/subsequent-session-request.png)\n3. When a subsequent request for a session is received and there is no available hot session, 2 requests are sent asynchronously to create a session. The first created session will be returned and another session will be reserved for future requests.\n\n### Variable Types\n\nThe SAS type (char/numeric) of the values is determined according to a set of rules:\n\n- If the values are numeric, the SAS type is numeric\n- If the values are all string, the SAS type is character\n- If the values contain a single character (a-Z + underscore + .) AND a numeric, then the SAS type is numeric (with special missing values).\n- `null` is set to either '.' or '' depending on the assigned or derived type per the above rules. If entire column is `null` then the type will be numeric.\n\nThe following table illustrates the formats applied to columns under various scenarios:\n\n| JS Values        | SAS Format |\n| ---------------- | ---------- |\n| 'a', 'a'         | $char1.    |\n| 0, '\\_'          | best.      |\n| 'Z', 0           | best.      |\n| 'a', 'aaa'       | $char3.    |\n| null, 'a', 'aaa' | $char3.    |\n| null, 'a', 0     | best.      |\n| null, null       | best.      |\n| null, ''         | $char1.    |\n| null, 'a'        | $char1.    |\n| 'a'              | $char1.    |\n| 'a', null        | $char1.    |\n| 'a', null, 0     | best.      |\n\nValidation is also performed on the values. The following combinations will throw errors:\n\n| JS Values       | SAS Format                                                 |\n| --------------- | ---------------------------------------------------------- |\n| null, 'aaaa', 0 | Error: mixed types. 'aaaa' is not a special missing value. |\n| 0, 'a', '!'     | Error: mixed types. '!' is not a special missing value     |\n| 1.1, '.', 0     | Error: mixed types. For regular nulls, use `null`          |\n\n### Variable Format Override\n\nThe auto-detect functionality above is thwarted in the following scenarios:\n\n- A character column containing only `null` values (is considered numeric)\n- A numeric column containing only special missing values (is considered character)\n\nTo 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.\n\nTo 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 `infile` statement in disguise. It looks a bit like this:\n\n```csv\nCHARVAR1:$char4. CHARVAR2:$char1. NUMVAR:best.\nLOAD,,0\nABCD,X,.\n```\n\nTo provide overrides to this header row, the tables object can be constructed as follows (with a leading '$' in the table name):\n\n```javascript\nlet specialData = {\n  tablewith2cols2rows: [\n    { col1: 'val1', specialMissingsCol: 'A' },\n    { col1: 'val2', specialMissingsCol: '_' }\n  ],\n  $tablewith2cols2rows: { formats: { specialMissingsCol: 'best.' } }\n}\n```\n\nIt is not necessary to provide formats for ALL the columns, only the ones that need to be overridden.\n\n## SAS Inputs / Outputs\n\nThe SAS side is handled by a number of macros in the [macro core](https://github.com/sasjs/core) library.\n\nThe following snippet shows the process of SAS tables arriving / leaving:\n\n```sas\n/* convert frontend input tables from into SASWORK datasets */\n%webout(FETCH)\n\n/* some sas code */\ndata a b c;\n  set from js;\nrun;\n\n%webout(OPEN)  /* Open the JSON to be returned */\n%webout(OBJ,a) /* Rows in table `a` are objects (easy to use) */\n%webout(ARR,b) /* Rows in table `b` are arrays (compact) */\n%webout(OBJ,c,fmt=N) /* Table `c` is sent unformatted (raw) */\n%webout(OBJ,c,dslabel=d) /* Rename table as `d` in output JSON */\n%webout(OBJ,c,dslabel=e, maxobs=10) /* send only 10 rows back */\n%webout(CLOSE) /* Close the JSON and add default variables */\n```\n\nBy default, special SAS numeric missings (\\_a-Z) are converted to `null` in the JSON. If you'd like to preserve these, use the `missing=STRING` option as follows:\n\n```sas\n%webout(OBJ,a,missing=STRING)\n```\n\nIn this case, special missings (such as `.a`, `.b`) are converted to javascript string values (`'A', 'B'`).\n\nWhere 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 `showmeta` param to the `webout()` macro as follows:\n\n```sas\n%webout(OBJ,a,missing=STRING,showmeta=YES)\n```\n\nThe `%webout()` macro itself is just a wrapper for the [mp_jsonout](https://core.sasjs.io/mp__jsonout_8sas.html) macro.\n\n## Configuration\n\nConfiguration 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 [here](https://github.com/sasjs/adapter/blob/master/src/types/SASjsConfig.ts). The main config items are:\n\n- `appLoc` - this is the folder (eg in metadata or SAS Drive) under which the SAS services are created.\n- `serverType` - either `SAS9`, `SASVIYA` or `SASJS`. The `SASJS` server type is for use with [sasjs/server](https://github.com/sasjs/server).\n- `serverUrl` - 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.\n- `debug` - if `true` then SAS Logs and extra debug information is returned.\n- `verbose` - optional, if `true` then a summary of every HTTP response is logged.\n- `loginMechanism` - either `Default` or `Redirected`. See [SAS Logon](#sas-logon) section.\n- `useComputeApi` - Only relevant when the serverType is `SASVIYA`. If `true` the [Compute API](#using-the-compute-api) is used. If `false` the [JES API](#using-the-jes-api) is used. If `null` or `undefined` the [Web](#using-jes-web-app) approach is used.\n- `contextName` - Compute context on which the requests will be called. If missing or not provided, defaults to `Job Execution Compute context`.\n- `requestHistoryLimit` - Request history limit. Increasing this limit may affect browser performance, especially with debug (logs) enabled. Default is 10.\n\nThe adapter supports a number of approaches for interfacing with Viya (`serverType` is `SASVIYA`). For maximum performance, be sure to [configure your compute context](https://sasjs.io/guide-viya/#shared-account-and-server-re-use) with `reuseServerProcesses` as `true` and a system account in `runServerAs`. This functionality is available since Viya 3.5. This configuration is supported when [creating contexts using the CLI](https://sasjs.io/sasjs-cli-context/#sasjs-context-create).\n\n### Using JES Web App\n\nIn this setup, all requests are routed through the JES web app, at `YOURSERVER/SASJobExecution?_program=/your/program`. 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.\n\n```\n{\n  appLoc:\"/Your/Path\",\n  serverType:\"SASVIYA\",\n  contextName: 'yourComputeContext'\n}\n```\n\nNote - to use the web approach, the `useComputeApi` property must be `undefined` or `null`.\n\n### Using the JES API\n\nHere 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 `__job` parameter. Depending on your network bandwidth, it may or may not be faster than the JES Web approach.\n\nThis approach (`useComputeApi: false`) also ensures that jobs are displayed in Environment Manager.\n\n```json\n{\n  \"appLoc\": \"/Your/Path\",\n  \"serverType\": \"SASVIYA\",\n  \"useComputeApi\": false,\n  \"contextName\": \"yourComputeContext\"\n}\n```\n\n### Using the Compute API\n\nThis 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 'hot' session, if it exists. Sessions are always deleted after every use, which actually makes this _less_ resource intensive than a typical JES web app, in which all sessions are kept alive by default for 15 minutes.\n\nWith this approach (`useComputeApi: true`), the requests/logs will _not_ appear in the list in Environment manager.\n\n```json\n{\n  \"appLoc\": \"/Your/Path\",\n  \"serverType\": \"SASVIYA\",\n  \"useComputeApi\": true,\n  \"contextName\": \"yourComputeContext\"\n}\n```\n\n# More resources\n\nFor more information and examples specific to this adapter you can check out the [user guide](https://sasjs.io/sasjs-adapter/) or the [technical](http://adapter.sasjs.io/) documentation.\n\nFor more information on building web apps in general, check out these [resources](https://sasjs.io/training/resources/) or contact the [author](https://www.linkedin.com/in/allanbowe/) directly.\n\nAs a SAS customer you can also request a copy of [Data Controller](https://datacontroller.io) - free for up to 5 users, this tool makes use of all parts of the SASjs framework.\n\n## Star Gazing\n\nIf you find this library useful, help us grow our star graph!\n\n![](https://starchart.cc/sasjs/adapter.svg)\n\n## Contributors ✨\n\n\u003c!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section --\u003e\n\n[![All Contributors](https://img.shields.io/badge/all_contributors-9-orange.svg?style=flat-square)](#contributors-)\n\n\u003c!-- ALL-CONTRIBUTORS-BADGE:END --\u003e\n\nThanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):\n\n\u003c!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section --\u003e\n\u003c!-- prettier-ignore-start --\u003e\n\u003c!-- markdownlint-disable --\u003e\n\u003ctable\u003e\n  \u003ctbody\u003e\n    \u003ctr\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://krishna-acondy.io/\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/2980428?v=4?s=100\" width=\"100px;\" alt=\"Krishna Acondy\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eKrishna Acondy\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/sasjs/adapter/commits?author=krishna-acondy\" title=\"Code\"\u003e💻\u003c/a\u003e \u003ca href=\"#infra-krishna-acondy\" title=\"Infrastructure (Hosting, Build-Tools, etc)\"\u003e🚇\u003c/a\u003e \u003ca href=\"#blog-krishna-acondy\" title=\"Blogposts\"\u003e📝\u003c/a\u003e \u003ca href=\"#content-krishna-acondy\" title=\"Content\"\u003e🖋\u003c/a\u003e \u003ca href=\"#ideas-krishna-acondy\" title=\"Ideas, Planning, \u0026 Feedback\"\u003e🤔\u003c/a\u003e \u003ca href=\"#video-krishna-acondy\" title=\"Videos\"\u003e📹\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://www.erudicat.com/\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/25773492?v=4?s=100\" width=\"100px;\" alt=\"Yury Shkoda\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eYury Shkoda\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/sasjs/adapter/commits?author=YuryShkoda\" title=\"Code\"\u003e💻\u003c/a\u003e \u003ca href=\"#infra-YuryShkoda\" title=\"Infrastructure (Hosting, Build-Tools, etc)\"\u003e🚇\u003c/a\u003e \u003ca href=\"#ideas-YuryShkoda\" title=\"Ideas, Planning, \u0026 Feedback\"\u003e🤔\u003c/a\u003e \u003ca href=\"https://github.com/sasjs/adapter/commits?author=YuryShkoda\" title=\"Tests\"\u003e⚠️\u003c/a\u003e \u003ca href=\"#video-YuryShkoda\" title=\"Videos\"\u003e📹\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/medjedovicm\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/18329105?v=4?s=100\" width=\"100px;\" alt=\"Mihajlo Medjedovic\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eMihajlo Medjedovic\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/sasjs/adapter/commits?author=medjedovicm\" title=\"Code\"\u003e💻\u003c/a\u003e \u003ca href=\"#infra-medjedovicm\" title=\"Infrastructure (Hosting, Build-Tools, etc)\"\u003e🚇\u003c/a\u003e \u003ca href=\"https://github.com/sasjs/adapter/commits?author=medjedovicm\" title=\"Tests\"\u003e⚠️\u003c/a\u003e \u003ca href=\"https://github.com/sasjs/adapter/pulls?q=is%3Apr+reviewed-by%3Amedjedovicm\" title=\"Reviewed Pull Requests\"\u003e👀\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/allanbowe\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/4420615?v=4?s=100\" width=\"100px;\" alt=\"Allan Bowe\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eAllan Bowe\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/sasjs/adapter/commits?author=allanbowe\" title=\"Code\"\u003e💻\u003c/a\u003e \u003ca href=\"https://github.com/sasjs/adapter/pulls?q=is%3Apr+reviewed-by%3Aallanbowe\" title=\"Reviewed Pull Requests\"\u003e👀\u003c/a\u003e \u003ca href=\"https://github.com/sasjs/adapter/commits?author=allanbowe\" title=\"Tests\"\u003e⚠️\u003c/a\u003e \u003ca href=\"#mentoring-allanbowe\" title=\"Mentoring\"\u003e🧑‍🏫\u003c/a\u003e \u003ca href=\"#maintenance-allanbowe\" title=\"Maintenance\"\u003e🚧\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/saadjutt01\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/8914650?v=4?s=100\" width=\"100px;\" alt=\"Muhammad Saad \"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eMuhammad Saad \u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/sasjs/adapter/commits?author=saadjutt01\" title=\"Code\"\u003e💻\u003c/a\u003e \u003ca href=\"https://github.com/sasjs/adapter/pulls?q=is%3Apr+reviewed-by%3Asaadjutt01\" title=\"Reviewed Pull Requests\"\u003e👀\u003c/a\u003e \u003ca href=\"https://github.com/sasjs/adapter/commits?author=saadjutt01\" title=\"Tests\"\u003e⚠️\u003c/a\u003e \u003ca href=\"#mentoring-saadjutt01\" title=\"Mentoring\"\u003e🧑‍🏫\u003c/a\u003e \u003ca href=\"#infra-saadjutt01\" title=\"Infrastructure (Hosting, Build-Tools, etc)\"\u003e🚇\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/sabhas\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/82647447?v=4?s=100\" width=\"100px;\" alt=\"Sabir Hassan\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eSabir Hassan\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/sasjs/adapter/commits?author=sabhas\" title=\"Code\"\u003e💻\u003c/a\u003e \u003ca href=\"https://github.com/sasjs/adapter/pulls?q=is%3Apr+reviewed-by%3Asabhas\" title=\"Reviewed Pull Requests\"\u003e👀\u003c/a\u003e \u003ca href=\"https://github.com/sasjs/adapter/commits?author=sabhas\" title=\"Tests\"\u003e⚠️\u003c/a\u003e \u003ca href=\"#ideas-sabhas\" title=\"Ideas, Planning, \u0026 Feedback\"\u003e🤔\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/VladislavParhomchik\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/83717836?v=4?s=100\" width=\"100px;\" alt=\"VladislavParhomchik\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eVladislavParhomchik\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/sasjs/adapter/commits?author=VladislavParhomchik\" title=\"Tests\"\u003e⚠️\u003c/a\u003e \u003ca href=\"https://github.com/sasjs/adapter/pulls?q=is%3Apr+reviewed-by%3AVladislavParhomchik\" title=\"Reviewed Pull Requests\"\u003e👀\u003c/a\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"http://rudvfaden.github.io/\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/2445577?v=4?s=100\" width=\"100px;\" alt=\"Rud Faden\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eRud Faden\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"#userTesting-rudvfaden\" title=\"User Testing\"\u003e📓\u003c/a\u003e \u003ca href=\"https://github.com/sasjs/adapter/commits?author=rudvfaden\" title=\"Documentation\"\u003e📖\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/saramartinelli1992\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/100193908?v=4?s=100\" width=\"100px;\" alt=\"Sara\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eSara\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"#userTesting-saramartinelli1992\" title=\"User Testing\"\u003e📓\u003c/a\u003e \u003ca href=\"#platform-saramartinelli1992\" title=\"Packaging/porting to new platform\"\u003e📦\u003c/a\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n\n\u003c!-- markdownlint-restore --\u003e\n\u003c!-- prettier-ignore-end --\u003e\n\n\u003c!-- ALL-CONTRIBUTORS-LIST:END --\u003e\n\nThis project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsasjs%2Fadapter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsasjs%2Fadapter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsasjs%2Fadapter/lists"}