From aad1486c73a828d3746225f3c1933e6b1bb9c226 Mon Sep 17 00:00:00 2001
From: a <>
Date: Mon, 24 Feb 2025 10:59:48 +0000
Subject: [PATCH 1/2] feat: triggerstp Stored Program
---
server/ms_triggerstp.sas | 215 +++++++++++++++++++++++++++++++++++++++
1 file changed, 215 insertions(+)
create mode 100644 server/ms_triggerstp.sas
diff --git a/server/ms_triggerstp.sas b/server/ms_triggerstp.sas
new file mode 100644
index 00000000..b7f00188
--- /dev/null
+++ b/server/ms_triggerstp.sas
@@ -0,0 +1,215 @@
+/**
+ @file
+ @brief Triggers a SASjs Server STP using the /SASjsApi/code/trigger endpoint
+ @details Triggers the STP and returns the sessionId
+
+ Example:
+
+ %ms_triggerstp(/some/stored/program
+ ,debug=131
+ ,outds=work.myresults
+ )
+
+ @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 [in] inputparams=(_null_) A dataset containing name/value pairs in the
+ following format:
+ |name:$32|value:$10000|
+ |---|---|
+ |stpmacname|some value|
+ |mustbevalidname|can be anything, oops, %abort!!|
+ @param [in] inputfiles= (_null_) A dataset containing fileref/name/filename in
+ the following format:
+ |fileref:$8|name:$32|filename:$256|
+ |---|---|--|
+ |someref|some_name|some_filename.xls|
+ |fref2|another_file|zyx_v2.csv|
+
+ @param [out] outds= (work.ms_triggerstp) Set to the name of a dataset to
+ contain the sessionId. If this dataset already exists, and contains the
+ sessionId, it will be appended to.
+ Format:
+ |sessionId:$36|
+ |---|
+ |20241028074744-54132-1730101664824|
+
+
SAS Macros
+ @li mf_getuniquefileref.sas
+ @li mf_getuniquename.sas
+ @li mp_abort.sas
+
+**/
+
+%macro ms_triggerstp(pgm
+ ,debug=131
+ ,inputparams=_null_
+ ,inputfiles=_null_
+ ,outds=work.ms_triggerstp
+ ,mdebug=0
+ );
+%local dbg mainref authref;
+%let mainref=%mf_getuniquefileref();
+%let authref=%mf_getuniquefileref();
+%if &inputparams=0 %then %let inputparams=_null_;
+
+%if &mdebug=1 %then %do;
+ %put &sysmacroname entry vars:;
+ %put _local_;
+%end;
+%else %let dbg=*;
+
+
+%mp_abort(iftrue=("&pgm"="")
+ ,mac=&sysmacroname
+ ,msg=%str(Program not provided)
+)
+
+/* avoid sending bom marker to API */
+%local optval;
+%let optval=%sysfunc(getoption(bomfile));
+options nobomfile;
+
+/* add params */
+data _null_;
+ file &mainref termstr=crlf lrecl=32767 mod;
+ length line $1000 name $32 value $32767;
+ if _n_=1 then call missing(of _all_);
+ set &inputparams;
+ put "--&boundary";
+ line=cats('Content-Disposition: form-data; name="',name,'"');
+ put line;
+ put ;
+ put value;
+run;
+
+/* parse input file list */
+%local webcount;
+%let webcount=0;
+data _null_;
+ set &inputfiles end=last;
+ length fileref $8 name $32 filename $256;
+ call symputx(cats('webref',_n_),fileref,'l');
+ call symputx(cats('webname',_n_),name,'l');
+ call symputx(cats('webfilename',_n_),filename,'l');
+ if last then do;
+ call symputx('webcount',_n_);
+ call missing(of _all_);
+ end;
+run;
+
+/* write out the input files */
+%local i;
+%do i=1 %to &webcount;
+ data _null_;
+ file &mainref termstr=crlf lrecl=32767 mod;
+ infile &&webref&i lrecl=32767;
+ if _n_ = 1 then do;
+ length line $32767;
+ line=cats(
+ 'Content-Disposition: form-data; name="'
+ ,"&&webname&i"
+ ,'"; filename="'
+ ,"&&webfilename&i"
+ ,'"'
+ );
+ put "--&boundary";
+ put line;
+ put "Content-Type: text/plain";
+ put ;
+ end;
+ input;
+ put _infile_; /* add the actual file to be sent */
+ run;
+%end;
+
+data _null_;
+ file &mainref termstr=crlf mod;
+ put "--&boundary--";
+run;
+
+data _null_;
+ file &authref lrecl=1000;
+ infile "&_sasjs_tokenfile" lrecl=1000;
+ input;
+ if _n_=1 then put "Content-Type: multipart/form-data; boundary=&boundary";
+ put _infile_;
+run;
+
+%if &mdebug=1 %then %do;
+ data _null_;
+ infile &authref;
+ input;
+ put _infile_;
+ data _null_;
+ infile &mainref;
+ input;
+ put _infile_;
+ run;
+%end;
+
+%local resp_path;
+%let resp_path=%sysfunc(pathname(work))/%mf_getuniquename();
+filename &outref "&resp_path" lrecl=32767;
+
+/* prepare request*/
+proc http method='POST' headerin=&authref in=&mainref out=&outref
+ url="&_sasjs_apiserverurl/SASjsApi/stp/trigger?%trim(
+ )_program=&pgm%str(&)_debug=131";
+%if &mdebug=1 %then %do;
+ debug level=2;
+%end;
+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)
+)
+
+/* reset options */
+options &optval;
+
+data work.%mf_getuniquename();
+ infile "&resp_path";
+ input
+
+%if &outlogds ne _null_ or &mdebug=1 %then %do;
+ %local matchstr chopout;
+ %let matchstr=SASJS_LOGS_SEPARATOR_163ee17b6ff24f028928972d80a26784;
+ %let chopout=%sysfunc(pathname(work))/%mf_getuniquename(prefix=chop);
+
+ %mp_chop("&resp_path"
+ ,matchvar=matchstr
+ ,keep=LAST
+ ,matchpoint=END
+ ,outfile="&chopout"
+ ,mdebug=&mdebug
+ )
+
+ data &outlogds;
+ infile "&chopout" lrecl=2000;
+ length line $2000;
+ line=_infile_;
+ %if &mdebug=1 %then %do;
+ putlog line=;
+ %end;
+ run;
+%end;
+
+%if &mdebug=1 %then %do;
+ %put &sysmacroname exit vars:;
+ %put _local_;
+%end;
+%else %do;
+ /* clear refs */
+ filename &authref;
+ filename &mainref;
+%end;
+%mend ms_triggerstp;
From d0102f7df01f766259614e0e9f8fe5bccc2cc741 Mon Sep 17 00:00:00 2001
From: github-actions
Date: Mon, 24 Feb 2025 11:00:24 +0000
Subject: [PATCH 2/2] chore: updating all.sas
---
all.sas | 215 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 215 insertions(+)
diff --git a/all.sas b/all.sas
index 3faa7ca4..9414b7ac 100644
--- a/all.sas
+++ b/all.sas
@@ -23113,6 +23113,221 @@ run;
%end;
%mend ms_testservice;
+/**
+ @file
+ @brief Triggers a SASjs Server STP using the /SASjsApi/code/trigger endpoint
+ @details Triggers the STP and returns the sessionId
+
+ Example:
+
+ %ms_triggerstp(/some/stored/program
+ ,debug=131
+ ,outds=work.myresults
+ )
+
+ @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 [in] inputparams=(_null_) A dataset containing name/value pairs in the
+ following format:
+ |name:$32|value:$10000|
+ |---|---|
+ |stpmacname|some value|
+ |mustbevalidname|can be anything, oops, %abort!!|
+ @param [in] inputfiles= (_null_) A dataset containing fileref/name/filename in
+ the following format:
+ |fileref:$8|name:$32|filename:$256|
+ |---|---|--|
+ |someref|some_name|some_filename.xls|
+ |fref2|another_file|zyx_v2.csv|
+
+ @param [out] outds= (work.ms_triggerstp) Set to the name of a dataset to
+ contain the sessionId. If this dataset already exists, and contains the
+ sessionId, it will be appended to.
+ Format:
+ |sessionId:$36|
+ |---|
+ |20241028074744-54132-1730101664824|
+
+ SAS Macros
+ @li mf_getuniquefileref.sas
+ @li mf_getuniquename.sas
+ @li mp_abort.sas
+
+**/
+
+%macro ms_triggerstp(pgm
+ ,debug=131
+ ,inputparams=_null_
+ ,inputfiles=_null_
+ ,outds=work.ms_triggerstp
+ ,mdebug=0
+ );
+%local dbg mainref authref;
+%let mainref=%mf_getuniquefileref();
+%let authref=%mf_getuniquefileref();
+%if &inputparams=0 %then %let inputparams=_null_;
+
+%if &mdebug=1 %then %do;
+ %put &sysmacroname entry vars:;
+ %put _local_;
+%end;
+%else %let dbg=*;
+
+
+%mp_abort(iftrue=("&pgm"="")
+ ,mac=&sysmacroname
+ ,msg=%str(Program not provided)
+)
+
+/* avoid sending bom marker to API */
+%local optval;
+%let optval=%sysfunc(getoption(bomfile));
+options nobomfile;
+
+/* add params */
+data _null_;
+ file &mainref termstr=crlf lrecl=32767 mod;
+ length line $1000 name $32 value $32767;
+ if _n_=1 then call missing(of _all_);
+ set &inputparams;
+ put "--&boundary";
+ line=cats('Content-Disposition: form-data; name="',name,'"');
+ put line;
+ put ;
+ put value;
+run;
+
+/* parse input file list */
+%local webcount;
+%let webcount=0;
+data _null_;
+ set &inputfiles end=last;
+ length fileref $8 name $32 filename $256;
+ call symputx(cats('webref',_n_),fileref,'l');
+ call symputx(cats('webname',_n_),name,'l');
+ call symputx(cats('webfilename',_n_),filename,'l');
+ if last then do;
+ call symputx('webcount',_n_);
+ call missing(of _all_);
+ end;
+run;
+
+/* write out the input files */
+%local i;
+%do i=1 %to &webcount;
+ data _null_;
+ file &mainref termstr=crlf lrecl=32767 mod;
+ infile &&webref&i lrecl=32767;
+ if _n_ = 1 then do;
+ length line $32767;
+ line=cats(
+ 'Content-Disposition: form-data; name="'
+ ,"&&webname&i"
+ ,'"; filename="'
+ ,"&&webfilename&i"
+ ,'"'
+ );
+ put "--&boundary";
+ put line;
+ put "Content-Type: text/plain";
+ put ;
+ end;
+ input;
+ put _infile_; /* add the actual file to be sent */
+ run;
+%end;
+
+data _null_;
+ file &mainref termstr=crlf mod;
+ put "--&boundary--";
+run;
+
+data _null_;
+ file &authref lrecl=1000;
+ infile "&_sasjs_tokenfile" lrecl=1000;
+ input;
+ if _n_=1 then put "Content-Type: multipart/form-data; boundary=&boundary";
+ put _infile_;
+run;
+
+%if &mdebug=1 %then %do;
+ data _null_;
+ infile &authref;
+ input;
+ put _infile_;
+ data _null_;
+ infile &mainref;
+ input;
+ put _infile_;
+ run;
+%end;
+
+%local resp_path;
+%let resp_path=%sysfunc(pathname(work))/%mf_getuniquename();
+filename &outref "&resp_path" lrecl=32767;
+
+/* prepare request*/
+proc http method='POST' headerin=&authref in=&mainref out=&outref
+ url="&_sasjs_apiserverurl/SASjsApi/stp/trigger?%trim(
+ )_program=&pgm%str(&)_debug=131";
+%if &mdebug=1 %then %do;
+ debug level=2;
+%end;
+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)
+)
+
+/* reset options */
+options &optval;
+
+data work.%mf_getuniquename();
+ infile "&resp_path";
+ input
+
+%if &outlogds ne _null_ or &mdebug=1 %then %do;
+ %local matchstr chopout;
+ %let matchstr=SASJS_LOGS_SEPARATOR_163ee17b6ff24f028928972d80a26784;
+ %let chopout=%sysfunc(pathname(work))/%mf_getuniquename(prefix=chop);
+
+ %mp_chop("&resp_path"
+ ,matchvar=matchstr
+ ,keep=LAST
+ ,matchpoint=END
+ ,outfile="&chopout"
+ ,mdebug=&mdebug
+ )
+
+ data &outlogds;
+ infile "&chopout" lrecl=2000;
+ length line $2000;
+ line=_infile_;
+ %if &mdebug=1 %then %do;
+ putlog line=;
+ %end;
+ run;
+%end;
+
+%if &mdebug=1 %then %do;
+ %put &sysmacroname exit vars:;
+ %put _local_;
+%end;
+%else %do;
+ /* clear refs */
+ filename &authref;
+ filename &mainref;
+%end;
+%mend ms_triggerstp;
/**
@file
@brief Send data to/from sasjs/server