mirror of
https://github.com/sasjs/core.git
synced 2026-01-06 17:10:05 +00:00
Compare commits
4 Commits
allanbowe/
...
v4.12.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
842662aae1 | ||
|
|
876fac2332 | ||
|
|
427deca350 | ||
|
|
badf5b5761 |
@@ -47,7 +47,7 @@ Documentation: https://core.sasjs.io
|
|||||||
|
|
||||||
This library will not be used for storing data entries (such as formats or datalines). Where this becomes necessary in the future, a new repo will be created, in order to keep the NPM bundle size down (for the benefit of those looking to embed purely macros in their applications).
|
This library will not be used for storing data entries (such as formats or datalines). Where this becomes necessary in the future, a new repo will be created, in order to keep the NPM bundle size down (for the benefit of those looking to embed purely macros in their applications).
|
||||||
|
|
||||||
#### FCMP library (All Platforms)
|
### FCMP library (All Platforms)
|
||||||
|
|
||||||
- Function and macro names are identical, except for special cases
|
- Function and macro names are identical, except for special cases
|
||||||
- Prefixes: _mcf_
|
- Prefixes: _mcf_
|
||||||
@@ -217,7 +217,6 @@ If you find this library useful, please leave a [star](https://github.com/sasjs/
|
|||||||

|

|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Contributors ✨
|
## Contributors ✨
|
||||||
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
|
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
|
||||||
[](#contributors-)
|
[](#contributors-)
|
||||||
|
|||||||
@@ -74,7 +74,8 @@
|
|||||||
outds=work.test_results
|
outds=work.test_results
|
||||||
)/*/STORE SOURCE*/;
|
)/*/STORE SOURCE*/;
|
||||||
%local ds test_result test_comments del add mod ilist;
|
%local ds test_result test_comments del add mod ilist;
|
||||||
%let ilist=%upcase(&sasjs_prefix._FUNCTIONS &ignorelist);
|
%let ilist=%upcase(&sasjs_prefix._FUNCTIONS SYS_PROCHTTP_STATUS_CODE
|
||||||
|
SYS_PROCHTTP_STATUS_CODE SYS_PROCHTTP_STATUS_PHRASE &ignorelist);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* this sets up the global vars, it will also enter STRICT mode. If this
|
* this sets up the global vars, it will also enter STRICT mode. If this
|
||||||
@@ -89,7 +90,7 @@
|
|||||||
create table &scopeds as
|
create table &scopeds as
|
||||||
select name,offset,value
|
select name,offset,value
|
||||||
from dictionary.macros
|
from dictionary.macros
|
||||||
where scope="&scope" and name not in (%mf_getquotedstr(&ilist))
|
where scope="&scope" and upcase(name) not in (%mf_getquotedstr(&ilist))
|
||||||
order by name,offset;
|
order by name,offset;
|
||||||
%end;
|
%end;
|
||||||
%else %if &action=COMPARE %then %do;
|
%else %if &action=COMPARE %then %do;
|
||||||
@@ -141,4 +142,4 @@
|
|||||||
drop table &ds;
|
drop table &ds;
|
||||||
%end;
|
%end;
|
||||||
|
|
||||||
%mend mp_assertscope;
|
%mend mp_assertscope;
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
@file
|
@file
|
||||||
@brief Mechanism for locking tables to prevent parallel modifications
|
@brief Mechanism for locking tables to prevent parallel modifications
|
||||||
@details Uses a control table to enable ANY table to be locked for updates.
|
@details Uses a control table to enable ANY table to be locked for updates
|
||||||
|
(not just SAS datasets).
|
||||||
Only useful if every update uses the macro! Used heavily within
|
Only useful if every update uses the macro! Used heavily within
|
||||||
[Data Controller for SAS](https://datacontroller.io).
|
[Data Controller for SAS](https://datacontroller.io).
|
||||||
|
|
||||||
@@ -15,7 +16,7 @@
|
|||||||
length is 200 characters.
|
length is 200 characters.
|
||||||
@param [out] ctl_ds= (0) The control table which controls the actual locking.
|
@param [out] ctl_ds= (0) The control table which controls the actual locking.
|
||||||
Should already be assigned and available. The definition is available by
|
Should already be assigned and available. The definition is available by
|
||||||
running mp_coretable.sas as follows: `%mp_coretable(LOCKTABLE)`.
|
running the mddl_dc_locktable.sas macro.
|
||||||
|
|
||||||
@param [in] loops= (25) Number of times to check for a lock.
|
@param [in] loops= (25) Number of times to check for a lock.
|
||||||
@param [in] loop_secs= (1) Seconds to wait between each lock attempt
|
@param [in] loop_secs= (1) Seconds to wait between each lock attempt
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
%mp_streamfile(contenttype=csv,inloc=/some/where.txt,outname=myfile.txt)
|
%mp_streamfile(contenttype=csv,inloc=/some/where.txt,outname=myfile.txt)
|
||||||
|
|
||||||
@param [in] contenttype= (TEXTS) Either TEXT, ZIP, CSV, EXCEL
|
@param [in] contenttype= (TEXT) Either TEXT, ZIP, CSV, EXCEL
|
||||||
@param [in] inloc= /path/to/file.ext to be sent
|
@param [in] inloc= /path/to/file.ext to be sent
|
||||||
@param [in] inref= fileref of file to be sent (if provided, overrides `inloc`)
|
@param [in] inref= fileref of file to be sent (if provided, overrides `inloc`)
|
||||||
@param [in] iftrue= (1=1) Provide a condition under which to execute.
|
@param [in] iftrue= (1=1) Provide a condition under which to execute.
|
||||||
|
|||||||
@@ -40,6 +40,12 @@
|
|||||||
/* now try and assign it */
|
/* now try and assign it */
|
||||||
if libname("&libref",,'meta',cats('liburi="',liburi,'";')) ne 0 then do;
|
if libname("&libref",,'meta',cats('liburi="',liburi,'";')) ne 0 then do;
|
||||||
putlog "&libref could not be assigned";
|
putlog "&libref could not be assigned";
|
||||||
|
putlog liburi=;
|
||||||
|
/**
|
||||||
|
* Fetch the system message for display in the abort modal. This is
|
||||||
|
* not always helpful though. One example, previously received:
|
||||||
|
* NOTE: Libref XX refers to the same library metadata as libref XX.
|
||||||
|
*/
|
||||||
call symputx('msg',sysmsg(),'l');
|
call symputx('msg',sysmsg(),'l');
|
||||||
if "&mabort"='HARD' then call symputx('mp_abort',1,'l');
|
if "&mabort"='HARD' then call symputx('mp_abort',1,'l');
|
||||||
end;
|
end;
|
||||||
@@ -61,7 +67,7 @@
|
|||||||
|
|
||||||
%if &mp_abort=1 %then %do;
|
%if &mp_abort=1 %then %do;
|
||||||
%mp_abort(iftrue= (&mp_abort=1)
|
%mp_abort(iftrue= (&mp_abort=1)
|
||||||
,mac=&sysmacroname
|
,mac=mm_assignlib.sas
|
||||||
,msg=&msg
|
,msg=&msg
|
||||||
)
|
)
|
||||||
%return;
|
%return;
|
||||||
|
|||||||
2
package-lock.json
generated
2
package-lock.json
generated
@@ -7,7 +7,7 @@
|
|||||||
"name": "@sasjs/core",
|
"name": "@sasjs/core",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@sasjs/cli": "^3.6.0",
|
"@sasjs/cli": "3.6.0",
|
||||||
"@sasjs/core": "4.4.7"
|
"@sasjs/core": "4.4.7"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -33,7 +33,7 @@
|
|||||||
"prepare": "git rev-parse --git-dir && git config core.hooksPath ./.git-hooks || true"
|
"prepare": "git rev-parse --git-dir && git config core.hooksPath ./.git-hooks || true"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@sasjs/cli": "^3.6.0",
|
"@sasjs/cli": "3.6.0",
|
||||||
"@sasjs/core": "4.4.7"
|
"@sasjs/core": "4.4.7"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,17 +73,24 @@
|
|||||||
"name": "server",
|
"name": "server",
|
||||||
"serverUrl": "https://sas.analytium.co.uk:5000",
|
"serverUrl": "https://sas.analytium.co.uk:5000",
|
||||||
"serverType": "SASJS",
|
"serverType": "SASJS",
|
||||||
"appLoc": "/Shared Data/temp/macrocore",
|
"httpsAgentOptions": {
|
||||||
|
"allowInsecureRequests": false
|
||||||
|
},
|
||||||
|
"appLoc": "/sasjs/core",
|
||||||
"macroFolders": [
|
"macroFolders": [
|
||||||
"tests/serveronly"
|
"tests/serveronly"
|
||||||
],
|
],
|
||||||
|
"programFolders": [],
|
||||||
|
"binaryFolders": [],
|
||||||
"deployConfig": {
|
"deployConfig": {
|
||||||
"deployServicePack": true
|
"deployServicePack": true,
|
||||||
|
"deployScripts": []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "docsonly",
|
"name": "docsonly",
|
||||||
"serverType": "SAS9",
|
"serverType": "SAS9",
|
||||||
|
"appLoc": "dummy",
|
||||||
"macroFolders": [
|
"macroFolders": [
|
||||||
"tests/sas9only",
|
"tests/sas9only",
|
||||||
"tests/viyaonly"
|
"tests/viyaonly"
|
||||||
|
|||||||
89
server/ms_createfile.sas
Normal file
89
server/ms_createfile.sas
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
/**
|
||||||
|
@file
|
||||||
|
@brief Creates a file on SASjs Drive
|
||||||
|
@details Creates a file on SASjs Drive. To use the file as a Stored Program,
|
||||||
|
it must have a ".sas" extension.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
filename stpcode temp;
|
||||||
|
data _null_;
|
||||||
|
file stpcode;
|
||||||
|
put '%put hello world;';
|
||||||
|
run;
|
||||||
|
%ms_createfile(/some/stored/program.sas, inref=stpcode)
|
||||||
|
|
||||||
|
@param [in] driveloc The full path to the file in SASjs Drive
|
||||||
|
@param [in] inref= (0) The fileref containing the file to create.
|
||||||
|
@param [in] mdebug= (0) Set to 1 to enable DEBUG messages
|
||||||
|
|
||||||
|
<h4> SAS Macros </h4>
|
||||||
|
@li mf_getuniquefileref.sas
|
||||||
|
@li mf_getuniquename.sas
|
||||||
|
@li mp_abort.sas
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
%macro ms_createfile(driveloc
|
||||||
|
,inref=0
|
||||||
|
,mdebug=0
|
||||||
|
);
|
||||||
|
|
||||||
|
%local fname0 fname1 boundary fname statcd msg;
|
||||||
|
%let fname0=%mf_getuniquefileref();
|
||||||
|
%let fname1=%mf_getuniquefileref();
|
||||||
|
%let boundary=%mf_getuniquename();
|
||||||
|
|
||||||
|
data _null_;
|
||||||
|
file &fname0 termstr=crlf;
|
||||||
|
infile &inref end=eof;
|
||||||
|
if _n_ = 1 then do;
|
||||||
|
put "--&boundary.";
|
||||||
|
put 'Content-Disposition: form-data; name="filePath"';
|
||||||
|
put ;
|
||||||
|
put "&driveloc";
|
||||||
|
put "--&boundary";
|
||||||
|
put 'Content-Disposition: form-data; name="file"; filename="ignore.sas"';
|
||||||
|
put "Content-Type: text/plain";
|
||||||
|
put ;
|
||||||
|
end;
|
||||||
|
input;
|
||||||
|
put _infile_; /* add the actual file to be sent */
|
||||||
|
if eof then do;
|
||||||
|
put ;
|
||||||
|
put "--&boundary--";
|
||||||
|
end;
|
||||||
|
run;
|
||||||
|
|
||||||
|
%if &mdebug=1 %then %do;
|
||||||
|
data _null_;
|
||||||
|
infile &fname0;
|
||||||
|
input;
|
||||||
|
put _infile_;
|
||||||
|
run;
|
||||||
|
%end;
|
||||||
|
|
||||||
|
proc http method='POST' in=&fname0 out=&fname1
|
||||||
|
url="&_sasjs_apiserverurl/SASjsApi/drive/file";
|
||||||
|
headers "Content-Type"="multipart/form-data; boundary=&boundary";
|
||||||
|
%if &mdebug=1 %then %do;
|
||||||
|
debug level=1;
|
||||||
|
%end;
|
||||||
|
run;
|
||||||
|
|
||||||
|
%let statcd=0;
|
||||||
|
data _null_;
|
||||||
|
infile &fname1;
|
||||||
|
input;
|
||||||
|
putlog _infile_;
|
||||||
|
if _infile_='{"status":"success"}' then call symputx('statcd',1,'l');
|
||||||
|
else call symputx('msg',_infile_,'l');
|
||||||
|
run;
|
||||||
|
|
||||||
|
%mp_abort(
|
||||||
|
iftrue=(&statcd=0)
|
||||||
|
,mac=ms_createfile.sas
|
||||||
|
,msg=%superq(msg)
|
||||||
|
)
|
||||||
|
|
||||||
|
%mend ms_createfile;
|
||||||
77
server/ms_runstp.sas
Normal file
77
server/ms_runstp.sas
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
/**
|
||||||
|
@file
|
||||||
|
@brief Executes a SASjs Server Stored Program
|
||||||
|
@details Runs a Stored Program (using POST method) and extracts the webout and
|
||||||
|
log from the response JSON.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
%ms_runstp(/some/stored/program
|
||||||
|
,debug=131
|
||||||
|
,outref=weboot
|
||||||
|
)
|
||||||
|
|
||||||
|
@param [in] pgm The full path to the Stored Program in SASjs Drive (_program
|
||||||
|
parameter)
|
||||||
|
@param [in] debug= (131) The value to supply to the _debug URL parameter
|
||||||
|
@param [in] mdebug= (0) Set to 1 to enable DEBUG messages
|
||||||
|
@param [out] outref= (outweb) The output fileref to contain the response JSON
|
||||||
|
(will be created using temp engine)
|
||||||
|
|
||||||
|
<h4> SAS Macros </h4>
|
||||||
|
@li mf_getuniquefileref.sas
|
||||||
|
@li mp_abort.sas
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
%macro ms_runstp(pgm
|
||||||
|
,debug=131
|
||||||
|
,outref=outweb
|
||||||
|
,mdebug=0
|
||||||
|
);
|
||||||
|
%local dbg fname1;
|
||||||
|
%if &mdebug=1 %then %do;
|
||||||
|
%put &sysmacroname entry vars:;
|
||||||
|
%put _local_;
|
||||||
|
%end;
|
||||||
|
%else %let dbg=*;
|
||||||
|
%let fname1=%mf_getuniquefileref();
|
||||||
|
|
||||||
|
%mp_abort(iftrue=("&pgm"="")
|
||||||
|
,mac=&sysmacroname
|
||||||
|
,msg=%str(Program not provided)
|
||||||
|
)
|
||||||
|
|
||||||
|
data _null_;
|
||||||
|
file &fname1;
|
||||||
|
infile "&_sasjs_tokenfile";
|
||||||
|
input;
|
||||||
|
put 'Authorization: Bearer' _infile_;
|
||||||
|
run;
|
||||||
|
|
||||||
|
filename &outref temp;
|
||||||
|
|
||||||
|
/* prepare request*/
|
||||||
|
proc http method='POST' headerin=&fname1 out=&outref
|
||||||
|
url="&_sasjs_apiserverurl.&_sasjs_apipath?_program=&pgm%str(&)_debug=131";
|
||||||
|
run;
|
||||||
|
%if (&SYS_PROCHTTP_STATUS_CODE ne 200 and &SYS_PROCHTTP_STATUS_CODE ne 201)
|
||||||
|
or &mdebug=1 %then %do;
|
||||||
|
data _null_;infile &outref;input;putlog _infile_;run;
|
||||||
|
%end;
|
||||||
|
%mp_abort(
|
||||||
|
iftrue=(&SYS_PROCHTTP_STATUS_CODE ne 200 and &SYS_PROCHTTP_STATUS_CODE ne 201)
|
||||||
|
,mac=&sysmacroname
|
||||||
|
,msg=%str(&SYS_PROCHTTP_STATUS_CODE &SYS_PROCHTTP_STATUS_PHRASE)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
%if &mdebug=1 %then %do;
|
||||||
|
%put &sysmacroname exit vars:;
|
||||||
|
%put _local_;
|
||||||
|
%end;
|
||||||
|
%else %do;
|
||||||
|
/* clear refs */
|
||||||
|
filename &fname1 clear;
|
||||||
|
%end;
|
||||||
|
%mend ms_runstp;
|
||||||
@@ -5,12 +5,16 @@
|
|||||||
<h4> SAS Macros </h4>
|
<h4> SAS Macros </h4>
|
||||||
@li mfs_httpheader.sas
|
@li mfs_httpheader.sas
|
||||||
@li mp_assert.sas
|
@li mp_assert.sas
|
||||||
|
@li mp_assertscope.sas
|
||||||
|
|
||||||
**/
|
**/
|
||||||
|
|
||||||
%let sasjs_stpsrv_header_loc=%sysfunc(pathname(work))/header.txt;
|
%let sasjs_stpsrv_header_loc=%sysfunc(pathname(work))/header.txt;
|
||||||
|
|
||||||
|
%mp_assertscope(SNAPSHOT)
|
||||||
%mfs_httpheader(Content-type,application/csv)
|
%mfs_httpheader(Content-type,application/csv)
|
||||||
|
%mp_assertscope(COMPARE)
|
||||||
|
|
||||||
data _null_;
|
data _null_;
|
||||||
infile "&sasjs_stpsrv_header_loc";
|
infile "&sasjs_stpsrv_header_loc";
|
||||||
input;
|
input;
|
||||||
|
|||||||
30
tests/serveronly/ms_createfile.test.sas
Normal file
30
tests/serveronly/ms_createfile.test.sas
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
/**
|
||||||
|
@file
|
||||||
|
@brief Testing ms_createfile.sas macro
|
||||||
|
|
||||||
|
<h4> SAS Macros </h4>
|
||||||
|
@li ms_createfile.sas
|
||||||
|
@li mp_assert.sas
|
||||||
|
@li mp_assertscope.sas
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
|
||||||
|
filename stpcode temp;
|
||||||
|
data _null_;
|
||||||
|
file stpcode;
|
||||||
|
put '%put hello world;';
|
||||||
|
run;
|
||||||
|
|
||||||
|
options mprint;
|
||||||
|
%let fname=%mf_getuniquename();
|
||||||
|
|
||||||
|
%mp_assertscope(SNAPSHOT)
|
||||||
|
%ms_createfile(/sasjs/tests/&fname..sas
|
||||||
|
,inref=stpcode
|
||||||
|
,mdebug=1
|
||||||
|
)
|
||||||
|
%mp_assertscope(COMPARE)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
44
tests/serveronly/ms_runstp.test.sas
Normal file
44
tests/serveronly/ms_runstp.test.sas
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
/**
|
||||||
|
@file
|
||||||
|
@brief Testing ms_runstp.sas macro
|
||||||
|
|
||||||
|
<h4> SAS Macros </h4>
|
||||||
|
@li ms_runstp.sas
|
||||||
|
@li mp_assert.sas
|
||||||
|
@li mp_assertscope.sas
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
%mp_assertscope(SNAPSHOT)
|
||||||
|
%ms_runstp(/Public/app/frs/allan/services/common/appinit
|
||||||
|
,debug=131
|
||||||
|
,outref=weboot
|
||||||
|
)
|
||||||
|
%mp_assertscope(COMPARE)
|
||||||
|
|
||||||
|
libname webeen json (weboot);
|
||||||
|
|
||||||
|
data _null_;
|
||||||
|
infile weboot;
|
||||||
|
input;
|
||||||
|
putlog _infile_;
|
||||||
|
run;
|
||||||
|
|
||||||
|
data work.httpheaders;
|
||||||
|
set webeen.httpheaders;
|
||||||
|
call symputx('test1',content_type);
|
||||||
|
run;
|
||||||
|
|
||||||
|
data work.log;
|
||||||
|
set webeen.log;
|
||||||
|
put (_all_)(=);
|
||||||
|
if _n_>10 then stop;
|
||||||
|
run;
|
||||||
|
|
||||||
|
%mp_assert(
|
||||||
|
iftrue=("&test1"="application/json"),
|
||||||
|
desc=Checking line was created,
|
||||||
|
outds=work.test_results
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user