1 | # HTML5 Data Adapter for SAS® (H54S)
|
2 | [](https://badge.fury.io/js/h54s)
|
3 | [](https://packagephobia.now.sh/result?p=h54s)
|
4 | [](https://img.shields.io/npm/dm/h54s)
|
5 | [](https://gitter.im/Boemska/h54s?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
6 |
|
7 |
|
8 | ## What is H54S?
|
9 |
|
10 | H54S facilitates and manages bi-directional communication between JavaScript based HTML5 Web Applications (Single Page Web Applications, Progressive Web Apps) and back-end services written in SAS that execute on either SAS Viya or SAS v9. The library aims to facilitate communication between Javascript-based UI developers and SAS developers, enabling them to build and deploy secure, production ready Web Applications with as little friction as possible.
|
11 |
|
12 |
|
13 | ## Quick Start
|
14 |
|
15 | This repository contains the **core H54S JavaScript library**. If you understand what this does and just want to start creating an App, we highly recommend that you head over to our our **[Create SAS App repository](https://github.com/boemska/create-sas-app)** for a choice of pre-integrated Create React App-based template applications that will make your development much, much easier.
|
16 |
|
17 |
|
18 | #### Server Requirements
|
19 |
|
20 | An instance of either:
|
21 |
|
22 | - SAS Viya (3.4 or later, full deployment); or
|
23 | - SAS v9 Platform (v9.4) with Integration Technologies and a SAS Web Tier
|
24 |
|
25 |
|
26 | #### Client Requirements
|
27 |
|
28 | - A modern Web Browser (Chrome, Firefox, Safari, IE11+)
|
29 |
|
30 | Google Chrome or Firefox are strongly recommended. For development, having Git and Node installed is also very useful.
|
31 |
|
32 |
|
33 | ## Why is it called H54S?
|
34 |
|
35 | It started out as an abbreviation of 'HTML5 4 SAS'. Marketing isn't our strong point. We know it sounds like a strain of Bird Flu, but the project has been active under this name for a few years now so we're sticking to it. It's _almost_ memorable now.
|
36 |
|
37 |
|
38 | ## Great. How do I get started?
|
39 |
|
40 | Using [git](https://git-scm.com/), clone this repository to somewhere local:
|
41 |
|
42 | ```
|
43 | git clone https://github.com/Boemska/h54s
|
44 | ```
|
45 |
|
46 | Then if you're a SAS developer, put your SAS hat on, and follow the instructions according which flavour of SAS you're working with.
|
47 |
|
48 | ## SAS Back End
|
49 |
|
50 | _Note: You may notice that while the process differs, the code is exactly the same for both SAS Viya and SAS v9. **The design of H54S ensures that all applications built with it are portable between SAS v9 and SAS Viya, with no changes in code required to deploy or promote applications across the two platforms**_
|
51 |
|
52 |
|
53 | 1. Copy the `sasautos` directory to your SAS server. **On Viya** this is your Compute Server node, **on SAS v9** this is your Application Server context (e.g. SASApp) compute node. In this example we copied it to `/pub/apps/h54s/sasautos` on the compute node filesystem.
|
54 |
|
55 | 2. Register a new back-end code object. **On Viya** this is a File of type Job Definition, and can be registered through the SASJobExecution WebApp (`https://[yourViyaServer]/SASJobExecution/`). **On SAS v9** this is a Stored Process and can be registered through SAS Management Console or Enterprise Guide. In both cases you'll be registering the code object to a SAS folder that you have permission to write to. In both Viya and v9, I created mine in my user's `My Folder` location ("chris") and called it `myFirstService`:
|
56 |
|
57 | 3. Edit the code for the newly registered code object, and register the following code:
|
58 |
|
59 | ```sas
|
60 | * get H54s (from wherever you placed it in step 1) ;
|
61 | %include '/pub/apps/h54s/sasautos/h54s.sas';
|
62 |
|
63 | * Process and receive datasets from the client ;
|
64 | %bafgetdatasets();
|
65 |
|
66 | * Do some SAS. Can be Anything. Just get some data;
|
67 | data mydata;
|
68 | set sashelp.class;
|
69 | run;
|
70 |
|
71 | proc sort data=mydata;
|
72 | by name;
|
73 | run;
|
74 |
|
75 | * Return a resulting dataset to the client ;
|
76 | %bafheader()
|
77 | %bafOutDataset(processed, work, myData)
|
78 | %bafFooter()
|
79 | ```
|
80 |
|
81 | 4. Configure the output type for your newly registered code object.
|
82 |
|
83 | **On Viya**, right click on the job name and select properties. From the properties menu select "Parameters". Add the following parameter and then click save:
|
84 | * Name: `_output_type`
|
85 | * Default value: `html`
|
86 | * Field type: `Character`
|
87 | * Required: `false`
|
88 |
|
89 | **On SAS v9**, make sure you enable Streaming Output as the output type. If you are using Enterprise Guide to do this, also be sure to check "Global Macro Variables" and uncheck "Include STP Macros" under the "Include code for" dropdown.
|
90 |
|
91 | 5. Execute the newly registered code. **On Viya** do this through the same SASJobExecution WebApp, by right clicking on the Job and selecting "Submit job". **On SAS v9** do this through the Stored Process WebApp, by logging on to [yourserver]/SASStoredProcess/, locating the job in the UI and clicking on it.
|
92 |
|
93 | In both cases, you should see output similar to the following:
|
94 |
|
95 | ```json
|
96 | { "processed" : [{"Name":"Alfred","Sex":"M","Age":14,"Height":69,"Weight":112.5},{"Name":"Alice","Sex":"F","Age":13,"Height":56.5,"Weight":84},{"Name":"Barbara","Sex":"F","Age":13,"Height":65.3,"Weight":98},{"Name":"Carol","Sex":"F","Age":14,"Height":62.8,"Weight":102.5},{"Name":"Henry","Sex":"M","Age":14,"Height":63.5,"Weight":102.5},{"Name":"James","Sex":"M","Age":12,"Height":57.3,"Weight":83},{"Name":"Jane","Sex":"F","Age":12,"Height":59.8,"Weight":84.5},{"Name":"Janet","Sex":"F","Age":15,"Height":62.5,"Weight":112.5},{"Name":"Jeffrey","Sex":"M","Age":13,"Height":62.5,"Weight":84},{"Name":"John","Sex":"M","Age":12,"Height":59,"Weight":99.5},{"Name":"Joyce","Sex":"F","Age":11,"Height":51.3,"Weight":50.5},{"Name":"Judy","Sex":"F","Age":14,"Height":64.3,"Weight":90},{"Name":"Louise","Sex":"F","Age":12,"Height":56.3,"Weight":77},{"Name":"Mary","Sex":"F","Age":15,"Height":66.5,"Weight":112},{"Name":"Philip","Sex":"M","Age":16,"Height":72,"Weight":150},{"Name":"Robert","Sex":"M","Age":12,"Height":64.8,"Weight":128},{"Name":"Ronald","Sex":"M","Age":15,"Height":67,"Weight":133},{"Name":"Thomas","Sex":"M","Age":11,"Height":57.5,"Weight":85},{"Name":"William","Sex":"M","Age":15,"Height":66.5,"Weight":112}], "usermessage" : "blank", "logmessage" : "blank", "requestingUser" : "chris", "requestingPerson" : "Chris", "executingPid" : 1054, "sasDatetime" : 1906323243.9 , "status" : "success"}
|
97 | ```
|
98 |
|
99 | This is good enough for now. Time for some Front End Development.
|
100 |
|
101 |
|
102 |
|
103 | ## HTML5 Front End
|
104 |
|
105 | ### Vanilla Javascript
|
106 |
|
107 | This is the most basic approach. Assuming that you have a local Web Server installed for development:
|
108 |
|
109 | 1. Create an `index.html` or start a new project in your chosen IDE.
|
110 |
|
111 | 2. Copy the `/dist/h54s.js` file to your project and include it. Your `index.html` might look like this:
|
112 |
|
113 | ```html
|
114 | <!DOCTYPE html>
|
115 | <html>
|
116 | <body>
|
117 | <script src="h54s.js"></script>
|
118 | <h1>Look Ma, Front End!</h1>
|
119 | </body>
|
120 | </html>
|
121 | ```
|
122 |
|
123 | For IE, you may need to add `<meta http-equiv="X-UA-Compatible" content="IE=edge;" />`.
|
124 |
|
125 | 3. *If you are hosting your index.html and project files from within a deployed static.war, or behind the same reverse proxy as your SPWA, you don't need this step. Otherwise, for most people:*
|
126 |
|
127 | Fire up your browser. This is where Chrome comes in handy, as it allows developers to disable [Same-Origin Policy](https://en.wikipedia.org/wiki/Same-origin_policy). To tell your browser to allow background requests to non-local pages while you develop, you need to start Chrome with the `--disable-web-security` command line flag. For example, on Mac OS, first close Chrome and run the following in the Terminal: `open /Applications/Google\ Chrome.app --args --disable-web-security`
|
128 | When you see this warning, you're in business:
|
129 |
|
130 | 
|
131 |
|
132 | 3. Load your `index.html` page, Open Chrome Developer Tools (F12), Open the Console tab.
|
133 |
|
134 | 4. Create an instance of the adapter. In the console, try typing `h5`... Chrome should autocomplete to `h54s`, meaning the script is sourced correctly.
|
135 |
|
136 | Assuming your SAS webapp URIs are the default `SASStoredProcess` and `SASLogon`, the following should be enough to get you started:
|
137 |
|
138 | ```javascript
|
139 | // Instantiate adapter. If SPWA was located at
|
140 | // http://myServer:7980/SASStoredProcess/, you would do a
|
141 | var adapter = new h54s({hostUrl: 'http://myServer:7980'});
|
142 |
|
143 | // then create a dataset to send to SAS, which in JS is an
|
144 | // object array that looks a bit like this
|
145 | var myFirstTable = [
|
146 | { name: 'Abdul', sex: 'M', weight: 101.1 },
|
147 | { name: 'Jane', sex: 'F', weight: 133.7 }
|
148 | ];
|
149 |
|
150 | // add it to a h54s SasData object
|
151 | var data = new h54s.SasData(myFirstTable, 'datain');
|
152 |
|
153 | // make your first call to SAS
|
154 | adapter.call('/User Folders/Christopher Blake/My Folder/myFirstService', data, function(err, res) {
|
155 | if(err) {
|
156 | //Houston we have a problem
|
157 | console.log(err);
|
158 | } else {
|
159 | //res is an object returned from the server
|
160 | console.log(res);
|
161 | }
|
162 | });
|
163 | ```
|
164 | If you're logged into your SPWA and have a session cookie already, you should see this:
|
165 |
|
166 | 
|
167 |
|
168 | Otherwise, if you're not logged in yet, you should see this:
|
169 |
|
170 | 
|
171 |
|
172 | The easiest thing to do at this point is to log into your SPWA in another tab, refresh your page and try running the code again. However, if you're feeling adventurous you could skip ahead and try this in the console:
|
173 |
|
174 | ```javascript
|
175 | adapter.login('mysasusername','mysaspassword'); // More on this later
|
176 | ```
|
177 |
|
178 | Any queued `adapter.call()` calls should resume after a successful `adapter.login()`.
|
179 |
|
180 | ### What just happened? What did I do?
|
181 |
|
182 | First, we registered a SAS program as either an STP or Job as a back-end service. When the "service" is called the program would do some SAS-based stuff (which given the power and flexibility of SAS could have been anything, from a secured lookup into a legacy mainframe-based system so you can pre-populate a form, to an on-the-fly Hadoop query built into your app). For this example, we just told it to select records from the good old `SASHELP.CLASS` into a new temporary dataset called `WORK.MYDATA`, sort it, and return the resulting dataset to the client as an object array called `processed`.
|
183 |
|
184 | Then, from the Web side, we started a new project by creating an `index.html` page which sources the client-side `h54s.js` script. We then used the Chrome Dev Console to run some JavaScript code - to create a configured instance of the h54s Adapter, create a sample dataset, attach that dataset to a call to SAS as `datain`, fire it over, and use a simple function to either show us the dataset that was returned by SAS as `processed`, or have a look at any errors that might have occured.
|
185 |
|
186 | Easy, right? Want to know more, read our [docs](https://github.com/Boemska/h54s/wiki)
|
187 |
|
188 | ## Development and Testing of JS adapter code
|
189 |
|
190 | We love contributions! If you'd like to get involved, check out the [build instructions](CONTRIBUTIONS.md).
|
191 |
|
192 |
|
193 | ## Any questions or comments? Come join the chat. [](https://gitter.im/Boemska/h54s?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
194 |
|
195 |
|
196 | ## License
|
197 |
|
198 | This work is dual-licensed under Apache 2.0 and GPL 3.0 (or any later version).
|
199 | You can choose between one of them if you use this work.
|
200 |
|
201 | `SPDX-License-Identifier: Apache-2.0 OR GPL-3.0-or-later` |
\ | No newline at end of file |