mirror of
https://github.com/sasjs/adapter.git
synced 2025-12-26 23:40:06 +00:00
Compare commits
45 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3ec6ee2db9 | ||
|
|
e6ab5f918f | ||
|
|
951e119c08 | ||
|
|
d22d9e1039 | ||
|
|
6e276e2e26 | ||
|
|
eec973efa1 | ||
|
|
2c763e38ae | ||
|
|
4957bc5b05 | ||
|
|
f6b1eecb42 | ||
|
|
7ae2a4d2c6 | ||
|
|
f86d20b723 | ||
|
|
7a1cce193e | ||
|
|
05539fff11 | ||
|
|
5f74b6990c | ||
|
|
a53b1ab421 | ||
|
|
3fdc56cdfe | ||
|
|
e318d8816e | ||
|
|
2c9cce8bf8 | ||
|
|
58d69a62d6 | ||
|
|
c9c9754916 | ||
|
|
e056ca21fe | ||
|
|
0a77ebf5c5 | ||
|
|
d5791a75cd | ||
|
|
3da5aba62a | ||
|
|
12835893b1 | ||
|
|
3f40737514 | ||
|
|
df86b2e700 | ||
|
|
0eb9bc43ff | ||
|
|
5fce25d58a | ||
|
|
7ee9335183 | ||
|
|
07695bdb85 | ||
|
|
26c8946fd5 | ||
|
|
fc1d54d105 | ||
|
|
a318d61f83 | ||
|
|
cc5a0cbec3 | ||
|
|
d932d9ea0a | ||
|
|
e3edace882 | ||
|
|
29d9df5792 | ||
|
|
1f970e1102 | ||
|
|
1552762d28 | ||
|
|
ef39252b0b | ||
|
|
3f3f8f4531 | ||
|
|
33879ee998 | ||
|
|
cc8271438b | ||
|
|
a064bc086d |
@@ -1,83 +1,14 @@
|
||||
# Contributing
|
||||
|
||||
Contributions to SASjs are very welcome! When making a PR, test cases should be included. To help in unit testing, be sure to run the following when making changes:
|
||||
Contributions to SASjs are very welcome! When making a PR, test cases should be included.
|
||||
|
||||
```
|
||||
# the following creates a tarball in the build folder of SASjs
|
||||
npm run-script package:lib
|
||||
This repository contains a suite of tests built using [@sasjs/test-framework](https://github.com/sasjs/test-framework).
|
||||
|
||||
# now go to your app and run:
|
||||
npm install ../sasjs/build/<tarball filename>
|
||||
```
|
||||
Detailed instructions for creating and running the tests can be found [here](https://github.com/sasjs/adapter/blob/master/sasjs-tests/README.md).
|
||||
|
||||
Tests are run using cypress. Before running tests, you need to define the following backend services:
|
||||
If you'd like to test your changes in an app that uses the adapter, you can do so as follows:
|
||||
|
||||
# SAS 9
|
||||
|
||||
```
|
||||
|
||||
filename mc url "https://raw.githubusercontent.com/sasjs/core/main/all.sas";
|
||||
%inc mc;
|
||||
filename ft15f001 temp;
|
||||
parmcards4;
|
||||
%webout(OPEN)
|
||||
%macro x();
|
||||
%do i=1 %to &_webin_file_count; %webout(OBJ,&&_webin_name&i) %end;
|
||||
%mend; %x()
|
||||
%webout(CLOSE)
|
||||
;;;;
|
||||
%mm_createwebservice(path=/Public/app/common,name=sendObj)
|
||||
parmcards4;
|
||||
%webout(OPEN)
|
||||
%macro x();
|
||||
%do i=1 %to &_webin_file_count; %webout(ARR,&&_webin_name&i) %end;
|
||||
%mend; %x()
|
||||
%webout(CLOSE)
|
||||
;;;;
|
||||
%mm_createwebservice(path=/Public/app/common,name=sendArr)
|
||||
```
|
||||
|
||||
# Viya
|
||||
|
||||
```
|
||||
filename mc url "https://raw.githubusercontent.com/sasjs/core/main/all.sas";
|
||||
%inc mc;
|
||||
filename ft15f001 temp;
|
||||
parmcards4;
|
||||
%webout(FETCH)
|
||||
%webout(OPEN)
|
||||
%macro x();
|
||||
%do i=1 %to %sysfunc(countw(&sasjs_tables));
|
||||
%let table=%scan(&sasjs_tables,&i);
|
||||
%webout(OBJ,&table)
|
||||
%end;
|
||||
%mend;
|
||||
%x()
|
||||
%webout(CLOSE)
|
||||
;;;;
|
||||
%mp_createwebservice(path=/Public/app/common,name=sendObj)
|
||||
filename ft15f001 temp;
|
||||
parmcards4;
|
||||
%webout(FETCH)
|
||||
%webout(OPEN)
|
||||
%macro x();
|
||||
%do i=1 %to %sysfunc(countw(&sasjs_tables));
|
||||
%let table=%scan(&sasjs_tables,&i);
|
||||
%webout(ARR,&table)
|
||||
%end;
|
||||
%mend;
|
||||
%x()
|
||||
%webout(CLOSE)
|
||||
;;;;
|
||||
%mp_createwebservice(path=/Public/app/common,name=sendArr)
|
||||
filename ft15f001 temp;
|
||||
parmcards4;
|
||||
If you can keep your head when all about you
|
||||
Are losing theirs and blaming it on you,
|
||||
If you can trust yourself when all men doubt you,
|
||||
But make allowance for their doubting too;
|
||||
;;;;
|
||||
%mp_createwebservice(path=/Public/app/common,name=makeErr)
|
||||
```
|
||||
|
||||
The above services will return anything you send. To run the tests simply launch `npm run cypress`.
|
||||
1. Run `npm run package:lib` from the root folder in this repository.
|
||||
This creates a tarball in the `/build` folder.
|
||||
2. In your app's root folder, run `npm install <path/to/tarball>`.
|
||||
This will install the changed version of the adapter in your app.
|
||||
|
||||
@@ -43,6 +43,6 @@ You now have a simple web app with a backend service!
|
||||
|
||||
# More resources
|
||||
|
||||
For more information specific to this adapter you can check out this [user guide](https://sasjs.io/sasjs-adapter/) or the [technical](http://adapter.sasjs.io/) documentation.
|
||||
For 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.
|
||||
|
||||
For 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.
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
223
docs/classes/reflection-640.reflection-158.fileuploader.html
Normal file
223
docs/classes/reflection-640.reflection-158.fileuploader.html
Normal file
File diff suppressed because one or more lines are too long
296
docs/classes/reflection-640.reflection-158.sas9apiclient.html
Normal file
296
docs/classes/reflection-640.reflection-158.sas9apiclient.html
Normal file
File diff suppressed because one or more lines are too long
1038
docs/classes/reflection-640.reflection-158.sasjs.html
Normal file
1038
docs/classes/reflection-640.reflection-158.sasjs.html
Normal file
File diff suppressed because one or more lines are too long
1006
docs/classes/reflection-640.reflection-158.sasviyaapiclient.html
Normal file
1006
docs/classes/reflection-640.reflection-158.sasviyaapiclient.html
Normal file
File diff suppressed because one or more lines are too long
259
docs/classes/reflection-640.reflection-158.sessionmanager.html
Normal file
259
docs/classes/reflection-640.reflection-158.sessionmanager.html
Normal file
File diff suppressed because one or more lines are too long
223
docs/classes/reflection-641.reflection-158.fileuploader.html
Normal file
223
docs/classes/reflection-641.reflection-158.fileuploader.html
Normal file
File diff suppressed because one or more lines are too long
296
docs/classes/reflection-641.reflection-158.sas9apiclient.html
Normal file
296
docs/classes/reflection-641.reflection-158.sas9apiclient.html
Normal file
File diff suppressed because one or more lines are too long
1038
docs/classes/reflection-641.reflection-158.sasjs.html
Normal file
1038
docs/classes/reflection-641.reflection-158.sasjs.html
Normal file
File diff suppressed because one or more lines are too long
1012
docs/classes/reflection-641.reflection-158.sasviyaapiclient.html
Normal file
1012
docs/classes/reflection-641.reflection-158.sasviyaapiclient.html
Normal file
File diff suppressed because one or more lines are too long
259
docs/classes/reflection-641.reflection-158.sessionmanager.html
Normal file
259
docs/classes/reflection-641.reflection-158.sessionmanager.html
Normal file
File diff suppressed because one or more lines are too long
223
docs/classes/reflection-644.reflection-162.fileuploader.html
Normal file
223
docs/classes/reflection-644.reflection-162.fileuploader.html
Normal file
File diff suppressed because one or more lines are too long
296
docs/classes/reflection-644.reflection-162.sas9apiclient.html
Normal file
296
docs/classes/reflection-644.reflection-162.sas9apiclient.html
Normal file
File diff suppressed because one or more lines are too long
1038
docs/classes/reflection-644.reflection-162.sasjs.html
Normal file
1038
docs/classes/reflection-644.reflection-162.sasjs.html
Normal file
File diff suppressed because one or more lines are too long
1006
docs/classes/reflection-644.reflection-162.sasviyaapiclient.html
Normal file
1006
docs/classes/reflection-644.reflection-162.sasviyaapiclient.html
Normal file
File diff suppressed because one or more lines are too long
259
docs/classes/reflection-644.reflection-162.sessionmanager.html
Normal file
259
docs/classes/reflection-644.reflection-162.sessionmanager.html
Normal file
File diff suppressed because one or more lines are too long
223
docs/classes/reflection-648.reflection-166.fileuploader.html
Normal file
223
docs/classes/reflection-648.reflection-166.fileuploader.html
Normal file
File diff suppressed because one or more lines are too long
296
docs/classes/reflection-648.reflection-166.sas9apiclient.html
Normal file
296
docs/classes/reflection-648.reflection-166.sas9apiclient.html
Normal file
File diff suppressed because one or more lines are too long
1064
docs/classes/reflection-648.reflection-166.sasjs.html
Normal file
1064
docs/classes/reflection-648.reflection-166.sasjs.html
Normal file
File diff suppressed because one or more lines are too long
1006
docs/classes/reflection-648.reflection-166.sasviyaapiclient.html
Normal file
1006
docs/classes/reflection-648.reflection-166.sasviyaapiclient.html
Normal file
File diff suppressed because one or more lines are too long
259
docs/classes/reflection-648.reflection-166.sessionmanager.html
Normal file
259
docs/classes/reflection-648.reflection-166.sessionmanager.html
Normal file
File diff suppressed because one or more lines are too long
223
docs/classes/reflection-678.reflection-166.fileuploader.html
Normal file
223
docs/classes/reflection-678.reflection-166.fileuploader.html
Normal file
File diff suppressed because one or more lines are too long
296
docs/classes/reflection-678.reflection-166.sas9apiclient.html
Normal file
296
docs/classes/reflection-678.reflection-166.sas9apiclient.html
Normal file
File diff suppressed because one or more lines are too long
1170
docs/classes/reflection-678.reflection-166.sasjs.html
Normal file
1170
docs/classes/reflection-678.reflection-166.sasjs.html
Normal file
File diff suppressed because one or more lines are too long
1118
docs/classes/reflection-678.reflection-166.sasviyaapiclient.html
Normal file
1118
docs/classes/reflection-678.reflection-166.sasviyaapiclient.html
Normal file
File diff suppressed because one or more lines are too long
259
docs/classes/reflection-678.reflection-166.sessionmanager.html
Normal file
259
docs/classes/reflection-678.reflection-166.sessionmanager.html
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
106
docs/modules/reflection-640.html
Normal file
106
docs/modules/reflection-640.html
Normal file
File diff suppressed because one or more lines are too long
128
docs/modules/reflection-640.reflection-158.html
Normal file
128
docs/modules/reflection-640.reflection-158.html
Normal file
File diff suppressed because one or more lines are too long
106
docs/modules/reflection-641.html
Normal file
106
docs/modules/reflection-641.html
Normal file
File diff suppressed because one or more lines are too long
128
docs/modules/reflection-641.reflection-158.html
Normal file
128
docs/modules/reflection-641.reflection-158.html
Normal file
File diff suppressed because one or more lines are too long
106
docs/modules/reflection-644.html
Normal file
106
docs/modules/reflection-644.html
Normal file
File diff suppressed because one or more lines are too long
128
docs/modules/reflection-644.reflection-162.html
Normal file
128
docs/modules/reflection-644.reflection-162.html
Normal file
File diff suppressed because one or more lines are too long
106
docs/modules/reflection-648.html
Normal file
106
docs/modules/reflection-648.html
Normal file
File diff suppressed because one or more lines are too long
128
docs/modules/reflection-648.reflection-166.html
Normal file
128
docs/modules/reflection-648.reflection-166.html
Normal file
File diff suppressed because one or more lines are too long
106
docs/modules/reflection-678.html
Normal file
106
docs/modules/reflection-678.html
Normal file
File diff suppressed because one or more lines are too long
128
docs/modules/reflection-678.reflection-166.html
Normal file
128
docs/modules/reflection-678.reflection-166.html
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
18
package-lock.json
generated
18
package-lock.json
generated
@@ -1103,9 +1103,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"supports-color": {
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
|
||||
"integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
|
||||
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"has-flag": "^4.0.0"
|
||||
@@ -1648,9 +1648,9 @@
|
||||
}
|
||||
},
|
||||
"@types/jest": {
|
||||
"version": "26.0.10",
|
||||
"resolved": "https://registry.npmjs.org/@types/jest/-/jest-26.0.10.tgz",
|
||||
"integrity": "sha512-i2m0oyh8w/Lum7wWK/YOZJakYF8Mx08UaKA1CtbmFeDquVhAEdA7znacsVSf2hJ1OQ/OfVMGN90pw/AtzF8s/Q==",
|
||||
"version": "26.0.13",
|
||||
"resolved": "https://registry.npmjs.org/@types/jest/-/jest-26.0.13.tgz",
|
||||
"integrity": "sha512-sCzjKow4z9LILc6DhBvn5AkIfmQzDZkgtVVKmGwVrs5tuid38ws281D4l+7x1kP487+FlKDh5kfMZ8WSPAdmdA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"jest-diff": "^25.2.1",
|
||||
@@ -5904,9 +5904,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"supports-color": {
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
|
||||
"integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
|
||||
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"has-flag": "^4.0.0"
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
"license": "ISC",
|
||||
"devDependencies": {
|
||||
"@types/isomorphic-fetch": "0.0.35",
|
||||
"@types/jest": "^26.0.10",
|
||||
"@types/jest": "^26.0.13",
|
||||
"cp": "^0.2.0",
|
||||
"jest": "^25.5.4",
|
||||
"path": "^0.12.7",
|
||||
|
||||
@@ -1,68 +1,139 @@
|
||||
This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
|
||||
`sasjs-tests` is a test suite for the SASjs adapter.
|
||||
|
||||
## Available Scripts
|
||||
It is a React app bootstrapped using [Create React App](https://github.com/facebook/create-react-app) and [@sasjs/test-framework](https://github.com/sasjs/test-framework).
|
||||
|
||||
In the project directory, you can run:
|
||||
When developing on `@sasjs/adapter`, it's good practice to run the test suite against your changed version of the adapter to ensure that existing functionality has not been impacted.
|
||||
|
||||
### `npm start`
|
||||
You can use the provided `update:adapter` NPM script for this.
|
||||
|
||||
Runs the app in the development mode.<br />
|
||||
Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
|
||||
```
|
||||
npm run update:adapter
|
||||
```
|
||||
|
||||
The page will reload if you make edits.<br />
|
||||
You will also see any lint errors in the console.
|
||||
This scripts builds a new version of the adapter and installs it in the `sasjs-tests` project.
|
||||
|
||||
### `npm test`
|
||||
## Running tests
|
||||
|
||||
Launches the test runner in the interactive watch mode.<br />
|
||||
See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
|
||||
There are three prerequisites to be able to run the tests:
|
||||
|
||||
### `npm run build`
|
||||
1. Correct server configuration for the SASjs adapter.
|
||||
2. `sasjs-tests` deployed to your SAS server.
|
||||
3. The required SAS services created on the same server.
|
||||
|
||||
Builds the app for production to the `build` folder.<br />
|
||||
It correctly bundles React in production mode and optimizes the build for the best performance.
|
||||
### 1. Configuring the SASjs adapter
|
||||
|
||||
The build is minified and the filenames include the hashes.<br />
|
||||
Your app is ready to be deployed!
|
||||
There is a `config.json` file in the `/public` folder which specifies the configuration for the SASjs adapter. You can set the values within the `sasjsConfig` property in this file to match your SAS server configuration.
|
||||
|
||||
See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
|
||||
### 2. Deploying to your SAS server
|
||||
|
||||
### `npm run eject`
|
||||
There is a `deploy` NPM script provided in the `sasjs-tests` project's `package.json`.
|
||||
|
||||
**Note: this is a one-way operation. Once you `eject`, you can’t go back!**
|
||||
It updates `sasjs-tests` to use the latest version of the adapter, and deploys to a specified server via SSH using the `rsync` command.
|
||||
|
||||
If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
|
||||
To be able to run the `deploy` script, two environment variables need to be set:
|
||||
|
||||
Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own.
|
||||
- `SSH_ACCOUNT` - your SSH account, this is of the form username@domain.com
|
||||
- `DEPLOY_PATH` - the path on the server where `sasjs-tests` will be deployed to, typically `/var/www/html/<some-subfolder>`.
|
||||
|
||||
You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it.
|
||||
So you can run the script like so:
|
||||
|
||||
## Learn More
|
||||
```
|
||||
SSH_ACCOUNT=me@my-sas-server.com DEPLOY_PATH=/var/www/html/my-folder/sasjs-tests npm run deploy
|
||||
```
|
||||
|
||||
You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
|
||||
If you'd like to deploy just `sasjs-tests` without changing the adapter version, you can use the `deploy:tests` script, while also setting the same environment variables as above.
|
||||
|
||||
To learn React, check out the [React documentation](https://reactjs.org/).
|
||||
## 3. Creating the required SAS services
|
||||
|
||||
### Code Splitting
|
||||
The below services need to be created on your SAS server, at the location specified as the `appLoc` in the SASjs configuration.
|
||||
|
||||
This section has moved here: https://facebook.github.io/create-react-app/docs/code-splitting
|
||||
### SAS 9
|
||||
|
||||
### Analyzing the Bundle Size
|
||||
```
|
||||
|
||||
This section has moved here: https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size
|
||||
filename mc url "https://raw.githubusercontent.com/sasjs/core/main/all.sas";
|
||||
%inc mc;
|
||||
filename ft15f001 temp;
|
||||
parmcards4;
|
||||
%webout(OPEN)
|
||||
%macro x();
|
||||
%do i=1 %to &_webin_file_count; %webout(OBJ,&&_webin_name&i) %end;
|
||||
%mend; %x()
|
||||
%webout(CLOSE)
|
||||
;;;;
|
||||
%mm_createwebservice(path=/Public/app/common,name=sendObj)
|
||||
parmcards4;
|
||||
%webout(OPEN)
|
||||
%macro x();
|
||||
%do i=1 %to &_webin_file_count; %webout(ARR,&&_webin_name&i) %end;
|
||||
%mend; %x()
|
||||
%webout(CLOSE)
|
||||
;;;;
|
||||
%mm_createwebservice(path=/Public/app/common,name=sendArr)
|
||||
```
|
||||
|
||||
### Making a Progressive Web App
|
||||
### SAS Viya
|
||||
|
||||
This section has moved here: https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app
|
||||
```
|
||||
filename mc url "https://raw.githubusercontent.com/sasjs/core/main/all.sas";
|
||||
%inc mc;
|
||||
filename ft15f001 temp;
|
||||
parmcards4;
|
||||
%webout(FETCH)
|
||||
%webout(OPEN)
|
||||
%macro x();
|
||||
%do i=1 %to %sysfunc(countw(&sasjs_tables));
|
||||
%let table=%scan(&sasjs_tables,&i);
|
||||
%webout(OBJ,&table)
|
||||
%end;
|
||||
%mend;
|
||||
%x()
|
||||
%webout(CLOSE)
|
||||
;;;;
|
||||
%mp_createwebservice(path=/Public/app/common,name=sendObj)
|
||||
filename ft15f001 temp;
|
||||
parmcards4;
|
||||
%webout(FETCH)
|
||||
%webout(OPEN)
|
||||
%macro x();
|
||||
%do i=1 %to %sysfunc(countw(&sasjs_tables));
|
||||
%let table=%scan(&sasjs_tables,&i);
|
||||
%webout(ARR,&table)
|
||||
%end;
|
||||
%mend;
|
||||
%x()
|
||||
%webout(CLOSE)
|
||||
;;;;
|
||||
%mp_createwebservice(path=/Public/app/common,name=sendArr)
|
||||
filename ft15f001 temp;
|
||||
parmcards4;
|
||||
If you can keep your head when all about you
|
||||
Are losing theirs and blaming it on you,
|
||||
If you can trust yourself when all men doubt you,
|
||||
But make allowance for their doubting too;
|
||||
;;;;
|
||||
%mp_createwebservice(path=/Public/app/common,name=makeErr)
|
||||
```
|
||||
|
||||
### Advanced Configuration
|
||||
You should now be able to access the tests in your browser at the deployed path on your server.
|
||||
|
||||
This section has moved here: https://facebook.github.io/create-react-app/docs/advanced-configuration
|
||||
## Creating new tests
|
||||
|
||||
### Deployment
|
||||
The `src/testSuites` folder contains all the test suites currently available.
|
||||
Each suite contains a set of specs, each of which looks like this:
|
||||
|
||||
This section has moved here: https://facebook.github.io/create-react-app/docs/deployment
|
||||
```javascript
|
||||
{
|
||||
title: "Your test title",
|
||||
description: "A slightly more detailed description",
|
||||
test: async () => {
|
||||
// typically makes a request using the adapter and returns a promise
|
||||
},
|
||||
assertion: (response: any) =>
|
||||
// receives the response when the test promise resolves, runs an assertion and returns a boolean
|
||||
}
|
||||
```
|
||||
|
||||
### `npm run build` fails to minify
|
||||
A test suite is an array of such objects, along with a `name` property.
|
||||
|
||||
This section has moved here: https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify
|
||||
You can add your test to one of the existing suites if suitable, or create a new file that specifies a new test suite.
|
||||
|
||||
6
sasjs-tests/package-lock.json
generated
6
sasjs-tests/package-lock.json
generated
@@ -1357,9 +1357,9 @@
|
||||
"integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw=="
|
||||
},
|
||||
"@sasjs/adapter": {
|
||||
"version": "1.3.6",
|
||||
"resolved": "https://registry.npmjs.org/@sasjs/adapter/-/adapter-1.3.6.tgz",
|
||||
"integrity": "sha512-d2B+cTII+vabKCU8mJy90mEz3tCWw2pEp4qIBGsDamJiTS0Rx69dgXGHuRUm8KtjLDHHrzwXATsqviU3dnU0QQ==",
|
||||
"version": "1.3.13",
|
||||
"resolved": "https://registry.npmjs.org/@sasjs/adapter/-/adapter-1.3.13.tgz",
|
||||
"integrity": "sha512-dWcDxgY3FB7Yx1I5dPpeQeyJDu4lezhIFrjn6lbdwRhV15aqOt4l9o9qZP+VbgOXqyi9gN0Y+p+vs2chBDFQqg==",
|
||||
"requires": {
|
||||
"es6-promise": "^4.2.8",
|
||||
"form-data": "^3.0.0",
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"homepage": ".",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@sasjs/adapter": "^1.3.6",
|
||||
"@sasjs/adapter": "^1.3.13",
|
||||
"@sasjs/test-framework": "^1.4.0",
|
||||
"@testing-library/jest-dom": "^4.2.4",
|
||||
"@testing-library/react": "^9.5.0",
|
||||
@@ -25,7 +25,9 @@
|
||||
"build": "react-scripts build",
|
||||
"test": "react-scripts test",
|
||||
"eject": "react-scripts eject",
|
||||
"deploy": "cd .. && npm run package:lib && cd sasjs-tests && npm i ../build/sasjs-adapter-5.0.0.tgz && npm run build && rsync -avhe ssh ./build/* --delete kriaco@sas.analytium.co.uk:/var/www/html/kriaco/sasjs-tests"
|
||||
"update:adapter": "cd .. && npm run package:lib && cd sasjs-tests && npm i ../build/sasjs-adapter-5.0.0.tgz",
|
||||
"deploy:tests": "npm run build && rsync -avhe ssh ./build/* --delete $SSH_ACCOUNT:$DEPLOY_PATH",
|
||||
"deploy": "npm run update:adapter && npm run deploy:tests"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": "react-app"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { isLogInRequired, needsRetry } from './utils'
|
||||
import { isLogInRequired, needsRetry, isUrl } from './utils'
|
||||
import { CsrfToken } from './types/CsrfToken'
|
||||
import { UploadFile } from './types/UploadFile'
|
||||
|
||||
@@ -11,7 +11,10 @@ export class FileUploader {
|
||||
private jobsPath: string,
|
||||
private setCsrfTokenWeb: any,
|
||||
private csrfToken: CsrfToken | null = null
|
||||
) {}
|
||||
) {
|
||||
if (serverUrl) isUrl(serverUrl)
|
||||
}
|
||||
|
||||
private retryCount = 0
|
||||
|
||||
public uploadFile(sasJob: string, files: UploadFile[], params: any) {
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
import { isUrl } from './utils'
|
||||
|
||||
/**
|
||||
* A client for interfacing with the SAS9 REST API
|
||||
*
|
||||
*/
|
||||
export class SAS9ApiClient {
|
||||
constructor(private serverUrl: string) {}
|
||||
constructor(private serverUrl: string) {
|
||||
if (serverUrl) isUrl(serverUrl)
|
||||
}
|
||||
|
||||
/**
|
||||
* returns on object containing the server URL
|
||||
|
||||
@@ -2,7 +2,9 @@ import {
|
||||
isAuthorizeFormRequired,
|
||||
parseAndSubmitAuthorizeForm,
|
||||
convertToCSV,
|
||||
makeRequest
|
||||
makeRequest,
|
||||
isUri,
|
||||
isUrl
|
||||
} from './utils'
|
||||
import * as NodeFormData from 'form-data'
|
||||
import * as path from 'path'
|
||||
@@ -26,7 +28,10 @@ export class SASViyaApiClient {
|
||||
if (!rootFolderName) {
|
||||
throw new Error('Root folder must be provided.')
|
||||
}
|
||||
|
||||
if (serverUrl) isUrl(serverUrl)
|
||||
}
|
||||
|
||||
private csrfToken: CsrfToken | null = null
|
||||
private rootFolder: Folder | null = null
|
||||
private sessionManager = new SessionManager(
|
||||
@@ -34,6 +39,7 @@ export class SASViyaApiClient {
|
||||
this.contextName,
|
||||
this.setCsrfToken
|
||||
)
|
||||
private isForceDeploy: boolean = false
|
||||
|
||||
/**
|
||||
* Returns a map containing the directory structure in the currently set root folder.
|
||||
@@ -189,6 +195,107 @@ export class SASViyaApiClient {
|
||||
return createdSession
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a compute context on the given server.
|
||||
* @param contextName - the name of the context to be created.
|
||||
* @param launchContextName - the name of the launcher context used by the compute service.
|
||||
* @param sharedAccountId - the ID of the account to run the servers for this context as.
|
||||
* @param autoExecLines - the lines of code to execute during session initialization.
|
||||
* @param authorizedUsers - an optional list of authorized user IDs.
|
||||
* @param accessToken - an access token for an authorized user.
|
||||
*/
|
||||
public async createContext(
|
||||
contextName: string,
|
||||
launchContextName: string,
|
||||
sharedAccountId: string,
|
||||
autoExecLines: string[],
|
||||
authorizedUsers: string[],
|
||||
accessToken?: string
|
||||
) {
|
||||
if (!contextName) {
|
||||
throw new Error('Missing context name.')
|
||||
}
|
||||
|
||||
if (!launchContextName) {
|
||||
throw new Error('Missing launch context name.')
|
||||
}
|
||||
|
||||
if (!sharedAccountId) {
|
||||
throw new Error('Missing shared account ID.')
|
||||
}
|
||||
|
||||
const headers: any = {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
|
||||
if (accessToken) {
|
||||
headers.Authorization = `Bearer ${accessToken}`
|
||||
}
|
||||
|
||||
const requestBody: any = {
|
||||
name: contextName,
|
||||
launchContext: {
|
||||
contextName: launchContextName
|
||||
},
|
||||
attributes: {
|
||||
reuseServerProcesses: true,
|
||||
runServerAs: sharedAccountId
|
||||
}
|
||||
}
|
||||
|
||||
if (authorizedUsers && authorizedUsers.length) {
|
||||
requestBody['authorizedUsers'] = authorizedUsers
|
||||
} else {
|
||||
requestBody['authorizeAllAuthenticatedUsers'] = true
|
||||
}
|
||||
|
||||
if (autoExecLines) {
|
||||
requestBody.environment = { autoExecLines }
|
||||
}
|
||||
|
||||
const createContextRequest: RequestInit = {
|
||||
method: 'POST',
|
||||
headers,
|
||||
body: JSON.stringify(requestBody)
|
||||
}
|
||||
|
||||
const { result: context } = await this.request<Context>(
|
||||
`${this.serverUrl}/compute/contexts`,
|
||||
createContextRequest
|
||||
)
|
||||
|
||||
return context
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a compute context on the given server.
|
||||
* @param contextId - the ID of the context to be deleted.
|
||||
* @param accessToken - an access token for an authorized user.
|
||||
*/
|
||||
public async deleteContext(contextId: string, accessToken?: string) {
|
||||
if (!contextId) {
|
||||
throw new Error('Invalid context ID.')
|
||||
}
|
||||
|
||||
const headers: any = {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
|
||||
if (accessToken) {
|
||||
headers.Authorization = `Bearer ${accessToken}`
|
||||
}
|
||||
|
||||
const deleteContextRequest: RequestInit = {
|
||||
method: 'DELETE',
|
||||
headers
|
||||
}
|
||||
|
||||
return await this.request<Context>(
|
||||
`${this.serverUrl}/compute/contexts/${contextId}`,
|
||||
deleteContextRequest
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes code on the current SAS Viya server.
|
||||
* @param fileName - a name for the file being submitted for execution.
|
||||
@@ -360,12 +467,15 @@ export class SASViyaApiClient {
|
||||
* provided, the parentFolderUri must be provided.
|
||||
* @param parentFolderUri - the URI (eg /folders/folders/UUID) of the parent
|
||||
* folder. If not provided, the parentFolderPath must be provided.
|
||||
* @param accessToken - an access token for authorizing the request.
|
||||
* @param isForced - flag that indicates if target folder already exists, it and all subfolders have to be deleted.
|
||||
*/
|
||||
public async createFolder(
|
||||
folderName: string,
|
||||
parentFolderPath?: string,
|
||||
parentFolderUri?: string,
|
||||
accessToken?: string
|
||||
accessToken?: string,
|
||||
isForced?: boolean
|
||||
): Promise<Folder> {
|
||||
if (!parentFolderPath && !parentFolderUri) {
|
||||
throw new Error('Parent folder path or uri is required')
|
||||
@@ -374,6 +484,8 @@ export class SASViyaApiClient {
|
||||
if (!parentFolderUri && parentFolderPath) {
|
||||
parentFolderUri = await this.getFolderUri(parentFolderPath, accessToken)
|
||||
if (!parentFolderUri) {
|
||||
if (isForced) this.isForceDeploy = true
|
||||
|
||||
console.log(`Parent folder is not present: ${parentFolderPath}`)
|
||||
|
||||
const newParentFolderPath = parentFolderPath.substring(
|
||||
@@ -394,6 +506,35 @@ export class SASViyaApiClient {
|
||||
accessToken
|
||||
)
|
||||
console.log(`Parent Folder "${newFolderName}" successfully created.`)
|
||||
parentFolderUri = `/folders/folders/${parentFolder.id}`
|
||||
} else if (isForced && accessToken && !this.isForceDeploy) {
|
||||
this.isForceDeploy = true
|
||||
|
||||
await this.deleteFolder(parentFolderPath, accessToken)
|
||||
|
||||
const newParentFolderPath = parentFolderPath.substring(
|
||||
0,
|
||||
parentFolderPath.lastIndexOf('/')
|
||||
)
|
||||
const newFolderName = `${parentFolderPath.split('/').pop()}`
|
||||
|
||||
if (newParentFolderPath === '') {
|
||||
throw new Error('Root Folder should have been present on server')
|
||||
}
|
||||
|
||||
console.log(
|
||||
`Creating Parent Folder:\n${newFolderName} in ${newParentFolderPath}`
|
||||
)
|
||||
|
||||
const parentFolder = await this.createFolder(
|
||||
newFolderName,
|
||||
newParentFolderPath,
|
||||
undefined,
|
||||
accessToken
|
||||
)
|
||||
|
||||
console.log(`Parent Folder "${newFolderName}" successfully created.`)
|
||||
|
||||
parentFolderUri = `/folders/folders/${parentFolder.id}`
|
||||
}
|
||||
}
|
||||
@@ -616,7 +757,7 @@ export class SASViyaApiClient {
|
||||
/**
|
||||
* Deletes the client representing the supplied ID.
|
||||
* @param clientId - the client ID to authenticate with.
|
||||
* @param accessToken - an access token for an authorized user.
|
||||
* @param accessToken - an access token for authorizing the request.
|
||||
*/
|
||||
public async deleteClient(clientId: string, accessToken?: string) {
|
||||
const url = this.serverUrl + `/oauth/clients/${clientId}`
|
||||
@@ -1085,6 +1226,101 @@ export class SASViyaApiClient {
|
||||
return `/folders/folders/${folder.id}`
|
||||
}
|
||||
|
||||
private async getRecycleBinUri(accessToken: string) {
|
||||
const url = '/folders/folders/@myRecycleBin'
|
||||
const requestInfo = {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: 'Bearer ' + accessToken
|
||||
}
|
||||
}
|
||||
|
||||
const { result: folder } = await this.request<Folder>(
|
||||
`${this.serverUrl}${url}`,
|
||||
requestInfo
|
||||
).catch((err) => {
|
||||
return { result: null }
|
||||
})
|
||||
|
||||
if (!folder) return undefined
|
||||
|
||||
return `/folders/folders/${folder.id}`
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves a Viya folder to a new location. The folder may be renamed at the same time.
|
||||
* @param sourceFolder - the full path (eg `/Public/example/myFolder`) or URI of the source folder to be moved. Providing URI instead of path will save one extra request.
|
||||
* @param targetParentFolder - the full path or URI of the _parent_ folder to which the `sourceFolder` will be moved (eg `/Public/newDestination`). To move a folder, a user has to have write permissions in targetParentFolder. Providing URI instead of path will save one extra request.
|
||||
* @param targetFolderName - the name of the "moved" folder. If left blank, the original folder name will be used (eg `myFolder` in `/Public/newDestination/myFolder` for the example above). Optional field.
|
||||
* @param accessToken - an access token for authorizing the request.
|
||||
*/
|
||||
public async moveFolder(
|
||||
sourceFolder: string,
|
||||
targetParentFolder: string,
|
||||
targetFolderName: string,
|
||||
accessToken: string
|
||||
) {
|
||||
// checks if 'sourceFolder' is already a URI
|
||||
const sourceFolderUri = isUri(sourceFolder)
|
||||
? sourceFolder
|
||||
: await this.getFolderUri(sourceFolder, accessToken)
|
||||
|
||||
// checks if 'targetParentFolder' is already a URI
|
||||
const targetParentFolderUri = isUri(targetParentFolder)
|
||||
? targetParentFolder
|
||||
: await this.getFolderUri(targetParentFolder, accessToken)
|
||||
|
||||
const sourceFolderId = sourceFolderUri?.split('/').pop()
|
||||
const url = sourceFolderUri
|
||||
|
||||
const requestInfo = {
|
||||
method: 'PATCH',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: 'Bearer ' + accessToken
|
||||
},
|
||||
body: JSON.stringify({
|
||||
id: sourceFolderId,
|
||||
name: targetFolderName,
|
||||
parentFolderUri: targetParentFolderUri
|
||||
})
|
||||
}
|
||||
|
||||
const { result: folder } = await this.request<Folder>(
|
||||
`${this.serverUrl}${url}`,
|
||||
requestInfo
|
||||
).catch((err) => {
|
||||
throw err
|
||||
})
|
||||
|
||||
if (!folder) return undefined
|
||||
|
||||
return folder
|
||||
}
|
||||
|
||||
/**
|
||||
* For performance (and in case of accidental error) the `deleteFolder` function does not actually delete the folder (and all it's content and subfolder content). Instead the folder is simply moved to the recycle bin. Deletion time will be added to the folder name.
|
||||
* @param folderPath - the full path (eg `/Public/example/deleteThis`) of the folder to be deleted.
|
||||
* @param accessToken - an access token for authorizing the request.
|
||||
*/
|
||||
public async deleteFolder(folderPath: string, accessToken: string) {
|
||||
const recycleBinUri = await this.getRecycleBinUri(accessToken)
|
||||
const folderName = folderPath.split('/').pop() || ''
|
||||
const date = new Date()
|
||||
const timeMark = date.toLocaleDateString() + ' ' + date.toLocaleTimeString()
|
||||
const deletedFolderName = folderName + ' ' + timeMark
|
||||
|
||||
const movedFolder = await this.moveFolder(
|
||||
folderPath,
|
||||
recycleBinUri!,
|
||||
deletedFolderName,
|
||||
accessToken
|
||||
)
|
||||
|
||||
return movedFolder
|
||||
}
|
||||
|
||||
setCsrfTokenLocal = (csrfToken: CsrfToken) => {
|
||||
this.csrfToken = csrfToken
|
||||
this.setCsrfToken(csrfToken)
|
||||
|
||||
75
src/SASjs.ts
75
src/SASjs.ts
@@ -107,6 +107,48 @@ export default class SASjs {
|
||||
return await this.sasViyaApiClient!.getExecutableContexts(accessToken)
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a compute context on the given server.
|
||||
* @param contextName - the name of the context to be created.
|
||||
* @param launchContextName - the name of the launcher context used by the compute service.
|
||||
* @param sharedAccountId - the ID of the account to run the servers for this context as.
|
||||
* @param autoExecLines - the lines of code to execute during session initialization.
|
||||
* @param authorizedUsers - an optional list of authorized user IDs.
|
||||
* @param accessToken - an access token for an authorized user.
|
||||
*/
|
||||
public async createContext(
|
||||
contextName: string,
|
||||
launchContextName: string,
|
||||
sharedAccountId: string,
|
||||
autoExecLines: string[],
|
||||
authorizedUsers: string[],
|
||||
accessToken: string
|
||||
) {
|
||||
if (this.sasjsConfig.serverType !== ServerType.SASViya) {
|
||||
throw new Error('This operation is only supported on SAS Viya servers.')
|
||||
}
|
||||
return await this.sasViyaApiClient!.createContext(
|
||||
contextName,
|
||||
launchContextName,
|
||||
sharedAccountId,
|
||||
autoExecLines,
|
||||
authorizedUsers,
|
||||
accessToken
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a compute context on the given server.
|
||||
* @param contextId - the ID of the context to be deleted.
|
||||
* @param accessToken - an access token for an authorized user.
|
||||
*/
|
||||
public async deleteContext(contextId: string, accessToken?: string) {
|
||||
if (this.sasjsConfig.serverType !== ServerType.SASViya) {
|
||||
throw new Error('This operation is only supported on SAS Viya servers.')
|
||||
}
|
||||
return await this.sasViyaApiClient!.deleteContext(contextId, accessToken)
|
||||
}
|
||||
|
||||
public async createSession(contextName: string, accessToken: string) {
|
||||
if (this.sasjsConfig.serverType !== ServerType.SASViya) {
|
||||
throw new Error('This operation is only supported on SAS Viya servers.')
|
||||
@@ -134,12 +176,22 @@ export default class SASjs {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a folder at SAS file system
|
||||
* @param folderName - name of the folder to be created.
|
||||
* @param parentFolderPath - the full path (eg `/Public/example/myFolder`) of the parent folder.
|
||||
* @param parentFolderUri - the URI of the parent folder.
|
||||
* @param accessToken - the access token to authorizing the request.
|
||||
* @param sasApiClient - a client for interfacing with SAS API.
|
||||
* @param isForced - flag that indicates if target folder already exists, it and all subfolders have to be deleted. Applicable for SAS VIYA only.
|
||||
*/
|
||||
public async createFolder(
|
||||
folderName: string,
|
||||
parentFolderPath: string,
|
||||
parentFolderUri?: string,
|
||||
accessToken?: string,
|
||||
sasApiClient?: SASViyaApiClient
|
||||
sasApiClient?: SASViyaApiClient,
|
||||
isForced?: boolean
|
||||
) {
|
||||
if (this.sasjsConfig.serverType !== ServerType.SASViya) {
|
||||
throw new Error('This operation is only supported on SAS Viya servers.')
|
||||
@@ -155,7 +207,8 @@ export default class SASjs {
|
||||
folderName,
|
||||
parentFolderPath,
|
||||
parentFolderUri,
|
||||
accessToken
|
||||
accessToken,
|
||||
isForced
|
||||
)
|
||||
}
|
||||
|
||||
@@ -484,12 +537,14 @@ export default class SASjs {
|
||||
* If not provided, is taken from SASjsConfig.
|
||||
* @param accessToken - an optional access token to be passed in when
|
||||
* using this function from the command line.
|
||||
* @param isForced - flag that indicates if target folder already exists, it and all subfolders have to be deleted.
|
||||
*/
|
||||
public async deployServicePack(
|
||||
serviceJson: any,
|
||||
appLoc?: string,
|
||||
serverUrl?: string,
|
||||
accessToken?: string
|
||||
accessToken?: string,
|
||||
isForced = false
|
||||
) {
|
||||
if (this.sasjsConfig.serverType !== ServerType.SASViya) {
|
||||
throw new Error('This operation is only supported on SAS Viya servers.')
|
||||
@@ -540,7 +595,8 @@ export default class SASjs {
|
||||
appLoc,
|
||||
members,
|
||||
accessToken,
|
||||
sasApiClient
|
||||
sasApiClient,
|
||||
isForced
|
||||
)
|
||||
}
|
||||
|
||||
@@ -855,7 +911,7 @@ export default class SASjs {
|
||||
) {
|
||||
if (this.retryCountWeb < requestRetryLimit) {
|
||||
this.retryCountWeb++
|
||||
this.request(sasJob, data).then(
|
||||
this.request(sasJob, data, config, loginRequiredCallback).then(
|
||||
(res: any) => resolve(res),
|
||||
(err: any) => reject(err)
|
||||
)
|
||||
@@ -1247,7 +1303,8 @@ export default class SASjs {
|
||||
parentFolder: string,
|
||||
membersJson: any[],
|
||||
accessToken?: string,
|
||||
sasApiClient?: SASViyaApiClient
|
||||
sasApiClient?: SASViyaApiClient,
|
||||
isForced?: boolean
|
||||
) {
|
||||
await asyncForEach(membersJson, async (member: any) => {
|
||||
switch (member.type) {
|
||||
@@ -1257,7 +1314,8 @@ export default class SASjs {
|
||||
parentFolder,
|
||||
undefined,
|
||||
accessToken,
|
||||
sasApiClient
|
||||
sasApiClient,
|
||||
isForced
|
||||
)
|
||||
break
|
||||
case 'service':
|
||||
@@ -1278,7 +1336,8 @@ export default class SASjs {
|
||||
`${parentFolder}/${member.name}`,
|
||||
member.members,
|
||||
accessToken,
|
||||
sasApiClient
|
||||
sasApiClient,
|
||||
isForced
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Session, Context, CsrfToken } from './types'
|
||||
import { asyncForEach, makeRequest } from './utils'
|
||||
import { asyncForEach, makeRequest, isUrl } from './utils'
|
||||
|
||||
const MAX_SESSION_COUNT = 1
|
||||
|
||||
@@ -8,7 +8,10 @@ export class SessionManager {
|
||||
private serverUrl: string,
|
||||
private contextName: string,
|
||||
private setCsrfToken: (csrfToken: CsrfToken) => void
|
||||
) {}
|
||||
) {
|
||||
if (serverUrl) isUrl(serverUrl)
|
||||
}
|
||||
|
||||
private sessions: Session[] = []
|
||||
private currentContext: Context | null = null
|
||||
private csrfToken: CsrfToken | null = null
|
||||
|
||||
@@ -13,3 +13,5 @@ export * from './parseSasViyaLog'
|
||||
export * from './serialize'
|
||||
export * from './splitChunks'
|
||||
export * from './parseWeboutResponse'
|
||||
export * from './isUri'
|
||||
export * from './isUrl'
|
||||
|
||||
5
src/utils/isUri.ts
Normal file
5
src/utils/isUri.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
/**
|
||||
* Checks if string is in URI format
|
||||
* @param str string to check
|
||||
*/
|
||||
export const isUri = (str: string): boolean => /^\/folders\/folders\//.test(str)
|
||||
12
src/utils/isUrl.ts
Normal file
12
src/utils/isUrl.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
export const isUrl = (url: string): boolean => {
|
||||
const pattern = new RegExp(
|
||||
'^(http://|https://)[a-z0-9]+([-.]{1}[a-z0-9]+)*.[a-z]{2,5}(:[0-9]{1,5})?(/.*)?$',
|
||||
'gi'
|
||||
)
|
||||
|
||||
if (pattern.test(url)) return true
|
||||
else
|
||||
throw new Error(
|
||||
`'${url}' is not a valid url. An example of a valid url is 'http://valid-url.com'.`
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user