Once upon a time promised to make Server-Side JavaScript alongside with Caché ObjectScript and Caché Basic:

I found a JS Runtime Shell that uses Node.JS & esprima:

SAMPLES>##class(%CPT.JS.Runtime.Shell).Run()
 
JRS> ?
 
.L CLASS   - load javascript methods from CLASS into JS global namespace
.LV var,.. - load the given COS public vars into JS global namespace
 
.S FUNC  - list the source of the method which implements function FUNC
           - FUNC must be in the global namespace
           - the whole implementing method is shown, even for an inner function
           - this will also work for non-javascript methods
.M       - list MAC code from latest compilation
.I       - list INT code from latest compilation
.T       - show latest tree
 
.G       - list global symbols
 
.N CODE  - execute JS on node.js
.N       - execute the last-entered line of JS on node.js
 
.CONFIG ... - passed to %CPT.CalloutShell 'CONFIG' command
 
.SET ... - passed to %CPT.CalloutShell 'SET' command
.CLEAR ... - passed to %CPT.CalloutShell 'CLEAR' command
.SHOW ... - passed to %CPT.CalloutShell 'SHOW' command
 
!COS     - execute a line of COS
 
Anything else is interpreted as JS. :-
* if preceded by "=" it must be a single function definition
* otherwise it can be either a single expression or a sequence
  of statements separated by ";"s
 
Either way it will be compiled into a function body and :-
* if preceded by "==" it is stored as a JS global with the new function's name
* otherwise it will just be executed
 
\n can be used to represent a newline.
 
You can also take input from a file :-
 <FILE    - read JS from FILE and compile+execute it
 <=FILE   - read JS from FILE and compile+store it
 
The result of the execution is shown and also stored in global variable '_'.
 
For a global variable, set it without using 'var' (this will be fixed)


JRS> .N var obj { name: "John", age: 30, city: "New York" }; JSON.stringify(obj);
{result: "{""name"":""John"",""age"":30,""city"":""New York""}"}

JRS> .N Math.random()
{result: .5670654247514904}

JRS> .N var fruits ["Banana""Orange""Apple""Mango"]; fruits.sort();
{result: ["Apple", "Banana", "Mango", "Orange", 1: "Apple", 2: "Banana", 3: "Mango", 4: "Orange"]}

JRS> q
 
SAMPLES>

If you do universal LPAD, it is best $$lpad^%qarfunc, because for certain arguments may produce an incorrect result, for example:

#define lpad(%s,%len,%pad) $tr($j(%s,%len)," ",%pad)
   
s s="a b",len=8,pad="0"
   
w $$$lpad(s,len,pad),!
 ,$$lpad^%qarfunc(s,len,pad),!
 ,$$$lpad(s,len,s),!
 ,$$lpad^%qarfunc(s,len,s),!

Result:

USER>^test
00000a0b
00000a b
aaaaaaab
a ba a b

Try

ClientMethod changeParams() [ Language = javascript ]
{
  var query zen('categorieBeneficiaire');
  var param1 zen('catBParam1');
  var param2 zen('catBParam2');

  param1.value='OS';
  param2.value='NSAL';
  query.refreshContents();
}

/// This client event, if present, is fired when the page is loaded.
ClientMethod onloadHandler() [ Language = javascript ]
{
  zenPage.changeParams();
}

Another variants:

USER>k  s args=3,args(1)="-h",args(2)=21,args(3)="community.intersystems.com" do $system.OBJ.DisplayError(##class(%Net.Remote.Utility).RunCommandViaCPIPE("tracert",,.output,,900,.args)) output

or

USER>k  s args=3,args(1)="-h",args(2)=21,args(3)="community.intersystems.com" do $system.OBJ.DisplayError(##class(%Net.Remote.Utility).RunCommandViaZF("tracert",,.output,,900,,.args)) output

See Handling of static dataEN or Обработка статикиRU.

In your case, is enough will be the standard class %CSP.StreamServer (see streamserve.csp from CSP Samples).
And you can use it to download external files, for example: %25CSP.StreamServer.cls?FILE=blablabla

PS: by the way, it is not safe to transmit OID in open form, so pay attention to the method %CSP.Page:Encrypt(oid).

Changed a bit and added new code:

/// d ##class(Scratch.test).ClassVsInst()
ClassMethod ClassVsInst(= {1e6}) [ ProcedureBlock = 0, PublicList = st ]
{
   p1p2p3p4p5p6p7p8p9p10xClassxInstst
   
   p1="пропоывшыщзшвыщшв"
    ,p2="гшщыгвыовлдыовдьыовдлоыдлв"
    ,p3="widuiowudoiwudoiwudoiwud"
    ,p4="прпроыпворыпворыпворыпв"
    ,p5="uywyiusywisywzxbabzjhagjЭ"
    ,p6="пропоывшыщзшвыщшв"
    ,p7="гшщыгвыовлдыовдьыовдлоыдлв"
    ,p8="widuiowudoiwudoiwudoiwud"
    ,p9="прпроыпворыпворыпворыпв"
    ,p10="uywyiusywisywzxbabzjhagjЭ"
    
    ,xClass="(args...) f i=1:1:N s sc=##class(Scratch.test).%1(args...)"
    ,xInst="(args...) f i=1:1:N s sc=st.%1(args...)"
   
   
   st=##class(Scratch.test).%New()
   
   w $p($zv,"(Build"),!!
   
   runClassmethod("dummyClass10"p1p2p3p4p5p6p7p8p9p10)
    ,runMethod("dummyClass10"p1p2p3p4p5p6p7p8p9p10)
    ,runMethod("dummyInst10"p1p2p3p4p5p6p7p8p9p10)
    ,runClassmethod("dummyClass5"p1p2p3p4p5)
    ,runMethod("dummyClass5"p1p2p3p4p5)
    ,runMethod("dummyInst5"p1p2p3p4p5)
    ,runClassmethod("dummyClassNull")
    ,runMethod("dummyClassNull")
    ,runMethod("dummyInstNull")
   
    ,runX("dummyClass10",xClassp1p2p3p4p5p6p7p8p9p10)
    ,runX("dummyInst10",xInstp1p2p3p4p5p6p7p8p9p10)
    ,runX("dummyClass5",xClassp1p2p3p4p5)
    ,runX("dummyInst5",xInstp1p2p3p4p5)
    ,runX("dummyClassNull",xClass)
    ,runX("dummyInstNull",xInst)
  
runMethod(methodname,args...)
   t,i,sc
   t=$zh f i=1:1:sc=$method(stmethodnameargs...)
   t=$zh-methodname,?16,"total time = "_t,?38,"avg time = "_(t/N),!
   q
runClassmethod(methodname,args...)
   t,i,sc
   t=$zh f i=1:1:sc=$classmethod("Scratch.test"methodnameargs...)
   t=$zh-methodname_"*",?16,"total time = "_t,?38,"avg time = "_(t/N),!
   q
runX(methodname,x,args...)
   t,i,sc
   t=$zh
   x ($$$FormatText(x,methodname), args...)
   t=$zh-"X"_methodname,?16,"total time = "_t,?38,"avg time = "_(t/N),!
   q
}
Result:

USER>##class(Scratch.test).ClassVsInst()
Cache for Windows (x86-64) 2018.1
 
dummyClass10*   total time = .328227  avg time = .000000328227
dummyClass10    total time = .27655   avg time = .00000027655
dummyInst10     total time = .259913  avg time = .000000259913
dummyClass5*    total time = .286983  avg time = .000000286983
dummyClass5     total time = .25666   avg time = .00000025666
dummyInst5      total time = .240312  avg time = .000000240312
dummyClassNull* total time = .274406  avg time = .000000274406
dummyClassNull  total time = .250926  avg time = .000000250926
dummyInstNull   total time = .234486  avg time = .000000234486
XdummyClass10   total time = .312917  avg time = .000000312917
XdummyInst10    total time = .264871  avg time = .000000264871
XdummyClass5    total time = .286985  avg time = .000000286985
XdummyInst5     total time = .238557  avg time = .000000238557
XdummyClassNull total time = .278684  avg time = .000000278684
XdummyInstNull  total time = .236815  avg time = .000000236815

I have a few comments.:

  1. your code finds by the class name, not the table name, which is confusing

    For example, for the next class, the method finds nothing:

    Class dc.test Extends %Persistent SqlTableName aaa ]
    {
    ...
    }

    USER>##class(objectscript.findTable).test("aaa")
    ?
  2. according to the documentation, your code uses the deprecated API:
    proof
    The Caché Library set of class definitions classes has been superseded by the %Dictionary package. The %Library classes described here are maintained for compatibility with existing applications.

    New code should make use of the classes within the %Dictionary package.

  3. in fact, the search is done elementary:

    select ClassName from %Dictionary.ClassDefinition_ClassIndex() where ClassName 'test'

    or

    select ClassName from %Dictionary.ClassDefinition_ClassIndex() where nvl(SqlTableName,ClassName) [ 'aaa'