From 756441384afa091a2e430d07e0ac2320638953f1 Mon Sep 17 00:00:00 2001 From: Allan Bowe Date: Wed, 18 Aug 2021 18:35:51 +0300 Subject: [PATCH 1/6] feat: adding first fcmp macro, mcf_string2file.sas --- README.md | 7 +++ all.sas | 79 +++++++++++++++++++++++++++++ build.py | 2 +- fcmp/mcf_string2file.sas | 79 +++++++++++++++++++++++++++++ main.dox | 13 +++++ sasjs/sasjsconfig.json | 4 +- tests/fcmp/mcf_string2file.test.sas | 52 +++++++++++++++++++ 7 files changed, 234 insertions(+), 2 deletions(-) create mode 100644 fcmp/mcf_string2file.sas create mode 100644 tests/fcmp/mcf_string2file.test.sas diff --git a/README.md b/README.md index f73a0c0..d732d72 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,13 @@ Documentation: https://core.sasjs.io - No X command - Prefixes: _mf_, _mp_ +**fcmp** library (SAS9/Viya) +- Function and macro names are identical, except for special cases +- Prefixes: _mcf_ + +The fcmp macros are used to generate fcmp functions, and can be used with or +without the `proc fcmp` wrapper. + **meta** library (SAS9 only) - OS independent diff --git a/all.sas b/all.sas index ffa7cad..de7d752 100644 --- a/all.sas +++ b/all.sas @@ -18804,3 +18804,82 @@ run; %inc "%sysfunc(pathname(work))/ml_json.lua"; %mend ml_json; +/** + @file + @brief Adds a string to a file + @details Creates an fcmp function for appending a string to an external file. + If the file does not exist, it is created. + + The function itself takes the following paramters: + + | PARAMETER | DESCRIPTION | + |------------|-------------| + | filepath $ | full path to the file| + | string $ | string to add to the file | + | mode $ | mode of the output - either APPEND (default) or CREATE | + + It returns 0 if successful, or -1 if an error occured. + + Usage: + + %mcf_string2file(wrap=YES, insert_cmplib=YES) + + data _null_; + rc=mcf_string2file( + "%sysfunc(pathname(work))/newfile.txt" + , "This is a test" + , "CREATE"); + run; + + data _null_; + infile "%sysfunc(pathname(work))/newfile.txt"; + input; + putlog _infile_; + run; + + @param [out] wrap= (NO) Choose YES to add the proc fcmp wrapper. + @param [out] insert_cmplib= (NO) Choose YES to insert the package into the + CMPLIB reference. + @param [out] lib= (work) The output library in which to create the catalog. + @param [out] cat= (sasjs) The output catalog in which to create the package. + @param [out] pkg= (utils) The output package in which to create the function. + Uses a 3 part format: libref.catalog.package + +**/ + +%macro mcf_string2file(wrap=NO + ,insert_cmplib=NO + ,lib=WORK + ,cat=SASJS + ,pkg=UTILS +)/*/STORE SOURCE*/; + +%if &wrap=YES %then %do; + proc fcmp outcat=&lib..&cat..&pkg; +%end; + +function mcf_string2file(filepath $, string $, mode $); + if mode='APPEND' then fmode='a'; + else fmode='o'; + length fref $8; + rc=filename(fref,filepath); + if (rc ne 0) then return( -1 ); + fid = fopen(fref,fmode); + if (fid = 0) then return( -1 ); + rc=fput(fid, string); + rc=fwrite(fid); + rc=fclose(fid); + rc=filename(fref); + return(0); +endsub; + + +%if &wrap=YES %then %do; + quit; +%end; + +%if &insert_cmplib=YES %then %do; + options insert=(CMPLIB=(&lib..&cat)); +%end; + +%mend mcf_string2file; \ No newline at end of file diff --git a/build.py b/build.py index 61e88be..1ad3046 100755 --- a/build.py +++ b/build.py @@ -84,7 +84,7 @@ options noquotelenmax; """ f = open('all.sas', "w") # r / r+ / rb / rb+ / w / wb f.write(header) -folders=['base','meta','metax','viya','lua'] +folders=['base','meta','metax','viya','lua','fcmp'] for folder in folders: filenames = [fn for fn in Path('./' + folder).iterdir() if fn.match("*.sas")] filenames.sort() diff --git a/fcmp/mcf_string2file.sas b/fcmp/mcf_string2file.sas new file mode 100644 index 0000000..add97ab --- /dev/null +++ b/fcmp/mcf_string2file.sas @@ -0,0 +1,79 @@ +/** + @file + @brief Adds a string to a file + @details Creates an fcmp function for appending a string to an external file. + If the file does not exist, it is created. + + The function itself takes the following (positional) parameters: + + | PARAMETER | DESCRIPTION | + |------------|-------------| + | filepath $ | full path to the file| + | string $ | string to add to the file | + | mode $ | mode of the output - either APPEND (default) or CREATE | + + It returns 0 if successful, or -1 if an error occured. + + Usage: + + %mcf_string2file(wrap=YES, insert_cmplib=YES) + + data _null_; + rc=mcf_string2file( + "%sysfunc(pathname(work))/newfile.txt" + , "This is a test" + , "CREATE"); + run; + + data _null_; + infile "%sysfunc(pathname(work))/newfile.txt"; + input; + putlog _infile_; + run; + + @param [out] wrap= (NO) Choose YES to add the proc fcmp wrapper. + @param [out] insert_cmplib= (NO) Choose YES to insert the package into the + CMPLIB reference. + @param [out] lib= (work) The output library in which to create the catalog. + @param [out] cat= (sasjs) The output catalog in which to create the package. + @param [out] pkg= (utils) The output package in which to create the function. + Uses a 3 part format: libref.catalog.package + +**/ + +%macro mcf_string2file(wrap=NO + ,insert_cmplib=NO + ,lib=WORK + ,cat=SASJS + ,pkg=UTILS +)/*/STORE SOURCE*/; + +%if &wrap=YES %then %do; + proc fcmp outcat=&lib..&cat..&pkg; +%end; + +function mcf_string2file(filepath $, string $, mode $); + if mode='APPEND' then fmode='a'; + else fmode='o'; + length fref $8; + rc=filename(fref,filepath); + if (rc ne 0) then return( -1 ); + fid = fopen(fref,fmode); + if (fid = 0) then return( -1 ); + rc=fput(fid, string); + rc=fwrite(fid); + rc=fclose(fid); + rc=filename(fref); + return(0); +endsub; + + +%if &wrap=YES %then %do; + quit; +%end; + +%if &insert_cmplib=YES %then %do; + options insert=(CMPLIB=(&lib..&cat)); +%end; + +%mend mcf_string2file; \ No newline at end of file diff --git a/main.dox b/main.dox index ad3e9de..33a1b14 100644 --- a/main.dox +++ b/main.dox @@ -20,6 +20,19 @@ */ +/*! \dir fcmp + * \brief Macros for generating FCMP functions + * \details These macros have the following attributes: + + * Macro name matches compiled function / subroutine name + * Prefixes: _mcf_, _mcs_ + + The macro part is just a wrapper for the underlying function / subroutine, + and has switches for including the proc fcmp / quit statements and whether + to insert the package into the CMPLIB option. + + */ + /*! \dir meta * \brief Metadata Aware Macros * \details These macros have the following attributes: diff --git a/sasjs/sasjsconfig.json b/sasjs/sasjsconfig.json index ef34a51..a3d2bff 100644 --- a/sasjs/sasjsconfig.json +++ b/sasjs/sasjsconfig.json @@ -2,11 +2,13 @@ "$schema": "https://cli.sasjs.io/sasjsconfig-schema.json", "macroFolders": [ "base", + "fcmp", "meta", "metax", "viya", "lua", - "tests/base" + "tests/base", + "tests/fcmp" ], "docConfig": { "displayMacroCore": false, diff --git a/tests/fcmp/mcf_string2file.test.sas b/tests/fcmp/mcf_string2file.test.sas new file mode 100644 index 0000000..7b58bac --- /dev/null +++ b/tests/fcmp/mcf_string2file.test.sas @@ -0,0 +1,52 @@ +/** + @file + @brief Testing mm_webout macro + +

SAS Macros

+ @li mcf_string2file.sas + @li mp_assert.sas + +**/ + + +%mcf_string2file(wrap=YES, insert_cmplib=YES) + +data _null_; + rc=mcf_string2file( + "%sysfunc(pathname(work))/newfile.txt" + , "line1" + , "APPEND"); + rc=mcf_string2file( + "%sysfunc(pathname(work))/newfile.txt" + , "line2" + , "APPEND"); +run; + +data _null_; + infile "%sysfunc(pathname(work))/newfile.txt"; + input; + if _n_=2 then call symputx('val',_infile_); +run; + +%mp_assert( + iftrue=(%str(&val)=%str(line2)), + desc=Check if APPEND works +) + +data _null_; + rc=mcf_string2file( + "%sysfunc(pathname(work))/newfile.txt" + , "creating" + , "CREATE"); +run; + +data _null_; + infile "%sysfunc(pathname(work))/newfile.txt"; + input; + if _n_=1 then call symputx('val2',_infile_); +run; + +%mp_assert( + iftrue=(%str(&val2)=%str(creating)), + desc=Check if CREATE works +) \ No newline at end of file From fc8ba2e36c1abf7e4824022d6b4b7358a7312e50 Mon Sep 17 00:00:00 2001 From: Allan Bowe Date: Wed, 18 Aug 2021 19:43:38 +0300 Subject: [PATCH 2/6] chore: moving files to tidy up docs --- sasjs/sasjsconfig.json | 7 +++---- tests/{fcmp => crossplatform}/mcf_string2file.test.sas | 0 tests/{base => crossplatform}/mf_existfileref.test.sas | 0 tests/{base => crossplatform}/mf_getapploc.test.sas | 0 tests/{base => crossplatform}/mf_getvarlist.test.sas | 0 tests/{base => crossplatform}/mp_abort.test.nofix.sas | 0 tests/{base => crossplatform}/mp_assertcolvals.test.sas | 0 tests/{base => crossplatform}/mp_assertdsobs.test.sas | 0 tests/{base => crossplatform}/mp_base64copy.test.sas | 0 tests/{base => crossplatform}/mp_ds2fmtds.test.sas | 0 tests/{base => crossplatform}/mp_ds2inserts.test.sas | 0 tests/{base => crossplatform}/mp_filtercheck.test.sas | 0 tests/{base => crossplatform}/mp_filtergenerate.test.sas | 0 tests/{base => crossplatform}/mp_filtervalidate.test.sas | 0 tests/{base => crossplatform}/mp_getddl.test.sas | 0 tests/{base => crossplatform}/mp_jsonout.test.sas | 0 tests/{base => crossplatform}/mp_lib2inserts.test.sas | 0 tests/{base => crossplatform}/mp_searchcols.test.sas | 0 tests/{base => crossplatform}/mp_validatecol.test.sas | 0 tests/{meta => sas9only}/mm_webout.test.sas | 0 tests/{viya => viyaonly}/mfv_existfile.test.sas | 0 tests/{viya => viyaonly}/mfv_existfolder.test.sas | 0 tests/{viya => viyaonly}/mv_createfile.test.sas | 0 tests/{viya => viyaonly}/mv_createfolder.test.sas | 0 tests/{viya => viyaonly}/mv_createwebservice.test.sas | 0 tests/{viya => viyaonly}/mv_getjobcode.test.sas | 0 tests/{viya => viyaonly}/mv_getjoblog.test.sas | 0 tests/{viya => viyaonly}/mv_getjobresult.test.sas | 0 tests/{viya => viyaonly}/mv_jobflow.test.1.sas | 0 tests/{viya => viyaonly}/mv_jobflow.test.2.sas | 0 tests/{viya => viyaonly}/mv_registerclient.test.1.sas | 0 tests/{viya => viyaonly}/mv_registerclient.test.2.sas | 0 tests/{viya => viyaonly}/mv_webout.test.sas | 0 33 files changed, 3 insertions(+), 4 deletions(-) rename tests/{fcmp => crossplatform}/mcf_string2file.test.sas (100%) rename tests/{base => crossplatform}/mf_existfileref.test.sas (100%) rename tests/{base => crossplatform}/mf_getapploc.test.sas (100%) rename tests/{base => crossplatform}/mf_getvarlist.test.sas (100%) rename tests/{base => crossplatform}/mp_abort.test.nofix.sas (100%) rename tests/{base => crossplatform}/mp_assertcolvals.test.sas (100%) rename tests/{base => crossplatform}/mp_assertdsobs.test.sas (100%) rename tests/{base => crossplatform}/mp_base64copy.test.sas (100%) rename tests/{base => crossplatform}/mp_ds2fmtds.test.sas (100%) rename tests/{base => crossplatform}/mp_ds2inserts.test.sas (100%) rename tests/{base => crossplatform}/mp_filtercheck.test.sas (100%) rename tests/{base => crossplatform}/mp_filtergenerate.test.sas (100%) rename tests/{base => crossplatform}/mp_filtervalidate.test.sas (100%) rename tests/{base => crossplatform}/mp_getddl.test.sas (100%) rename tests/{base => crossplatform}/mp_jsonout.test.sas (100%) rename tests/{base => crossplatform}/mp_lib2inserts.test.sas (100%) rename tests/{base => crossplatform}/mp_searchcols.test.sas (100%) rename tests/{base => crossplatform}/mp_validatecol.test.sas (100%) rename tests/{meta => sas9only}/mm_webout.test.sas (100%) rename tests/{viya => viyaonly}/mfv_existfile.test.sas (100%) rename tests/{viya => viyaonly}/mfv_existfolder.test.sas (100%) rename tests/{viya => viyaonly}/mv_createfile.test.sas (100%) rename tests/{viya => viyaonly}/mv_createfolder.test.sas (100%) rename tests/{viya => viyaonly}/mv_createwebservice.test.sas (100%) rename tests/{viya => viyaonly}/mv_getjobcode.test.sas (100%) rename tests/{viya => viyaonly}/mv_getjoblog.test.sas (100%) rename tests/{viya => viyaonly}/mv_getjobresult.test.sas (100%) rename tests/{viya => viyaonly}/mv_jobflow.test.1.sas (100%) rename tests/{viya => viyaonly}/mv_jobflow.test.2.sas (100%) rename tests/{viya => viyaonly}/mv_registerclient.test.1.sas (100%) rename tests/{viya => viyaonly}/mv_registerclient.test.2.sas (100%) rename tests/{viya => viyaonly}/mv_webout.test.sas (100%) diff --git a/sasjs/sasjsconfig.json b/sasjs/sasjsconfig.json index a3d2bff..3a870d2 100644 --- a/sasjs/sasjsconfig.json +++ b/sasjs/sasjsconfig.json @@ -7,8 +7,7 @@ "metax", "viya", "lua", - "tests/base", - "tests/fcmp" + "tests/crossplatform" ], "docConfig": { "displayMacroCore": false, @@ -35,7 +34,7 @@ "allowInsecureRequests": false, "appLoc": "/Public/temp/macrocore", "macroFolders": [ - "tests/viya" + "tests/viyaonly" ], "programFolders": [], "deployConfig": { @@ -50,7 +49,7 @@ "serverType": "SAS9", "appLoc": "/Shared Data/temp/macrocore", "macroFolders": [ - "tests/meta" + "tests/sas9only" ] } ] diff --git a/tests/fcmp/mcf_string2file.test.sas b/tests/crossplatform/mcf_string2file.test.sas similarity index 100% rename from tests/fcmp/mcf_string2file.test.sas rename to tests/crossplatform/mcf_string2file.test.sas diff --git a/tests/base/mf_existfileref.test.sas b/tests/crossplatform/mf_existfileref.test.sas similarity index 100% rename from tests/base/mf_existfileref.test.sas rename to tests/crossplatform/mf_existfileref.test.sas diff --git a/tests/base/mf_getapploc.test.sas b/tests/crossplatform/mf_getapploc.test.sas similarity index 100% rename from tests/base/mf_getapploc.test.sas rename to tests/crossplatform/mf_getapploc.test.sas diff --git a/tests/base/mf_getvarlist.test.sas b/tests/crossplatform/mf_getvarlist.test.sas similarity index 100% rename from tests/base/mf_getvarlist.test.sas rename to tests/crossplatform/mf_getvarlist.test.sas diff --git a/tests/base/mp_abort.test.nofix.sas b/tests/crossplatform/mp_abort.test.nofix.sas similarity index 100% rename from tests/base/mp_abort.test.nofix.sas rename to tests/crossplatform/mp_abort.test.nofix.sas diff --git a/tests/base/mp_assertcolvals.test.sas b/tests/crossplatform/mp_assertcolvals.test.sas similarity index 100% rename from tests/base/mp_assertcolvals.test.sas rename to tests/crossplatform/mp_assertcolvals.test.sas diff --git a/tests/base/mp_assertdsobs.test.sas b/tests/crossplatform/mp_assertdsobs.test.sas similarity index 100% rename from tests/base/mp_assertdsobs.test.sas rename to tests/crossplatform/mp_assertdsobs.test.sas diff --git a/tests/base/mp_base64copy.test.sas b/tests/crossplatform/mp_base64copy.test.sas similarity index 100% rename from tests/base/mp_base64copy.test.sas rename to tests/crossplatform/mp_base64copy.test.sas diff --git a/tests/base/mp_ds2fmtds.test.sas b/tests/crossplatform/mp_ds2fmtds.test.sas similarity index 100% rename from tests/base/mp_ds2fmtds.test.sas rename to tests/crossplatform/mp_ds2fmtds.test.sas diff --git a/tests/base/mp_ds2inserts.test.sas b/tests/crossplatform/mp_ds2inserts.test.sas similarity index 100% rename from tests/base/mp_ds2inserts.test.sas rename to tests/crossplatform/mp_ds2inserts.test.sas diff --git a/tests/base/mp_filtercheck.test.sas b/tests/crossplatform/mp_filtercheck.test.sas similarity index 100% rename from tests/base/mp_filtercheck.test.sas rename to tests/crossplatform/mp_filtercheck.test.sas diff --git a/tests/base/mp_filtergenerate.test.sas b/tests/crossplatform/mp_filtergenerate.test.sas similarity index 100% rename from tests/base/mp_filtergenerate.test.sas rename to tests/crossplatform/mp_filtergenerate.test.sas diff --git a/tests/base/mp_filtervalidate.test.sas b/tests/crossplatform/mp_filtervalidate.test.sas similarity index 100% rename from tests/base/mp_filtervalidate.test.sas rename to tests/crossplatform/mp_filtervalidate.test.sas diff --git a/tests/base/mp_getddl.test.sas b/tests/crossplatform/mp_getddl.test.sas similarity index 100% rename from tests/base/mp_getddl.test.sas rename to tests/crossplatform/mp_getddl.test.sas diff --git a/tests/base/mp_jsonout.test.sas b/tests/crossplatform/mp_jsonout.test.sas similarity index 100% rename from tests/base/mp_jsonout.test.sas rename to tests/crossplatform/mp_jsonout.test.sas diff --git a/tests/base/mp_lib2inserts.test.sas b/tests/crossplatform/mp_lib2inserts.test.sas similarity index 100% rename from tests/base/mp_lib2inserts.test.sas rename to tests/crossplatform/mp_lib2inserts.test.sas diff --git a/tests/base/mp_searchcols.test.sas b/tests/crossplatform/mp_searchcols.test.sas similarity index 100% rename from tests/base/mp_searchcols.test.sas rename to tests/crossplatform/mp_searchcols.test.sas diff --git a/tests/base/mp_validatecol.test.sas b/tests/crossplatform/mp_validatecol.test.sas similarity index 100% rename from tests/base/mp_validatecol.test.sas rename to tests/crossplatform/mp_validatecol.test.sas diff --git a/tests/meta/mm_webout.test.sas b/tests/sas9only/mm_webout.test.sas similarity index 100% rename from tests/meta/mm_webout.test.sas rename to tests/sas9only/mm_webout.test.sas diff --git a/tests/viya/mfv_existfile.test.sas b/tests/viyaonly/mfv_existfile.test.sas similarity index 100% rename from tests/viya/mfv_existfile.test.sas rename to tests/viyaonly/mfv_existfile.test.sas diff --git a/tests/viya/mfv_existfolder.test.sas b/tests/viyaonly/mfv_existfolder.test.sas similarity index 100% rename from tests/viya/mfv_existfolder.test.sas rename to tests/viyaonly/mfv_existfolder.test.sas diff --git a/tests/viya/mv_createfile.test.sas b/tests/viyaonly/mv_createfile.test.sas similarity index 100% rename from tests/viya/mv_createfile.test.sas rename to tests/viyaonly/mv_createfile.test.sas diff --git a/tests/viya/mv_createfolder.test.sas b/tests/viyaonly/mv_createfolder.test.sas similarity index 100% rename from tests/viya/mv_createfolder.test.sas rename to tests/viyaonly/mv_createfolder.test.sas diff --git a/tests/viya/mv_createwebservice.test.sas b/tests/viyaonly/mv_createwebservice.test.sas similarity index 100% rename from tests/viya/mv_createwebservice.test.sas rename to tests/viyaonly/mv_createwebservice.test.sas diff --git a/tests/viya/mv_getjobcode.test.sas b/tests/viyaonly/mv_getjobcode.test.sas similarity index 100% rename from tests/viya/mv_getjobcode.test.sas rename to tests/viyaonly/mv_getjobcode.test.sas diff --git a/tests/viya/mv_getjoblog.test.sas b/tests/viyaonly/mv_getjoblog.test.sas similarity index 100% rename from tests/viya/mv_getjoblog.test.sas rename to tests/viyaonly/mv_getjoblog.test.sas diff --git a/tests/viya/mv_getjobresult.test.sas b/tests/viyaonly/mv_getjobresult.test.sas similarity index 100% rename from tests/viya/mv_getjobresult.test.sas rename to tests/viyaonly/mv_getjobresult.test.sas diff --git a/tests/viya/mv_jobflow.test.1.sas b/tests/viyaonly/mv_jobflow.test.1.sas similarity index 100% rename from tests/viya/mv_jobflow.test.1.sas rename to tests/viyaonly/mv_jobflow.test.1.sas diff --git a/tests/viya/mv_jobflow.test.2.sas b/tests/viyaonly/mv_jobflow.test.2.sas similarity index 100% rename from tests/viya/mv_jobflow.test.2.sas rename to tests/viyaonly/mv_jobflow.test.2.sas diff --git a/tests/viya/mv_registerclient.test.1.sas b/tests/viyaonly/mv_registerclient.test.1.sas similarity index 100% rename from tests/viya/mv_registerclient.test.1.sas rename to tests/viyaonly/mv_registerclient.test.1.sas diff --git a/tests/viya/mv_registerclient.test.2.sas b/tests/viyaonly/mv_registerclient.test.2.sas similarity index 100% rename from tests/viya/mv_registerclient.test.2.sas rename to tests/viyaonly/mv_registerclient.test.2.sas diff --git a/tests/viya/mv_webout.test.sas b/tests/viyaonly/mv_webout.test.sas similarity index 100% rename from tests/viya/mv_webout.test.sas rename to tests/viyaonly/mv_webout.test.sas From bc410a9135b18710f080d460a559e6009f3c68a2 Mon Sep 17 00:00:00 2001 From: Allan Bowe Date: Wed, 18 Aug 2021 19:55:05 +0300 Subject: [PATCH 3/6] chore: fixing docs for tests --- package.json | 2 +- sasjs/sasjsconfig.json | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 3d6255b..77a59f2 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "main": "index.js", "scripts": { "build": "sasjs cbd -t viya", - "docs": "sasjs doc && ./sasjs/utils/build.sh", + "docs": "sasjs doc -t docsonly && ./sasjs/utils/build.sh", "test": "sasjs test -t viya", "lint": "sasjs lint", "prepare": "git rev-parse --git-dir && git config core.hooksPath ./.git-hooks || true" diff --git a/sasjs/sasjsconfig.json b/sasjs/sasjsconfig.json index 3a870d2..2a885b8 100644 --- a/sasjs/sasjsconfig.json +++ b/sasjs/sasjsconfig.json @@ -51,6 +51,14 @@ "macroFolders": [ "tests/sas9only" ] + }, + { + "name": "docsonly", + "serverType": "SAS9", + "macroFolders": [ + "tests/sas9only", + "tests/viyaonly" + ] } ] } \ No newline at end of file From 005af0ecf8aef1f871d618a4a75757dca1d5f000 Mon Sep 17 00:00:00 2001 From: Allan Bowe Date: Wed, 18 Aug 2021 23:36:12 +0300 Subject: [PATCH 4/6] feat: new mf_existfunction macro --- base/mf_existfunction.sas | 33 +++++++++++++++++++ tests/crossplatform/mf_existfunction.test.sas | 22 +++++++++++++ 2 files changed, 55 insertions(+) create mode 100644 base/mf_existfunction.sas create mode 100644 tests/crossplatform/mf_existfunction.test.sas diff --git a/base/mf_existfunction.sas b/base/mf_existfunction.sas new file mode 100644 index 0000000..937ced2 --- /dev/null +++ b/base/mf_existfunction.sas @@ -0,0 +1,33 @@ +/** + @file + @brief Checks if a function exists + @details Returns 1 if the function exists, else 0 + Usage: + + %put %mf_existfunction(CAT); + %put %mf_existfunction(DOG); + + Full credit to [Bart](https://sasensei.com/user/305) for the vfunc pointer + and the tidy approach for pure macro data set filtering. + Check out his [SAS Packages](https://github.com/yabwon/SAS_PACKAGES) + framework! + + @param [in] name (positional) - function name + + @author Allan Bowe +**/ +/** @cond */ + +%macro mf_existfunction(name +)/*/STORE SOURCE*/; + + %local dsid rc exist; + %let dsid=%sysfunc(open(sashelp.vfunc(where=(fncname="%upcase(&name)")))); + %let exist = %sysfunc(fetch(&dsid, NOSET)); + %let rc = %sysfunc(close(&dsid)); + + %sysevalf(0 = &exist) + +%mend mf_existfunction; + +/** @endcond */ \ No newline at end of file diff --git a/tests/crossplatform/mf_existfunction.test.sas b/tests/crossplatform/mf_existfunction.test.sas new file mode 100644 index 0000000..cd00373 --- /dev/null +++ b/tests/crossplatform/mf_existfunction.test.sas @@ -0,0 +1,22 @@ +/** + @file + @brief Testing mf_existfunction macro + +

SAS Macros

+ @li mf_existfunction.sas + @li mp_assert.sas + +**/ + +%mp_assert( + iftrue=(%mf_existfunction(CAT)=1), + desc=Checking if CAT function exists, + outds=work.test_results +) + +%mp_assert( + iftrue=(%mf_existfunction(DOG)=0), + desc=Checking DOG function does not exist, + outds=work.test_results +) + From 8ddb86785cb9bff8358738bcba336bfeeea388cc Mon Sep 17 00:00:00 2001 From: Allan Bowe Date: Wed, 18 Aug 2021 23:45:45 +0300 Subject: [PATCH 5/6] feat: new fcmp stpsrv_header function --- all.sas | 129 +++++++++++++++++- base/mf_existfunction.sas | 4 +- fcmp/mcf_stpsrv_header.sas | 94 +++++++++++++ .../crossplatform/mcf_stpsrv_header.test.sas | 39 ++++++ tests/crossplatform/mcf_string2file.test.sas | 2 +- 5 files changed, 265 insertions(+), 3 deletions(-) create mode 100644 fcmp/mcf_stpsrv_header.sas create mode 100644 tests/crossplatform/mcf_stpsrv_header.test.sas diff --git a/all.sas b/all.sas index de7d752..49f955b 100644 --- a/all.sas +++ b/all.sas @@ -147,6 +147,40 @@ options noquotelenmax; %end; %mend mf_existfileref;/** + @file + @brief Checks if a function exists + @details Returns 1 if the function exists, else 0. Note that this function + can be slow as it needs to open the sashelp.vfuncs table. + + Usage: + + %put %mf_existfunction(CAT); + %put %mf_existfunction(DOG); + + Full credit to [Bart](https://sasensei.com/user/305) for the vfunc pointer + and the tidy approach for pure macro data set filtering. + Check out his [SAS Packages](https://github.com/yabwon/SAS_PACKAGES) + framework! + + @param [in] name (positional) - function name + + @author Allan Bowe +**/ +/** @cond */ + +%macro mf_existfunction(name +)/*/STORE SOURCE*/; + + %local dsid rc exist; + %let dsid=%sysfunc(open(sashelp.vfunc(where=(fncname="%upcase(&name)")))); + %let exist = %sysfunc(fetch(&dsid, NOSET)); + %let rc = %sysfunc(close(&dsid)); + + %sysevalf(0 = &exist) + +%mend mf_existfunction; + +/** @endcond *//** @file @brief Checks if a variable exists in a data set. @details Returns 0 if the variable does NOT exist, and return the position of @@ -18805,12 +18839,105 @@ run; %mend ml_json; /** + @file + @brief Provides a replacement for the stpsrv_header function + @details The stpsrv_header is normally a built-in function, used to set the + headers for SAS 9 Stored Processes as documented here: + https://go.documentation.sas.com/doc/en/itechcdc/9.4/stpug/srvhead.htm + + The purpose of this custom function is to provide a replacement when running + similar code as a web service against + [sasjs/server](https://github.com/sasjs/server). It operates by creating a + text file with the headers. The location of this text file is determined by + a macro variable (`sasjs_stpsrv_header_loc`) which needs to be injected into + each service by the calling process, eg: + + %let sasjs_stpsrv_header_loc = C:/temp/some_uuid/stpsrv_header.txt; + + Note - the function works by appending headers to the file. If multiple same- + named headers are provided, they will all be appended - the calling process + needs to pick up the last one. This will mean removing the attribute if the + final record has an empty value. + + The function takes the following (positional) parameters: + + | PARAMETER | DESCRIPTION | + |------------|-------------| + | name $ | name of the header attribute to create| + | value $ | value of the header attribute| + + It returns 0 if successful, or -1 if an error occured. + + Usage: + + %let sasjs_stpsrv_header_loc=%sysfunc(pathname(work))/stpsrv_header.txt; + + %mcf_stpsrv_header(wrap=YES, insert_cmplib=YES) + + data _null_; + rc=stpsrv_header('Content-type','application/text'); + rc=stpsrv_header('Content-disposition',"attachment; filename=file.txt"); + run; + + data _null_; + infile "&sasjs_stpsrv_header_loc"; + input; + putlog _infile_; + run; + + + @param [out] wrap= (NO) Choose YES to add the proc fcmp wrapper. + @param [out] insert_cmplib= (NO) Choose YES to insert the package into the + CMPLIB reference. + @param [out] lib= (work) The output library in which to create the catalog. + @param [out] cat= (sasjs) The output catalog in which to create the package. + @param [out] pkg= (utils) The output package in which to create the function. + Uses a 3 part format: libref.catalog.package + +**/ + +%macro mcf_stpsrv_header(wrap=NO + ,insert_cmplib=NO + ,lib=WORK + ,cat=SASJS + ,pkg=UTILS +)/*/STORE SOURCE*/; + +%if &wrap=YES %then %do; + proc fcmp outcat=&lib..&cat..&pkg; +%end; + +function stpsrv_header(name $, value $); + length loc $128 val $512; + loc=symget('sasjs_stpsrv_header_loc'); + val=trim(name)!!': '!!value; + length fref $8; + rc=filename(fref,loc); + if (rc ne 0) then return( -1 ); + fid = fopen(fref,'a'); + if (fid = 0) then return( -1 ); + rc=fput(fid, val); + rc=fwrite(fid); + rc=fclose(fid); + rc=filename(fref); + return(0); +endsub; + +%if &wrap=YES %then %do; + quit; +%end; + +%if &insert_cmplib=YES %then %do; + options insert=(CMPLIB=(&lib..&cat)); +%end; + +%mend mcf_stpsrv_header;/** @file @brief Adds a string to a file @details Creates an fcmp function for appending a string to an external file. If the file does not exist, it is created. - The function itself takes the following paramters: + The function itself takes the following (positional) parameters: | PARAMETER | DESCRIPTION | |------------|-------------| diff --git a/base/mf_existfunction.sas b/base/mf_existfunction.sas index 937ced2..f875d48 100644 --- a/base/mf_existfunction.sas +++ b/base/mf_existfunction.sas @@ -1,7 +1,9 @@ /** @file @brief Checks if a function exists - @details Returns 1 if the function exists, else 0 + @details Returns 1 if the function exists, else 0. Note that this function + can be slow as it needs to open the sashelp.vfuncs table. + Usage: %put %mf_existfunction(CAT); diff --git a/fcmp/mcf_stpsrv_header.sas b/fcmp/mcf_stpsrv_header.sas new file mode 100644 index 0000000..3f00d17 --- /dev/null +++ b/fcmp/mcf_stpsrv_header.sas @@ -0,0 +1,94 @@ +/** + @file + @brief Provides a replacement for the stpsrv_header function + @details The stpsrv_header is normally a built-in function, used to set the + headers for SAS 9 Stored Processes as documented here: + https://go.documentation.sas.com/doc/en/itechcdc/9.4/stpug/srvhead.htm + + The purpose of this custom function is to provide a replacement when running + similar code as a web service against + [sasjs/server](https://github.com/sasjs/server). It operates by creating a + text file with the headers. The location of this text file is determined by + a macro variable (`sasjs_stpsrv_header_loc`) which needs to be injected into + each service by the calling process, eg: + + %let sasjs_stpsrv_header_loc = C:/temp/some_uuid/stpsrv_header.txt; + + Note - the function works by appending headers to the file. If multiple same- + named headers are provided, they will all be appended - the calling process + needs to pick up the last one. This will mean removing the attribute if the + final record has an empty value. + + The function takes the following (positional) parameters: + + | PARAMETER | DESCRIPTION | + |------------|-------------| + | name $ | name of the header attribute to create| + | value $ | value of the header attribute| + + It returns 0 if successful, or -1 if an error occured. + + Usage: + + %let sasjs_stpsrv_header_loc=%sysfunc(pathname(work))/stpsrv_header.txt; + + %mcf_stpsrv_header(wrap=YES, insert_cmplib=YES) + + data _null_; + rc=stpsrv_header('Content-type','application/text'); + rc=stpsrv_header('Content-disposition',"attachment; filename=file.txt"); + run; + + data _null_; + infile "&sasjs_stpsrv_header_loc"; + input; + putlog _infile_; + run; + + + @param [out] wrap= (NO) Choose YES to add the proc fcmp wrapper. + @param [out] insert_cmplib= (NO) Choose YES to insert the package into the + CMPLIB reference. + @param [out] lib= (work) The output library in which to create the catalog. + @param [out] cat= (sasjs) The output catalog in which to create the package. + @param [out] pkg= (utils) The output package in which to create the function. + Uses a 3 part format: libref.catalog.package + +**/ + +%macro mcf_stpsrv_header(wrap=NO + ,insert_cmplib=NO + ,lib=WORK + ,cat=SASJS + ,pkg=UTILS +)/*/STORE SOURCE*/; + +%if &wrap=YES %then %do; + proc fcmp outcat=&lib..&cat..&pkg; +%end; + +function stpsrv_header(name $, value $); + length loc $128 val $512; + loc=symget('sasjs_stpsrv_header_loc'); + val=trim(name)!!': '!!value; + length fref $8; + rc=filename(fref,loc); + if (rc ne 0) then return( -1 ); + fid = fopen(fref,'a'); + if (fid = 0) then return( -1 ); + rc=fput(fid, val); + rc=fwrite(fid); + rc=fclose(fid); + rc=filename(fref); + return(0); +endsub; + +%if &wrap=YES %then %do; + quit; +%end; + +%if &insert_cmplib=YES %then %do; + options insert=(CMPLIB=(&lib..&cat)); +%end; + +%mend mcf_stpsrv_header; \ No newline at end of file diff --git a/tests/crossplatform/mcf_stpsrv_header.test.sas b/tests/crossplatform/mcf_stpsrv_header.test.sas new file mode 100644 index 0000000..5b87d57 --- /dev/null +++ b/tests/crossplatform/mcf_stpsrv_header.test.sas @@ -0,0 +1,39 @@ +/** + @file + @brief Testing mcf_stpsrv_header macro + +

SAS Macros

+ @li mcf_stpsrv_header.sas + @li mp_assert.sas + +**/ + +%let sasjs_stpsrv_header_loc=%sysfunc(pathname(work))/stpsrv_header.txt; + +%mcf_stpsrv_header(wrap=YES, insert_cmplib=YES) + +data _null_; + rc=stpsrv_header('Content-type','application/text'); + rc=stpsrv_header('Content-disposition',"attachment; filename=file.txt"); +run; + +%let test1=FAIL; +%let test2=FAIL; + +data _null_; + infile "&sasjs_stpsrv_header_loc"; + input; + if _n_=1 and _infile_='Content-type: application/text' + then call symputx('test1','PASS'); + else if _n_=2 & _infile_='Content-disposition: attachment; filename=file.txt' + then call symputx('test2','PASS'); +run; + +%mp_assert( + iftrue=(%str(&test1)=%str(PASS)), + desc=Check first header line +) +%mp_assert( + iftrue=(%str(&test2)=%str(PASS)), + desc=Check second header line +) \ No newline at end of file diff --git a/tests/crossplatform/mcf_string2file.test.sas b/tests/crossplatform/mcf_string2file.test.sas index 7b58bac..4de900e 100644 --- a/tests/crossplatform/mcf_string2file.test.sas +++ b/tests/crossplatform/mcf_string2file.test.sas @@ -1,6 +1,6 @@ /** @file - @brief Testing mm_webout macro + @brief Testing mcf_string2file macro

SAS Macros

@li mcf_string2file.sas From 078bdbeecf5a5a172fae7f3e4e0ec2db77c59c95 Mon Sep 17 00:00:00 2001 From: Allan Bowe Date: Wed, 18 Aug 2021 23:47:17 +0300 Subject: [PATCH 6/6] chore: bumping devDependency (sasjs cli) --- package-lock.json | 226 ++++++++++++++++++---------------------------- package.json | 2 +- 2 files changed, 90 insertions(+), 138 deletions(-) diff --git a/package-lock.json b/package-lock.json index b5c04fc..c17710b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,44 +7,43 @@ "name": "@sasjs/core", "license": "MIT", "devDependencies": { - "@sasjs/cli": "2.33.3" + "@sasjs/cli": "^2.37.2" } }, "node_modules/@sasjs/adapter": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/@sasjs/adapter/-/adapter-2.8.9.tgz", - "integrity": "sha512-8UChcZlqqlmaMMaKOCr2Bc1h+i2KVDY0FINlPXQN5PdAgEMd8dbxI2p9bsiI1yjYjOBO9LuMl7B79/mwYCtyEw==", + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/@sasjs/adapter/-/adapter-2.10.0.tgz", + "integrity": "sha512-GbvyIgbODnAJaBaz/Tz8/IwcujNOsZcwzbIuKQtG5y13BzgVPtx/e7b2TAhdoBqd+8uVh0CdrSDfOV/SuvPurg==", "dev": true, "dependencies": { - "@sasjs/utils": "^2.21.0", + "@sasjs/utils": "^2.27.1", "axios": "^0.21.1", "axios-cookiejar-support": "^1.0.1", "form-data": "^4.0.0", "https": "^1.0.0", - "jwt-decode": "^3.1.2", - "tough-cookie": "^4.0.0", - "url": "^0.11.0" + "tough-cookie": "^4.0.0" + }, + "engines": { + "node": ">=15" } }, "node_modules/@sasjs/cli": { - "version": "2.33.3", - "resolved": "https://registry.npmjs.org/@sasjs/cli/-/cli-2.33.3.tgz", - "integrity": "sha512-y1uFM5MEE6eoKLrPUJbweDt4njSy9Y3CS5w5/U2xwNbiAyhiPXgkwCHjCQ8Qg+0rQnMvyNEn6qJuJZ3udc6T7w==", + "version": "2.37.2", + "resolved": "https://registry.npmjs.org/@sasjs/cli/-/cli-2.37.2.tgz", + "integrity": "sha512-Bcm8UFN9Y/ZON4T31Gu9mf1REn1pZoStHFVrix/yp7mchFt5rrrY5RbIqO/AI1jzhShSVg9P7oU4VPJrqki+SA==", "dev": true, "dependencies": { - "@sasjs/adapter": "2.8.9", - "@sasjs/core": "2.35.3", + "@sasjs/adapter": "2.10.0", + "@sasjs/core": "2.35.4", "@sasjs/lint": "1.11.2", - "@sasjs/utils": "2.23.3", - "@types/url-parse": "1.4.3", - "btoa": "1.2.1", + "@sasjs/utils": "2.27.1", "chalk": "4.1.1", "csv-stringify": "5.6.2", "dotenv": "10.0.0", "esm": "3.2.25", "find": "0.3.0", - "fs-extra": "10.0.0", "get-installed-path": "4.0.8", + "js-base64": "3.6.1", "jsdom": "16.6.0", "jwt-decode": "3.1.2", "lodash.groupby": "4.6.0", @@ -60,9 +59,9 @@ } }, "node_modules/@sasjs/core": { - "version": "2.35.3", - "resolved": "https://registry.npmjs.org/@sasjs/core/-/core-2.35.3.tgz", - "integrity": "sha512-3o5PU6DkihpA+Aibt1lRy4USqJI0VFa+wNsKCD+bUD2DLZICU3JablZQxwAPH70VWJGXAUJtDFj0T/iRo5Devg==", + "version": "2.35.4", + "resolved": "https://registry.npmjs.org/@sasjs/core/-/core-2.35.4.tgz", + "integrity": "sha512-Exr3+yRdvacKvbXQoi1RfGHi5NtZUkc7RwFNkemHTFXLYaIzPI8CGSCaQmKkwM1UteOJly2e2pw2YT6kHNY1NA==", "dev": true }, "node_modules/@sasjs/lint": { @@ -75,11 +74,12 @@ } }, "node_modules/@sasjs/utils": { - "version": "2.23.3", - "resolved": "https://registry.npmjs.org/@sasjs/utils/-/utils-2.23.3.tgz", - "integrity": "sha512-tEh4mGG80eUxSLpbPivA0vl4akMdauL+yZrLn1uUM8EyiXPvlcWPkQTeN6oHbyyAH108D9cfEBidTePZh1p5VQ==", + "version": "2.27.1", + "resolved": "https://registry.npmjs.org/@sasjs/utils/-/utils-2.27.1.tgz", + "integrity": "sha512-CYTQwEj89cc7H3tGiQQcyDkZYaWRc1HZJpOF8o2RHYS37fIAOy0SyyJdq6mcQ74Nb1u5AmFXPFIvnRCMEcTYeQ==", "dev": true, "dependencies": { + "@types/fs-extra": "^9.0.11", "@types/prompts": "^2.0.13", "chalk": "^4.1.1", "cli-table": "^0.3.6", @@ -87,7 +87,11 @@ "fs-extra": "^10.0.0", "jwt-decode": "^3.1.2", "prompts": "^2.4.1", + "rimraf": "^3.0.2", "valid-url": "^1.0.9" + }, + "engines": { + "node": ">=15" } }, "node_modules/@tootallnate/once": { @@ -99,6 +103,15 @@ "node": ">= 6" } }, + "node_modules/@types/fs-extra": { + "version": "9.0.12", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.12.tgz", + "integrity": "sha512-I+bsBr67CurCGnSenZZ7v94gd3tc3+Aj2taxMT4yu4ABLuOgOjeFxX3dokG24ztSRg5tnT00sL8BszO7gSMoIw==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/node": { "version": "16.3.1", "resolved": "https://registry.npmjs.org/@types/node/-/node-16.3.1.tgz", @@ -121,12 +134,6 @@ "dev": true, "peer": true }, - "node_modules/@types/url-parse": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/@types/url-parse/-/url-parse-1.4.3.tgz", - "integrity": "sha512-4kHAkbV/OfW2kb5BLVUuUMoumB3CP8rHqlw48aHvFy5tf9ER0AfOonBlX29l/DD68G70DmyhRlSYfQPSYpC5Vw==", - "dev": true - }, "node_modules/abab": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.5.tgz", @@ -298,18 +305,6 @@ "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==", "dev": true }, - "node_modules/btoa": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/btoa/-/btoa-1.2.1.tgz", - "integrity": "sha512-SB4/MIGlsiVkMcHmT+pSmIPoNDoHg+7cMzmt3Uxt628MTz2487DKSqK/fuhFBrkuqrYv5UCEnACpF4dTFNKc/g==", - "dev": true, - "bin": { - "btoa": "bin/btoa.js" - }, - "engines": { - "node": ">= 0.4.0" - } - }, "node_modules/buffer": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", @@ -657,9 +652,9 @@ } }, "node_modules/follow-redirects": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.1.tgz", - "integrity": "sha512-HWqDgT7ZEkqRzBvc2s64vSZ/hfOceEol3ac/7tKwzuvEyWx3/4UegXh5oBOIotkGsObyk3xznnSRVADBgWSQVg==", + "version": "1.14.2", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.2.tgz", + "integrity": "sha512-yLR6WaE2lbF0x4K2qE2p9PEXKLDjUjnR/xmjS3wHAYxtlsI9MLLBJUZirAHKzUZDGLxje7w/cXR49WOUo4rbsA==", "dev": true, "funding": [ { @@ -990,6 +985,12 @@ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", "dev": true }, + "node_modules/js-base64": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-3.6.1.tgz", + "integrity": "sha512-Frdq2+tRRGLQUIQOgsIGSCd1VePCS2fsddTG5dTCqR0JHgltXWfsxnY0gIXPoMeRmdom6Oyq+UMOFg5suduOjQ==", + "dev": true + }, "node_modules/jsdom": { "version": "16.6.0", "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.6.0.tgz", @@ -1273,9 +1274,9 @@ } }, "node_modules/path-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, "node_modules/pify": { @@ -1327,16 +1328,6 @@ "node": ">=6" } }, - "node_modules/querystring": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", - "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", - "deprecated": "The", - "dev": true, - "engines": { - "node": ">=0.4.x" - } - }, "node_modules/readable-stream": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", @@ -1595,22 +1586,6 @@ "node": ">= 10.0.0" } }, - "node_modules/url": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", - "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", - "dev": true, - "dependencies": { - "punycode": "1.3.2", - "querystring": "0.2.0" - } - }, - "node_modules/url/node_modules/punycode": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", - "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", - "dev": true - }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -1760,40 +1735,36 @@ }, "dependencies": { "@sasjs/adapter": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/@sasjs/adapter/-/adapter-2.8.9.tgz", - "integrity": "sha512-8UChcZlqqlmaMMaKOCr2Bc1h+i2KVDY0FINlPXQN5PdAgEMd8dbxI2p9bsiI1yjYjOBO9LuMl7B79/mwYCtyEw==", + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/@sasjs/adapter/-/adapter-2.10.0.tgz", + "integrity": "sha512-GbvyIgbODnAJaBaz/Tz8/IwcujNOsZcwzbIuKQtG5y13BzgVPtx/e7b2TAhdoBqd+8uVh0CdrSDfOV/SuvPurg==", "dev": true, "requires": { - "@sasjs/utils": "^2.21.0", + "@sasjs/utils": "^2.27.1", "axios": "^0.21.1", "axios-cookiejar-support": "^1.0.1", "form-data": "^4.0.0", "https": "^1.0.0", - "jwt-decode": "^3.1.2", - "tough-cookie": "^4.0.0", - "url": "^0.11.0" + "tough-cookie": "^4.0.0" } }, "@sasjs/cli": { - "version": "2.33.3", - "resolved": "https://registry.npmjs.org/@sasjs/cli/-/cli-2.33.3.tgz", - "integrity": "sha512-y1uFM5MEE6eoKLrPUJbweDt4njSy9Y3CS5w5/U2xwNbiAyhiPXgkwCHjCQ8Qg+0rQnMvyNEn6qJuJZ3udc6T7w==", + "version": "2.37.2", + "resolved": "https://registry.npmjs.org/@sasjs/cli/-/cli-2.37.2.tgz", + "integrity": "sha512-Bcm8UFN9Y/ZON4T31Gu9mf1REn1pZoStHFVrix/yp7mchFt5rrrY5RbIqO/AI1jzhShSVg9P7oU4VPJrqki+SA==", "dev": true, "requires": { - "@sasjs/adapter": "2.8.9", - "@sasjs/core": "2.35.3", + "@sasjs/adapter": "2.10.0", + "@sasjs/core": "2.35.4", "@sasjs/lint": "1.11.2", - "@sasjs/utils": "2.23.3", - "@types/url-parse": "1.4.3", - "btoa": "1.2.1", + "@sasjs/utils": "2.27.1", "chalk": "4.1.1", "csv-stringify": "5.6.2", "dotenv": "10.0.0", "esm": "3.2.25", "find": "0.3.0", - "fs-extra": "10.0.0", "get-installed-path": "4.0.8", + "js-base64": "3.6.1", "jsdom": "16.6.0", "jwt-decode": "3.1.2", "lodash.groupby": "4.6.0", @@ -1806,9 +1777,9 @@ } }, "@sasjs/core": { - "version": "2.35.3", - "resolved": "https://registry.npmjs.org/@sasjs/core/-/core-2.35.3.tgz", - "integrity": "sha512-3o5PU6DkihpA+Aibt1lRy4USqJI0VFa+wNsKCD+bUD2DLZICU3JablZQxwAPH70VWJGXAUJtDFj0T/iRo5Devg==", + "version": "2.35.4", + "resolved": "https://registry.npmjs.org/@sasjs/core/-/core-2.35.4.tgz", + "integrity": "sha512-Exr3+yRdvacKvbXQoi1RfGHi5NtZUkc7RwFNkemHTFXLYaIzPI8CGSCaQmKkwM1UteOJly2e2pw2YT6kHNY1NA==", "dev": true }, "@sasjs/lint": { @@ -1821,11 +1792,12 @@ } }, "@sasjs/utils": { - "version": "2.23.3", - "resolved": "https://registry.npmjs.org/@sasjs/utils/-/utils-2.23.3.tgz", - "integrity": "sha512-tEh4mGG80eUxSLpbPivA0vl4akMdauL+yZrLn1uUM8EyiXPvlcWPkQTeN6oHbyyAH108D9cfEBidTePZh1p5VQ==", + "version": "2.27.1", + "resolved": "https://registry.npmjs.org/@sasjs/utils/-/utils-2.27.1.tgz", + "integrity": "sha512-CYTQwEj89cc7H3tGiQQcyDkZYaWRc1HZJpOF8o2RHYS37fIAOy0SyyJdq6mcQ74Nb1u5AmFXPFIvnRCMEcTYeQ==", "dev": true, "requires": { + "@types/fs-extra": "^9.0.11", "@types/prompts": "^2.0.13", "chalk": "^4.1.1", "cli-table": "^0.3.6", @@ -1833,6 +1805,7 @@ "fs-extra": "^10.0.0", "jwt-decode": "^3.1.2", "prompts": "^2.4.1", + "rimraf": "^3.0.2", "valid-url": "^1.0.9" } }, @@ -1842,6 +1815,15 @@ "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", "dev": true }, + "@types/fs-extra": { + "version": "9.0.12", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.12.tgz", + "integrity": "sha512-I+bsBr67CurCGnSenZZ7v94gd3tc3+Aj2taxMT4yu4ABLuOgOjeFxX3dokG24ztSRg5tnT00sL8BszO7gSMoIw==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@types/node": { "version": "16.3.1", "resolved": "https://registry.npmjs.org/@types/node/-/node-16.3.1.tgz", @@ -1864,12 +1846,6 @@ "dev": true, "peer": true }, - "@types/url-parse": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/@types/url-parse/-/url-parse-1.4.3.tgz", - "integrity": "sha512-4kHAkbV/OfW2kb5BLVUuUMoumB3CP8rHqlw48aHvFy5tf9ER0AfOonBlX29l/DD68G70DmyhRlSYfQPSYpC5Vw==", - "dev": true - }, "abab": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.5.tgz", @@ -1994,12 +1970,6 @@ "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==", "dev": true }, - "btoa": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/btoa/-/btoa-1.2.1.tgz", - "integrity": "sha512-SB4/MIGlsiVkMcHmT+pSmIPoNDoHg+7cMzmt3Uxt628MTz2487DKSqK/fuhFBrkuqrYv5UCEnACpF4dTFNKc/g==", - "dev": true - }, "buffer": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", @@ -2253,9 +2223,9 @@ } }, "follow-redirects": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.1.tgz", - "integrity": "sha512-HWqDgT7ZEkqRzBvc2s64vSZ/hfOceEol3ac/7tKwzuvEyWx3/4UegXh5oBOIotkGsObyk3xznnSRVADBgWSQVg==", + "version": "1.14.2", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.2.tgz", + "integrity": "sha512-yLR6WaE2lbF0x4K2qE2p9PEXKLDjUjnR/xmjS3wHAYxtlsI9MLLBJUZirAHKzUZDGLxje7w/cXR49WOUo4rbsA==", "dev": true }, "form-data": { @@ -2493,6 +2463,12 @@ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", "dev": true }, + "js-base64": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-3.6.1.tgz", + "integrity": "sha512-Frdq2+tRRGLQUIQOgsIGSCd1VePCS2fsddTG5dTCqR0JHgltXWfsxnY0gIXPoMeRmdom6Oyq+UMOFg5suduOjQ==", + "dev": true + }, "jsdom": { "version": "16.6.0", "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.6.0.tgz", @@ -2717,9 +2693,9 @@ "dev": true }, "path-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, "pify": { @@ -2756,12 +2732,6 @@ "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", "dev": true }, - "querystring": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", - "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", - "dev": true - }, "readable-stream": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", @@ -2954,24 +2924,6 @@ "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", "dev": true }, - "url": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", - "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", - "dev": true, - "requires": { - "punycode": "1.3.2", - "querystring": "0.2.0" - }, - "dependencies": { - "punycode": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", - "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", - "dev": true - } - } - }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", diff --git a/package.json b/package.json index 77a59f2..e4a838e 100644 --- a/package.json +++ b/package.json @@ -33,6 +33,6 @@ "prepare": "git rev-parse --git-dir && git config core.hooksPath ./.git-hooks || true" }, "devDependencies": { - "@sasjs/cli": "2.33.3" + "@sasjs/cli": "^2.37.2" } }