From 1d514a8a0ab5edf5617b7144da3cc45d4045b68e Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Bianchi Date: Mon, 13 Jan 2025 17:44:55 +0100 Subject: [PATCH 01/21] Added PHP and Rust SDK Signed-off-by: Jean-Baptiste Bianchi --- src/pages/index.astro | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/pages/index.astro b/src/pages/index.astro index 753e3da..6c951f0 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -29,7 +29,9 @@ const examples = (await getCollection('example'));
  • .NET
  • Go
  • Java
  • +
  • PHP
  • Python
  • +
  • Rust
  • TypeScript
  • From 9bbc66f26d890ca304041b9e68aab1ab44cac7eb Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Bianchi Date: Wed, 15 Jan 2025 10:40:20 +0100 Subject: [PATCH 02/21] Fixed Huawei branding Signed-off-by: Jean-Baptiste Bianchi --- public/img/logos/huawei.png | Bin 11565 -> 38822 bytes public/img/logos/huawei.svg | 22 ++++++++++++++++++++++ src/pages/index.astro | 2 +- 3 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 public/img/logos/huawei.svg diff --git a/public/img/logos/huawei.png b/public/img/logos/huawei.png index bcdae63e048a127e558925ca5972b321594534fb..a31877b13617f71b419ef33b5d5005c18b8e90f8 100644 GIT binary patch literal 38822 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 + image + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/pages/index.astro b/src/pages/index.astro index 16ba9dd..d46c5bf 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -128,7 +128,7 @@ const examples = (await getCollection('example'));

    FaasNet makes it easy to deploy functions and API to Kubernetes without repetitive, boiler-plate coding.

    Learn More - +

    Huawei FunctionGraph hosts event-driven functions in a serverless context while ensuring high availability, high scalability, and zero maintenance.

    Learn More
    From 916db02f9e11dd846b16cf1e3d7ff7827cb0dfe8 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Bianchi Date: Wed, 15 Jan 2025 12:01:35 +0100 Subject: [PATCH 03/21] Changed Neuroglia logo Closes #236 Signed-off-by: Jean-Baptiste Bianchi --- public/img/logos/neuroglia.png | Bin 24907 -> 6601 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/public/img/logos/neuroglia.png b/public/img/logos/neuroglia.png index c89a44b6d2bc33767ffa6f01dcf706182b68609d..0f5dfadb48c26907e31fbb23d3727f7b9b0115fa 100644 GIT binary patch literal 6601 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 Me#Q8up>xcC0K#90)&Kwi literal 24907 zcmeFYcR1DY|37>hsDvVfkc3JcN%p8@Wy_Y89mmL?r?N6nQch)+nZ1v3jO--ikadnj zNan$bGdLW-_tED&uIv8izJGt;=jyt;uDA1kzFyD$c#acipr^rfhWiW%1Y*+Cd|(6u zok4>@#|fuS08ji*8x;co-8RrMR?~6w0ogSCfBGjcCy)xfe$LNG?-A(NC%bc7m+wCR zDlzPBQ2AQpdBzwBbQz@e;GS_%1`fLxFxtdHKWr2deLVQE5bIEX!SZe0O@%k$?-^}_ zvIln>w{+}OoNGlJ8A$-qt-xdTqyRx_= zweuoeR*CbF9|RI?LaJoO@Qv>W%ZH0m^+6!|oi#uCaDMVvMY3d-xpb;?p3r4V!x^mW)% zpZ~0^(;?ZO)N?6~9`tLV_qU8Aege!-(my5vdj3KQ8jo0TYJ(5``+j9>7WLL7C17(y zWpm~W-5>}=mf2-8Q~NdXAA+Bh#u?w}?-*CioPzV^=qX#B$!w%eEk#K3zZ8O(F^dN~e*h2{dqD^7u+IBki4-*PPUlK(gfVKFYXW;piME+X;|_A?I3TC;Yr-;EoI4 z2LwtM=Krz(i@atyI_E}vhZ$`Ba<6Z0BDWwR9(HJX2K3w=&cRIXotv#sPkU(qIt%*s zYvfr)E|W(AT^P*v#BtECrhMO>Xxd$^!|^3#SrCZfZ~m#E55N~o&q=d$be(r~}v^9vx*B~|Y2EE2xrvAVU1(Ve)+-`dOtTtZ8fF3*=3TOqh*u#W1rCS3&{w&&IS ztq-=Sq;XWX6iTk^0)Zxk)8DqW^>@zBapwJ@`bp@OQ!Pg8hz$NUxQ)|wayRIV<6nX-0ZrU{$~ zJaw1606GDZedWQ0i#^ug44OpE)`!9m&WId|TtF;hYfjg}jVpQqU_=Z=tf8rfk}5n7 z=9iHf_}UA|w&}e&%@s~)PH=_k`MD7$Mh`}n$COW`iOVVPy_W)gy+bz5Yha-kEq{z@ z!xon}hNk1%QN4Kp^LOQ$4mU?1xxK5z7KeYu30QsnOyhs%;F{z#gW5nz+;KYvlLP6h zTF_(#O`q!zP5-X`xa-7C4Or8t;(xI|aV@6u7-;gHRB={tn}?;IeSNX*yR>9`GZyM` zP~{7$qAam9uT7!YvL{YzSFM8|E0GyNU-w2nf|j%!0Tl$Swg%j~X9=FyrdcuZir63a zpFbWR4tUZjJbKs}LHGp*f!zBGW;m+X*Vu^9v!7iS@iX*`%#3c;TcLb?4jw@_gE#m9SGZ|Z^j!wUiuLBtz*_RGu(GeZso~* z+<6G_hcsp#(`Ezd%$nIU_!E`mQ?CP#7%U;1oJ6oh=y9z7iyol0V_GJrv82kQU6nwG3-YIa^T;pV!j8X;B&xZ5i2(oGL0qJ>839-3yHisG8fB_d7mSLS4oEo2baw`jJq*&T7R)j8DQNKk?+!wcONiMqbqo-G$B=fBPP9eFI;GeL7)GBdwDxE@f| zkr920lghaBW$+`w^mqkeZYxPIXh)SipHwliqO z@`ZD6*w%5o*?8z)dw2AUK+nGjr-S|{&05_WoZ4P4^2q(>M0i^TW++ypcuu=Gp$*#u zKa3?Z%a@b32#6bFRR6<$DWl_L;xmQKlM$`qQ%?>_&$3LX@IBOP(kp@q^b8m3dl2AJ zn$p)0ld!v%pwc}YOYen()W9`PQj$y&dHG2WgmEqf4Xq6)9W0H)RIPcSKa%R8`(a!H zCl!^&lmgpk%ay{!(1;Y9PgVia>uQ$p5+{|k2$bhofaA)SonLfcJN&Axht7K$;ZfZW zFdQ9%{u!>6Rq9f|K#$jEYr&}BXzRZG4mv6puFdb(dbsP~9R>!-S!efVo42TgyA7$I z+^)o>A7s^C2bn67Lp4{*+bk$gFa9rrm9CUF3Z_D#E$#r7XFLG6W#B~~5KB;?ez>hl zyvj_hE2isbUR5uhMk=#(gd0YG>Cy2}6Kr(8ZGCUP48VX_k;47xgq+6V11-cxGhip1O=nYghk98n2F|Dp%Br? zCy`X2HXIRUX-O^#zQkDZ1UX&+nvCduCT`~YcypqKxhLH?%&%%EC{P$ZXt<9X+z90K z+~kItw+1Ue?2AfU7&~mhP1htK#B@};l>gH0ap#*Y{VBTzb(^p;iLKsI{*0ebwmv=D zr?Hl7)%%au?-iZe%v>@Ci!eR@=BY|!QpLoq4M_|4w~+}Wi3UhymZCf zm0#WIiI4j1nEU0n^XoO${xmncM)as;xUknE*Y2I@6-Olh<(a(s+=MuUSd_-)QYUKZT5l%ew8J(?JZQR*8 z%N^Jw2+@F+HC`3?U(~ix#GU3yfRJ}MUkMw8=L=VZ7dhmHbQ-hd z;1~OS#f5h#dvAhF!&Tu~_d8p^$m@t4n)~EO9Qhg>#Of66Cq5Uq60zp;sI_cN-HSxN z*1mvtS%$E*QQFljXvx!U-iCiC{|0sl*evi$>4Bv{h*rf9LPFt; zxGuqv{2GXMxuJX4{>0~|m7E#XvadUhK8jgsS$8wz5WW|np=z@-@++IGF~!{I(XY79 z7!emtA{ZSoT|CqiK1^xKi*8u$<(@ISXdIhX`)ktE1SS(>wmRBC_jM$k>R9K^|34;i zN3#}t4HKaaKM1T&e}UNvo}pSQ8wjIqN&}p}Z;bz}e6Y6{#dZ33%hXSmfPikguk8AcmYLxvLe(tWaywU$G#}F zMqKo=DsN@YcMl6J2@%kf=T>%pky0ym;E*pa{y)a>^t~&R8iGOk^+C&(7anH>Y%{fjQs@J#W=RZ_DvqdJ8|L*wOpJ9YE`Fp)V%f)fo z|0TRUSLFN^%1+N-B4w$tw^BbOC@f?!q~@zLX>*o?*?d;zFk}yJ?zc6|2US#3D&*|< z{g`z(2NykZdKH>Tk=%Drnfdn9)`%)LZy8=6@dH2%D5Yl0?4HL%sT*EyNvy6%tlUgQ z%<>}{J2mg10@_pd_ICV`9*SON{Qfr8;SojepHhgDl%m?CEB8aJ8Ta{d2|5&5Y;R#U zL8Aqtb{0jHbj#m`V!i6#)uxCCWZo(zd%?^OUm3hV6Htbz*0nT;d_8VwFMqnU@*?<% zwdf@BIWJ=l2%NvjOU0SRxx6OPYrNkH8d0{n3Y{Lr%<5L-_8qO*aZqGv*qI@+J~~S! z2j}$XT{}h%FVCT!El_5A%>=Ok_@{|&7N8i_li3y>eyrwm7EMQ<#bLAj0K?TGShoOV zyty?<2qOh{hvU=C*ia@E`axmq&|!QMM?WR)p|ymarM_1o;mK0FY%s&Tcs->3f8d2t>~DdC8_z$x%J-T6tLE-Bg34##{qExg49ed5IGNS zD71e)8@cpAmC>aXK~s=FJ>y67~t{gv!%y&x94h`=&~7mC}vo% zd|n*)kYU+%+97lQl<_bAUq%uC{1H%^I$Vy>u&U=G>BGC5_Pmi#5t%6-P-(YcsORBp z$N&`a$`Z?n_ST_QinlB3p3;D&;kjw%u?m-O(hhA;UD5{`4oSAbl@>6G%&rhPL;U{$ z8F`)Bmd0HU>1dcd_(3saASXR0U2ZO*+ar|v)Nc@iTo2xuYWhRDiMF|NF*E!XG83Qm zx0QSDmXftGdCi*eJR*!^-6H+CUF5qVZ4#lGi)8Q*CD~`4Ka&5890-=@>mKu|=(dGI zUDs!5tdfbih*eoD#2*qB(@y;3kHxiR-rbJSt!?SrwaVJ`iQxL1`EWvjS1$wq@^HDy zM&%0EL3B8fI#z~z3N~{*Jo_+<^1W^U>`B@V6%ezf$$JAmGi~ydWjR>EjBTS;N}-y? z9&_lC|1P1f58+c8PS{#oV6Qu{yp1BVE{zUqS4)I{Gn=!G_Cpu9ip2L@nPgATg^!k- z6dsaq@|V;6T{65PdM^v5pi#IjqF6N8z7>vj&dQ2uL}t7 z1)DDy{;|RLkBvL~>;Pt6)YNTVtebsqAkRrEz`n+9R+QfGMfNz*`Fl+qjQAF9FKo7c z>O9ergQFW{`Q1`}_Ke0jeVFyK$tiH}_D9kU|zl~mtuIp+DW-&6&L$U8Xkk%~NQeBDODTaOB?-L~m>+&T3(2lwn= zM-Y!${NRVVr@l6^ej}w3^b)R;zE(c6B9-oADv#uEC>hamdd5h=i0?(A|A~^TL8t&p zCxT_lYogR4a#K=Uifd8d-Oq2%joeOR=TKLi4v=f5(Vq@R9y?84aAoOu99O%R>C+z^ zk#T5!02ykA|H7%^EI!VFcErzD764~-Y%Kf?u9o~4uO^KDsb2!EH;@$g^kRE_M_Y&x z61jiB@}Y0B#rSyWH)6fGb(1S{diT!lwnE0u_`@xX9U-AyHHb@Yps7WVbA6C2CfH2ST6$z?iew&4l2|dZLA3mf^fu~G#nhDmP z>BOow8M|1nN}K7N2bk0Mg2J=gW%RV1d*7KX3l zcRvT=RDg<8wM6Eu4VMB-hHbd7uEAU;uTsBk=!|NV1(e7)^}6gC(Cq;EIlc)#yQicB zhZu?4=bbz9!&|wK=^J{PM$REI1aObhd2t2xXuqvb82wgZR6x~s(!!9Ro5UA)wGMn2 z&eK#RTYU1MECgZ}WRIy^t>al4=#rrOIv?54ogWdB%6*yyBz;<0kc3!yTE;vJA4(`4 z?$>bv@C~bUNQ9?u4$i2(VQQAAYPZtlCcW*-hHI*VXmS6DfZc_skzWq{#2WS7-BctT zK)1NN4|R@J%IvNt-8=Ifru5;{ueWsSuFPqUIB5~;3Kn`O7XFTM&c`Z&tMZ!2J)r-{QIJ}H ziEHOp8-dI0<9`#LbWLZ%AX-zkLkR?7Q;`V_u^}?aYAapf4Wt^L16kcK!mo7jmTN8( zJlW;H?P26(##YWvGvop?_T0Az$um6y-P92&EIOPiGkCE74ycnEVWqALsz3?G16hbc z?K6(rgby(87$b07kMAi9j4zILSOKOcKdY!*(VS?BlO0PazdM2*bPHU${99yf zFs+xwvk*RJFCRRVvK0DZw&|wUIY?m_&ZxGB-=KN1=;FopKUWWRI-B&EXHd*q@ zD*E4?L+ve5nwBuxuv-O>D((dx$ObkzY>zV=t8~5A z`GqqlINdtH!>H96>3$5eDk-xqeixfKAce0G2g$~gFQ@+Y>QV;A+#d_4#CyT7!gvAGy-m;DnXqd?xTC#vfNl9wUYh!+>Db_BiOl_h6rb#g zrTbUWdU3Eg2+4mor9(z^~U&nm9E$9qC zWu?2uAMBfhV{Ly%dKMwkqy`}Fa~)Qxqm4Wt%zvJ}Ldf-T+nOp{UFM7VG#cVGrVw9o z8`^d|Q&x6#@v$aNqydUX_M@)5VGqZ7y+(^N_-}+xcuz`i>Y9o%q0(KE54_4Ds^Wr*u|^lHUuCeqQ^d&H4ayJqOY&$i89R z>B__Zb->atOLpjFLjL@0;1`W=o+F(%(LIBt0hbtjM{jIQlM1(qH^XhxDZL#l7bY8^ zd(+EkR+6oLO^TJj8J7Jp*3S~mbb+QLUYPOpB0^!R^H06K#o!LL4%@l}&#B4+u|hac z9bapVzJcn5k-9~u(sx#NxH_HO6d5xbb>+d>ZwJLVwb54c7Hm6a<@cjx9cbkEHh_XJ zpb!fw@z7~!ym_NA-{ zcw$mtAs#)zWN8$W3&v+JDjugk?f2>T^Q=JiTXYEfa&NI0<>12FC8l>12)h?ACE}|E zS6F+u87LWH>?Wm6%8!RH1(xs4TvlFzsf?VneX0xh*Es>% zd;C;B2kpw`L1gc25iqIE1UIzFL(7;&*vd2~>l>;D)?7vndlQe_d39X&li#-h8f#Er z$7f1ecOr+qQ^n8m86M^HIK+oMl^MkC)3BwYv1f@A31=;mjcYSE_xsLEwR%$>YV*Z% zPsd{PYdmvCnMF;ocmGljT8bm+Z$2LNeagFL$|;i!t-q=hS=a-9ex9anjbsEKg^|bR zV}nwA2Wzy^?eKui^Zafo>2o?DjnS8L%|usstDZO5IraKmE_nxIC+WW42-qCncEx8M zQ2L~1>({AAmN+EH-czA25+d1M=WoW!H~c95{9?l#v)nMpX1ObmEc97ay@|a#cjkzUA!^p-DdUjOgr7%!yL zw?%jBtcanE7;GyP(-H2qUFjMi#$A$!6Ga6ewwWX@MV`?wP}f%)QLW6{(+vmn)K7Ac z$*5@an_x@{r_assW-;451xgl|XO6NN{!g2Z^prgcxRRF#8zi+nZ?QVdX(VB=yItYz z6^jr#2~o4$I-&8~%m4Tzn!G_8@z53#y^wD(1YRY@Z%EfO-4GL+E zg0iBq+Y&jrw++7MAPNx&$7!}mEji}t=0r`HkziDupo z=iFX>*<|QQ(66Iau!m_Y3XIZFszX)7iwsJF4=M2D@(X8LqKmy(+hV@NFVm{V%zwhx zBw(&_Yv5+z{TTrUh#IDGF#FO9$fMzk{SRUPusO8_sawj276I9hOPW-)>x1iyU8Y8` z3hUpqf-2%+Gr!FW*=M>f!uE|0OZ~2eDX39XlAjM=yrKx@l+q6w+R+;E$C(3p&X1HV{~3T1+j5eJ=g~)L`6$+9 z;DBEIIc7=R;)jjPHqA{Q2T%S=^?U-uSRqTN^;-73PMKYm3a2O}Ma8a3t+~ZC)D0T) znxn(8=wiy6oxpHj?a;rR|#p)s8_53G+Br@0aAeG_Kd{#Jks3oefCx1oZ zlz5?!?JgKS=u5rT8Q1r9E4eQ|iuVl6v^#~m9QNo#iE^c5%Y1~%?2SBR;PCZ2iOdIb zlC9G9@jU;Dp{p3Fc?(z=+FxmkcVF$!mH86X7vJ6-+|Bl=cH>+|{UX)2V^9P8P5Fw? zPMJS1jn%8%!%Q~1`b+cZJUW{nuplrbuX1H7N zdtTxxlMyN)?UTX>ZVSdj3;Ik(*=ngb<0SFmQy+4hAhBg06UCw9eqGPjNNr#?KM}2D z9aBbx#Ty`Zo`+C)i)6zP4Mshwe<@szI()+oj)JKr=-2Ps9ss&$Y111tigj5}nPrtP z*f-4F^ZaBzXbdWSLQ1xvK{20X9r1A8z_zJ*Ih| z7xuFxKz!#P{9K9qDgjOk>Gw0Aqg#-2_mKDi`dAk7^~xFtsbufQ2fmN0;#M%y7xFSv z>X*z#4C{Ze$E4)P+E(({cEjd1-I>1#jU3#ic7y4iSB8^JOqfdM;xXj0 zdF7B+@R%*n%srf?f97jH60zFSGr7`Av;248&nF4(?x=uxR}4mZ}*D_f-dW?ZxfBHvLJurI^XGpynyvEI)xMBM#M9sK~kzx|c znunbDqg&$+^r^E1J1M`-;DqQShZ#+I_|ZSXZTq)j@qCTdL(f^b9=<2x5`6@Jv8&bQ zzOIv#z~W_2tCUK?x$b!>cO8ipRnC$POlJVXea!5;pCr}$z;F6jJj|4eOyG3xf;Rov zh)e!yEmOK$x`@$ymXGa#_~7RR87Yq&f^D}S)|PQ3uA15CM?#f0L^EI_TzB5HUwk7T zQne@ac5dfuxk+FZzPKu!Xi-FdlX_566d8sZs6G;aZ{GZD-GIaX+-6-3D*v}+t>5n5 zppK;d3!&3l4=~V^f#G#So>~0cN`F$Z4)F@lEi|q-uC?CvC-G!o4K)p4dc84&I`h2S z3^Sjby~uU~z7s=>@O1GAxTfdCN5vj~L{p2&X-y7m_UtmYWQN53JeaE$ZokM(X_@=# z!e==0(!=Q{X|a7m`5sliITl^FO5j`B;Pr?Q(-BFXs3hCkG+Y&+cGAiu)tI9)DVYn> zi7hIFQ=GR~jzK>B!vP)atIW!;w~Dcqj~jNYO}(*M=SoRHC&=^Md4+I#_=kj`xfd!uXAAIQ%Mx8o3; z;e_V+AX+KQD8jEAG~x4cENQ9#F4#=z0^If{v3QR=bz^3**w`7k?>oWmam1F(q!c>9 z*rV%7d;VRZxD?2YYTQ~3fp#Z(21YL~=vt2_Cba$a{C)g%4kZ8A6M1kdJ@mJM*@D30 z8pj&Tv!FV+yjGC;$B=-MCXhKIlmX~&)WhdI+a+C$O6k2ubqMhMA^I$K($s17`0T#EFjeFcR zYRgy?VLx~wObiV0iO;{EmC+v?%|ksPtUp#}ZlP_t0C4BWUKW|#G;F7o`9CFH&1TT4 zrCXT8f^J)?Ltu?!9~+PM%lqeS)M30ikaw4Bf3(EVJ8>jS4NK+JMwVrtOGtN7pmmP; zaCIxzV3miGapm;eO^hgni+Ve@Qa%%jlAEOF&uww9f8t<#t1du1@KKE zXAYz#7VbB{SRc*UGjs~vl7ss+Z);e4AbRoAhqewS#mrcn;TB)Ft7TpmKDt{+VLH^>K=SGYu%{ITrD`732FNRvePt4uT=Qbwwxzp%$RodsEkW!UBL7Yt!7ov zWp!ylVvki!b^***etfniBYjolaqWR%(BJU(FxxFSJ#-OUzL-)QasTFH4eaDH-Pfo5 z5KS27sFCH^vnV|fw~f3;Q!sKzfv-(j$;AcNW|`HEH^j_c(6373yi>L1=RRh@mnGlO zuxu69rG`;?nUW%;5+QruL9Ii*L$u3neAzZ=bmXyrjW)@nzLc4nIkexNfLpA2MUU&Gf%8 zblG{x#PF&UQ^mZKOKdzs+tf0;5a>Pd@IX9XM{qEmrGvV|#t1+McqTi*3>aeglQ=k~ zrfXJDckIZhbjepsWd3;gWNEV*nr>xkKr3$*P>6g48+fil2yJsySy22ky1cTg{l<4E z?Nc3V2BV?IH@bD7&P=^azKoC#0*dbq1#F98hCZHvAiG`({uB~1aSZ^Y$g?QK=N|3& z4qI)YdI(d03ad7;fE^JupMb7;Mw0I%H!~(eSG9ZkkTF z*JV%X8iWw__BJ$@>;>#)+-x2X`02R@3^{9UZt_ztLz}mH`roKw=&gj%RF2<~(MvX4 z#8|-=KEKOzBTK;=vf-9(kw;a{R(sg@^b;3A2^IC-8jn_((9J@pX&MTk8{j{|1T9li z$B<82NOH1MfuW-eVrud--_3*XmERvD|Ni{>@b6zFJ~Fpv!JBXdAIdxBcef_E58pA( ztq7wxdW3m+6rEei9b6TfvJYBvs;2Wh5p|KVKFD>ab=nRVVrf%;_R?G#(~&B~y?TAq zoB{utud%L$%(wPNOYGM@z$A3LbkRM)Z1C{tNP|@lI@nJ$Ty*BvlZ}b^=o>%>$;(|u zuugx#S@^Ru4&{yB8z*&50Lg-Fz8o)AQ3GJ^E|of0OouN#bYyFS6$0kSKF@g$66)nq zX^DSHCvQJFIhT`-k6t=(QxC8ABUi$FfYOqsz6aZGnD&p(Wnvau|+DUMR#HDj3&_ zDO(EgVO)1YMcQ!Bav)1dOlixH0|L2h-ojgu@PsJ%tI>=XJ6q4Nx`eB~!!e|yJqCRi z%rTn@@6-)dJjyM2yaHDxorH)D63lhQ^g<>uC?NW57N>i-Xamk!i% zpS>yvlF`(S$W(}!vXy|xwH%yhX@=^GQ z(+j8~{XUZTe8OOkmo_x@d(2H*XBL>oe5Tl9InU9FGV1rnBNCV)Vf`3aH{a$Kz^o{q z9>d{}LsrhlqLQEK@@WSZW%_FV-TftAoGq*u=&fHIYqe1R>)PoR;SHO#Ki`_^t+CA| zG{XwX!Ce_Dc}$oW!&sLj)GX)dCh>UW8t_Bgh01csADw}y(ZjVf(mv*GPrAjo&ZjFO zeOMq5iH3jl>=6Z-wycZE-kQCXvo)cMb_8mLxQe(jM)RYNnD(r#X~_KTnLpUNCID$z zRb7;sRQD02zGQrbu$GZFm-F^XI7KaIKh1O6>yDnUCuFo?OpV~J(G*EB#AfDmZODp_ zFSwiIQS$b#iemv*M@7v$O1AApiQ}7{!EP5B4$^o+jK#u>By};Nqv#ueo&1z!t^9&D z%S9tdX*mcG?U=rF_dpGN_530bKym}3)tVFtcOJ`d7Nq8zVaQp##&W{qfOz$NQ31)G zUM{j=4?ju*0$(7Wz|fuT*1W``-yaS8a&%+OPjHs980?6^42yi0bnbH>_|JZGU{wgZ z{3~sH;NBT1))D)4-d%5>Qxtx+3;GGDm*#@69F6dD6Vc@q-{>SysG-QU{@Nhzg%{6p z8pk?nv}$pURqeUkOu~u_axWLo$}tHw#C@1(n$JaRADnWUw%$Y13k%LIcB? zn96&dVBhy0wlXV=K$44Wv#66*pe_M*)4$a)ZWLlqVWWDt@{SosxTR(Sy_c@Bi*x>wdeF-`ae1#F_5q1hOyS-Hjbh~7vFD^a3 zy}(tj`M#MvtQM3nJMf|5G>f~;7-RPc@3f7-S=vT#m5mAS=0iLx#0MN)ynI~^a~;1a ziq2wttZrK-E0EQk?BT-F(AAITaE^3L8Tk{+m!+EnX-i@nj8+$=e_BeBS3>Y~GAVtvx32nDymGOIGH_{2!t)3F zI$ikh_hVOn=Un;#)_U(Mew4NU1a@uDm56Jdvck?dKTH@vHoWNejY}VT7VVPiit%z- zAP!Gd{V`^E!?$$+Y~W=ZKMeG?8tW|c;rIUPBGKvh3}~l7bK_n}0+Y7=wRpsmQ$2+( z(2_}r)P;N+*!TBEzONDf*kp6>S(?FNdOV4fNq{rQrB7riUv8fFdxSlmr_fNgIyWxC zkx86#$)88OIVf?%=X*T+1Wbupv(<8N!7Nj6qQ*=^W7;MLXEZqU%f$vi_mz9KOiC-J zKfrkM@Te3{VrFh=+9v&OZB-6i9BsG0)CMx=t5<$SIml(FHfe$7x;0$1;4*(sI300K z40N0r8A}chnROdI=vwLqD zX?#!g2#eY@DU3VJoH$*D46&^Ot3cw{F_Ab?w0Lk2m zghI^4Bj&xpibhjP{s;XX;J4Ep6&7}Z_gPip^%b(>UcAyrk)f{2hc1#@syV5dey_dZ z1JTG9bQ9Y?@RM4-vPX&pxbGY3>z0$Wee-(yOdNn-Mngpa(kVBnJ0pU1u|lV(a5E9Y zVQ)^u=WE91)tIefleRoqA)%1s$PD>z1pI)c76MqJGal#m%+#A7pHSgb|DM^oq2Rg<*FUk@g zZ3gU5#dl8aScwFy6|w-v*#j4jZc7eQxoGQ=02@r>TP8ON0CC3Zvnx+O2U#f4QmmW7 zQ-7$w%i$^K&4%vEHdk)qLj1Dgk5HsZPo6q-h+Zg-1>O zrIb|0(yAzz*RJWWWCH6JY{E7fLM;Z~K7KA941aX#{X)4NJ1t-ZpeJ{lhOwxJLo8QY z3X8Jj^h4h06;oRL80rnMu|hRZ8N@_cZ8w1X!GRSq@x>#hPo;eK)S0kgsXXA&(H=xE zzb#AI*~91s9=VQ-Lu%c0i8+1@9ri{U%0~YZS~eSzYz4%?EwiS%*vFltGMQ1Q|Gu3* zLxYqh!y#VdOkR>(~~$)`kg2f^OVX=zgzckyq1`db)@6{?Y=G^)Q{*>-bFD<=AH@aYIIvMH)t*mXOC;fSn})3z+xR zucwOK&5&XinhW&zICqlPWam|HMZU6{Y6arnY}jTouorsiRmJb#vXfW^4d;m(yCbJ3 zvE)F+sf!&7Wr+D~4=}sw{B2?fs{HD0FZo4w#AzC_p8oga)hk!q-}TFXT|M`%;w&y_ z?<(L<)?>T@VH^BHteGeUjX%B&E*Jp&7fr4QD#Rfa!g!{~eZ%Y(~ly8Vr9sJM7Zpr-Ff=b(?@Pzs*& zfvy~t^Qg=B!BwG?yX^_S9!yCtgI~?#o#o5&iW_Q8fMx|L290V}NQ}lIl%xX=jEyXv zaOYi|A{j#g7>8BG6#%RszRP+On>qig!m(Qeu2s`DmC*R_vTMpt{CwyGU~TA3>)@NH zEg4K-Lel~c8B{8|c2DLKg2^h%731Jg!;?{WsakId_=(ENu_2}IvO0K8r}q*NPz%r+ zf+I{eD^BXXJ3}eKf{LS%ctmRaz>M>DLd9k!SNCk|jzV>Qgy{6=f=CVwcvAnN?Bo4~ zJl_-yE@bjv9D-L`8gjBk?$7O6hi@C+>>&5Ty+WPX4=@Yzny}JY;JOdNe_S@Afi1Oe zXRn&w?uo$3MBs-Rd%P=3PY=JPlxt45-ZW(02OmPJk0EgZNr^jlrWP`VDCcwwOh;tEE3H7a}bYyrEZ8x8pGx za^5aX)5`Cen|;Q>41&j59);-aDHwp>F}><>&C|{Idso-3&+t|CRBL5(s86x@-p2#zU5J{J1~kmBLf{<5}e--TtZ3j9++NK{Gq{vIIA=z=9(V!j`_TY z-$pd;>aA7n(VsAa$MKEMY8^4v$pzHmE-?fRDu*$c8BlnX9eJ8!pS#VO;C^O=FI1k)i0pUr}Mc>m~~LG2rGx^WuMu_oDy}l0__iDGA`i z+_~;bGDepuwHDkop`e9KWm;o(5^>8-f444*;1)V{JJS^t;*i@pyD7K6^;p5%B=>w2 z=Px-Xao*3%3l{-Qt}sH*Q=wjGjRk%%!P!^crQ+3m4kFU6f{Guw6@1Z-gp&3Ii6(|E zv2c|dKyRK?oZl`U+lNd))3+LPJcA5GAqW6~_UF~+pclRT-O0Q3h9|^V{7JCah^l|~ z>kT`vu};A$CvO-qX7pKb-B(+Ik&D`2AyQvzce#y`*01syh6Oavd)3Psxiznck1<-! zmXysLzL_qrO}~|#Z2_(8e(fK09ssRCi5)q;?e@;wZgUv+?UJo*M#PN*pC#pNkN?^Q za0u?(7f%Kn{Ciw|zgZ*J0ch>6jtTqw%fX5R;0XSi-Th{7=A(YY_wz6rc_SauwL`KW zI@g03r5&Uvh0SXi%ZT4i_m2_*KwpqUF6CoZoBHI8X*iPU@Zt8?(9G!mgrIJBLjKgKUg)UBxy z5-)jVPt8^L&aE`Py5Tv_5P=#wHQ&FV(fg@`F<547$kb^K*;H&ZKKAF_x=C~3fQ&38 znx7e%b(T$TsF?QCYpJ^hn_hr6kENiWY2Eiug4TDZ7NOXbD=dYpyf2o8V~W^l5dq&r zAD9}>5*))vobHy63*Qc z%eBDwrt=mxWD?r$eG6?7D_D$ldJTzKg^e)#C$!gYtzJVTfEMUCQVZ-X!%#95uZ##% z3?FQi@hP0XM-Vf77QJ2+^8MD@UzwXfM<0fT+ioM3{iX1|@of#0s9Z?H!CGCP-Kjr6 z$sN}FcxR0pywc0fR|Py5c z+_k#tEpw5lY~xckqmIlN09)B266*=w6O;3~aP5&{0LcN&kYz00S#kv4kLwna7jVSe zO7#@x3_bsE?q*u#G>HDf2TW18EppFd^6Uc)f`{kvij37{t5%U5^_7?W1&~$wUW}No z0|R*9KUF%BMi=upn<9k@u$2B#Gw2Z@NgUrvt{|^5!Hla}T6peDyd?BCS@&C`2kJZx z@TaNBgVJQ5`9>nwfpMVaiX!$@U^w2X zfb2TqMX3bFW(If?2P0|0YgmrYL?{XtY=lMu;-H3#9+o@a+}nfX2cU&rZ($unFRt}^-{;KnGGQ914Nh!A&!M|iK<#kG0r_D&%S zJ4Dn`U#1)-5xMrWq+sY6JG5mb<$FZWpsqmkFDk;Oxj$AZ1-ye5zbl-bY`vk$n0^o&b4v}hL(Zq}% zI9@=#F!`pZpYLFsl(C;7R>_I;J99CQ-^J&8oo|^f6ws!$)eq6Uxlf_unr!wMq2=yu zuh6`ls=P;sK*8_|U*aF~UU4emjQuEQE}0_5~#-1Ya|Nv)+O2c0wEE?=}d z(B;kD%Q%IxVHv~8DNnJyeIZ=R3)$u;)OEi?+!?89B)z+>{9u4VAwgx9tm$;D#>+u- zHi!B&sXrp3V#<9vXx>WS-5FD^A1@d~TAX#k_wAFlaviW3y$Y*<6@c(le~_8Z~S|@ZAiaG>|sR`|Qvo z9e%Jn@%l!{KIWZiSakXowDk1kCyZ_W_hD;%-6r#4&VHx%l2-t&ZQ;($9lsPy+8Y24a1GP_AR~DI)FQtTmLURw2hGR-Bi`zrY?h;ToK}eiF3r@%j#Ez za03qskWL*DGy*eu&APm1SvZjs@C&h|6Jy#P^F0`CLcRbm+_NOW;QHZ!MiH?&qBirC z)9eF`yv6o9MVLwkWugmL=Qm|kjO?wJmA|}&MYOGkt{h6=LZk5XtxvQ%R{C#jch5N) z)S6zY|QC06E84v}LH+hj};p3)p+Yz`rZ%{j(wY~Oo*KYzgI zr|(bS{kHe}eZTMPzII*LecjjLwID4M_T|We^a~t~9UICx{?iv!Z{lz6M6`-8c@N8^ z=J?iP1wJdOJ|~C>h~>j?mx57*M-L)--T!$ zycAvdMg+X3&w|x6SWDLOwTjyB-!E7RtCy;qc#VpxZPcCy88n*Wxd-}F=Vqv?Yv_Q^ znBeEIx4T2SVh=z26;CG{bJ_nNu%E)sIN6Pr0;8!DKhDHpd1q6!>+tqpsLPuoV`1aB zvNCkCo$-NQ9g(9nZL2FYLq`8Dn$Cvle-L9TXGEhipH&pd{sr86zm;}VIF2I76h!Ng?&^+!_oe?B-EjEtWfM{kZd0z zZn$_Dk~HnPgHm&~@<`oIab=G-TO0n|b|rBULC8WX$3?GnhQ1ngD9lwgMa(I;!!Id|Nm-^>2Pg_Fcv+JCF2bM^C! zbK&pbn-js~(^C#KO3ktoCNg{7D372LAzlRqVmejdyfAid_$nA|>@ z2Xa%MF|<+f4=dsXviFL~xZR%=!E+CD4doZp?pph%f=nuJF}Z#A{~Q-DC+VlFzkG%! zM|0@Oqqya>ifDvc{H;Pb@~}ybtVSrtg}d(O|2mY7InHY-zR0vyS@^3ROLO(+ED`V0 z+@W2{pw6HV>Q;4m-aOp0YU22c9nPxwKw{crwd_lt=;zqT0b1fGY~SBTw2qqU(~rKd zZjrOR@HqnO*k-W%89dAz(d+osVQ&0=yPhrnLG48NiO#x{pRTo@<1btl9$1Pz-@+bB zonrijN;1qB>>x(xd~A~$86IBx(BtvkNwp3!QKp>W zokwQJzkb0kx->0$izL%;w13bJNA9BK`o&U1>Y=!@MJ3kkZQZU8UD?E(d+Y=q27&7> z4~`j|2nv#4QEx!#KdTM!^iGhk5>UD8E=IlK3Ab#-s0te^^8mjnbPk;{|EWm_@1+3fr8d_$IzDP=*#iTSa++RgwQQz#dG{yOgQ^`w67hY9qu!6pp6>93bvvHhc@weHi7kC zP7~ELB$rTY6J}_jJ3D5{uFnw@{%@i1)m_16=&$QvtuxUk8|*a1A8!nz7FJ8>4LyIM z->2hWoy3R^RA{7j_?ZlUbFSuY&F;7tH7!pDdr4x=iqLM3Yzl(dV>1EI{qrr=Ns)|i zC)Eeicz&fg)SdUk_VckBQyyIh4z~0b37quKac|t;w()K@i8KOIS9Oa7rQ4(X12)u~ z8$F_Tl(ErgcB7qJE4MMjQFA0jB0@47e6eWiu}T5H*#YaY@v|qIUos<%)c9Tnw#@Zz}1NJO$l%S1EL&pEk+^O#)3X|ko{b!b2eOR zjarfm5kPDB7z-7&`vTMy!&uwL|frmm0H40E;P6Tp6~{Fe@$-EsRi%B`~^e z+YBnhv(gCS^ca)$7xMA(Ha0C*0TCj1<=EnImNz;u+*dg(=OND{x0U&J#@qGfgempW z*cifwU~CFAYT|U>kL|eOYZObhOY0qamsnx^WDz6KslWbrvzofe*J}T3;K=D~0rgiZ zlqUC*W8<+p6RP=rGEYF){N?p6EiG0L1t#N$>+Er?^g?YD_PMTOT`nl7O){1>oBEB| z%Ouxwe=@F*{%4l9^*#t2%`Hoz0-fwk4GQyES)^kYlq3&5@W#)re{$nbN|4DxuJ!W#bYkFUREa*TT`U>Yx4+l$}UoD0vMMwzx5xO!AD>-AL4 z_uMKR+?I_;pvgV2fnRiFdoNe3bJVydCO_2Gdmc&lee6Mgk#;UM_()mFb?OuxmM5qT zscvp8KoxYz`oBN?W<+mAO|=wJBPnhTwYV5=%$2@<_gT((r}YcOL9+e5vh_I*gy&yRhDnyGA7nB}k=e}$PwIR(Xh zcQ5<;=gd%fcTZ#n`q*8noyGl7v)WLFiTEQG3gPy~B8HgqJ{~F;Jnkbk$hy+0&G7j`TCy5=U7r`R$1F#CU8%|J8+_tZkW7 z>Nczp8?*Woj0u|Iz9uI>Ei2a`pGfob)Ig8Yrxhes8ZraDRqaH?s`E|?JP9|veJ=Ug zNgGi;F)!jBW9!@D_IU?+noQ0hc^in=O&(-B$uftaSV@Dbu+ab7Dp#n$GgBB?E<*hK zL=_)KVP{koPwf3xT~N9@ex0w`LDD|towCb_V_h!Cp2ga~{v^W;-50|sy%((_Eh1aA zF}L-7ry5`lL)L+s$qSr?oS9M!uZtXtRaB8qzcY@T4ub*z7k9N_xj%{Suj`6}Z-4!& zap4b^Th2YARF6qWWw}r2rC!U^kre!tQ9wJ^(AQ!?XtkJc{(@{>8E_DQ~eHcfbsLl`0c5%SX zq|X4Vui#!GK3r*~rOENb2Fwsn8)^8i{Z*D^I~x!}w>x`Z%l_}~Tm!hI$ro5(o`nEe z`#Rk~-)EvTEh*%Bf~lPGwUPuRoObYyz?T@Oj1CM?Wp#gm`7ynA4y+VSO!-i|2z`ev z=_<@rSq?e4c8Zi{6<2J`zBqTIsR@PikvGzf&@*+;kLI^tKY2+jA#G=^5S zO)A^4n4YX>nNu4Fsebze1%l}icMxLCq5p!Pq#w01JoA2afW`0&Frp1hnVf)B-dkl2 zb$cvpC!;kJb{aJXU#)QJO^dijgSbr1{L|&6LXmRg2#~zQ6Jw)fJuGNv54)^*)E!yx zNp~z~8Z}TFLsZjBr%?esmy3HB<^GUnQJp; zpUh_c=(|KCBQC7jn4DvAZk}^id4NE+2`g45fN4z zNe6dId`cGXhEQ)rREpTg`y!VqXOC)7humlK)KFhupjA&UFHV$VA_x(^=H5!wpXmr^ zCF+&pR^zGt?2CJDPgt~iuAk*%O7~xfC4b9s*1GMVUrC5lzMjbA)EW30ZIN0xE}RqC zo_K*HX_B#MQLSBOSNq*IBl#zV=GyVy#cK37BSVBoRZ78tVm;BG1 z;FoSiSJrfTI+aK%=BRMfuMXYuO6V9)Xw3Oqw>&b|aZ#&?6lmr8iB0O&CC%P1yZ3J8U`rXA$>x2PAGZ+TKJgjn+PNT7GYC!!EEcppd|rDBUm$qw&!1EcmywINYkefJxPi)+OIZVPdePiX3sZJhM0aiaoLmr^8@XK$a(7p|T_Y%BXxFE^ zFKB@pqG3CCu5*+kfEDciot*sP?Fz{!3fXQw6*pg72bb`kc|#!VOTLr&q?EUrB=_>L z%-S$eslY{2Y5~BVpWpVDcKsZ@11!e6F}npduRbsx_-h^H2Li3$sp#C}T2SdTIcc4* zHBN?&+Nx}Wc;cnReprrnq-xt552io0A^|6}BYR7yO~x8X>lGko!k|LTZ3fYU^5td> ze13qb`!~Q3lu`g?xjJ}H?3acJiATize8Jegg<=f=?Dswn^SkIHHCzhP7J#0AeghC~ z`Fn^ZDGl4^<2dOHt2f<}r5T!^eqk--bqPqsg3hdR&ohcszf1qbhs9jkjQ|MGUz(XW zHcKz+naViz$SKg3{N9az6(GJYw(k+~Wb@lk3V{WM3i6rTV|Y*ii@M0(eC{nMM?=oH zvQ~_(p_lCe@}8$X_X(cw;^QixPc+D`?57+#B4Gx2;?=%;LapBxlcRK>fb8?uEFaEF#L=B2@V7@t|q0? zF+C|_D#Kch-H}p@=z(R=DndSP$y>^Ya^^%vu2(7uyv3#1a!l}4j_(hp!zVJ)gJTnH$M_?HHh`Rkh)s& zosHg!^gJtUs${IjF`r z^wgpVX?kcVa&ZDHsh}|Z9<716*z0&n>;QAQwcoXq3SZ%mi0|wxRIyt)CH)O*J&iiSWu(co5gykFt#@SsoW zBcIV5367G3V3~!?t=^SBG~zNi8$*qyLippgl->iWC`tj~6L~h`WKi&zB8+pMED?Z< zo~eB4`DNHu^BsP*wytWh3j=W-gaH6hzl4$Y^?B~!;70J(+x_YmP{>_$`Kx<2tVygL z+;dT~ZG@*(%@sc3DV75c0?j+izYyuVnM#D|-b|oeb9p0`!+u~6^PntC-(U3H$m5eA zK!9iUNM4ORdvxCv#Q zVwAgF;3ps<5PvRw+fS2Qd-+Rf1bp7ZIT^D}TEsWHbR)>s0p#wh@dnYgREvgT=q zb0h#4)!AL5cUul}EH)qEo4gCit?@btgkzPz*6lpde9H$?Nj1Mc(sl)nfZPpoTYiA6 z+?Tl+2eN;Yb@tE3O?I#9s5S3r))(3k}E(&O)ol517z9Rq9DlpshGSqkcN=xrYjw_2-t5>CnR#r~)0;14P8-pqV|#A$Ln2=q}dC^e}I^ z{TA6a9PIc&eh}}5nUM=_D_HfWjd$Zp_709JVZpZ$nijv~wWrZK9C0E4@ju<34J zya62HFoQp00^q%OrjE{>cpca*N@Z}74>;UDaoC|`i2+P``PV!%7~-E`uyRM>X+iu~jn@T5 Date: Wed, 15 Jan 2025 12:26:33 +0100 Subject: [PATCH 04/21] Added CNCF and LF section Closes #237 Signed-off-by: Jean-Baptiste Bianchi --- public/img/logos/cncf-color-bg.svg | 1 + public/img/logos/cncf-white-logo.svg | 1 + public/img/logos/lf-stacked-color.svg | 49 +++++++++++++++++++++++++++ public/img/logos/lf-stacked-white.svg | 1 + src/components/Card.astro | 4 +-- src/components/Section.astro | 2 +- src/pages/community.astro | 2 +- src/pages/index.astro | 12 +++++++ 8 files changed, 68 insertions(+), 4 deletions(-) create mode 100644 public/img/logos/cncf-color-bg.svg create mode 100644 public/img/logos/cncf-white-logo.svg create mode 100644 public/img/logos/lf-stacked-color.svg create mode 100644 public/img/logos/lf-stacked-white.svg diff --git a/public/img/logos/cncf-color-bg.svg b/public/img/logos/cncf-color-bg.svg new file mode 100644 index 0000000..c8d667f --- /dev/null +++ b/public/img/logos/cncf-color-bg.svg @@ -0,0 +1 @@ +cncf-color-bg.svg \ No newline at end of file diff --git a/public/img/logos/cncf-white-logo.svg b/public/img/logos/cncf-white-logo.svg new file mode 100644 index 0000000..bef1f96 --- /dev/null +++ b/public/img/logos/cncf-white-logo.svg @@ -0,0 +1 @@ +cncf-white-logo.svg \ No newline at end of file diff --git a/public/img/logos/lf-stacked-color.svg b/public/img/logos/lf-stacked-color.svg new file mode 100644 index 0000000..e8df47f --- /dev/null +++ b/public/img/logos/lf-stacked-color.svg @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/img/logos/lf-stacked-white.svg b/public/img/logos/lf-stacked-white.svg new file mode 100644 index 0000000..fd7114c --- /dev/null +++ b/public/img/logos/lf-stacked-white.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/components/Card.astro b/src/components/Card.astro index fceee37..14d9dfe 100644 --- a/src/components/Card.astro +++ b/src/components/Card.astro @@ -1,6 +1,6 @@ --- interface Props { - title: string; + title?: string; alignment?: 'center' | 'start' | 'end'; icon?: string; image?: string; @@ -50,7 +50,7 @@ const { `justify-center` ), ]}> - { title } + { title && title } diff --git a/src/components/Section.astro b/src/components/Section.astro index 2f05e83..3c6980a 100644 --- a/src/components/Section.astro +++ b/src/components/Section.astro @@ -45,7 +45,7 @@ const { `max-w-7xl` ), ]}> - { title &&

    { title }

    } + { title &&

    { title }

    } { subTitle &&

    { subTitle }

    } { isGrid ?
    diff --git a/src/pages/community.astro b/src/pages/community.astro index 1b664f8..db5310a 100644 --- a/src/pages/community.astro +++ b/src/pages/community.astro @@ -7,7 +7,7 @@ import Section from '../components/Section.astro';
    -

    Join the Serverless Workflow community

    +

    Join the Serverless Workflow community

    Serverless Workflow is an open source project that anyone in the community can use, improve, and enjoy. We'd love you to join us! Here's a few ways to find out what's happening and get involved.

    diff --git a/src/pages/index.astro b/src/pages/index.astro index 3c03227..efd726f 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -158,4 +158,16 @@ const examples = (await getCollection('example'));
    + + +
    +

    Proudly Open Source

    +

    + Serverless Workflow is an open-source project under the governance of the Cloud Native Computing Foundation (CNCF) and a proud part of the Linux Foundation. +

    +
    + + +
    +
    \ No newline at end of file From f8907275868b8eb5aa75b416cecb12fe301a94aa Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Bianchi <72747835+JBBianchi@users.noreply.github.com> Date: Wed, 15 Jan 2025 16:15:02 +0100 Subject: [PATCH 05/21] Removed double title in content files (#234) Signed-off-by: Jean-Baptiste Bianchi --- src/content/blog/releases/release-sdk-rust.md | 2 -- .../blog/releases/release-sdk-typescript-1.0.0-alpha5.md | 2 -- src/content/blog/releases/release-sdk-typescript-legacy.md | 2 -- 3 files changed, 6 deletions(-) diff --git a/src/content/blog/releases/release-sdk-rust.md b/src/content/blog/releases/release-sdk-rust.md index 169914d..335f026 100644 --- a/src/content/blog/releases/release-sdk-rust.md +++ b/src/content/blog/releases/release-sdk-rust.md @@ -6,8 +6,6 @@ description: > Introducing the first alpha release of the Serverless Workflow Rust SDK, version v1.0.0-alpha1. --- -# Announcing the Serverless Workflow Rust SDK v1.0.0-alpha1 - Hello, Serverless Workflow community! We are thrilled to announce the release of the very first alpha version of the **Serverless Workflow Rust SDK**! Version `v1.0.0-alpha6` marks an exciting milestone as we bring the power of the Serverless Workflow specification to the Rust ecosystem. diff --git a/src/content/blog/releases/release-sdk-typescript-1.0.0-alpha5.md b/src/content/blog/releases/release-sdk-typescript-1.0.0-alpha5.md index aacef24..014cab2 100644 --- a/src/content/blog/releases/release-sdk-typescript-1.0.0-alpha5.md +++ b/src/content/blog/releases/release-sdk-typescript-1.0.0-alpha5.md @@ -6,8 +6,6 @@ description: > Announcing the availability of the v1.0.0-alpha5.0 package for the Serverless Workflow TypeScript SDK. --- -# Announcing the Serverless Workflow TypeScript SDK v1.0.0-alpha5.0 - Hello, Serverless Workflow community! We are excited to announce the release of version `1.0.0-alpha5.0` of the TypeScript SDK for the Serverless Workflow specification. This release brings us one step closer to a stable and production-ready v1.0.0. diff --git a/src/content/blog/releases/release-sdk-typescript-legacy.md b/src/content/blog/releases/release-sdk-typescript-legacy.md index 9702453..4de51d5 100644 --- a/src/content/blog/releases/release-sdk-typescript-legacy.md +++ b/src/content/blog/releases/release-sdk-typescript-legacy.md @@ -6,8 +6,6 @@ description: > Legacy Branch & Release for the TypeScript SDK --- -# Announcing the Legacy Branch & release for Serverless Workflow TypeScript SDK - Hello, Serverless Workflow community! I'm excited to share some important updates regarding the TypeScript SDK for the Serverless Workflow specification. As many of you know, our specification underwent a significant rewrite after version 0.9, culminating in the anticipated release of version 1.0.0-alpha. This update will bring many improvements and changes, aligning the spec with the latest needs and trends in serverless architectures. From 98acab5d448bad1088c8a80b5bbdef864818f26f Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Bianchi Date: Wed, 15 Jan 2025 17:15:02 +0100 Subject: [PATCH 06/21] Included @cdavernas reviews Signed-off-by: Jean-Baptiste Bianchi --- src/components/Section.astro | 2 +- src/pages/index.astro | 9 ++++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/components/Section.astro b/src/components/Section.astro index 3c6980a..bf6bdd1 100644 --- a/src/components/Section.astro +++ b/src/components/Section.astro @@ -48,7 +48,7 @@ const { { title &&

    { title }

    } { subTitle &&

    { subTitle }

    } { isGrid ? -
    +
    : diff --git a/src/pages/index.astro b/src/pages/index.astro index 537fc35..2645e21 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -161,11 +161,10 @@ const examples = (await getCollection('example'));
    -

    Proudly Open Source

    -

    - Serverless Workflow is an open-source project under the governance of the Cloud Native Computing Foundation (CNCF) and a proud part of the Linux Foundation. -

    -
    +

    Innovation in the Open

    +

    Serverless Workflow is an open-source project under the governance of the Cloud Native Computing Foundation (CNCF) and a part of the Linux Foundation.

    +

    The project is in the Application Definition & Image Build landscape.

    +
    From a3f3b7bb05fbff104bff11e0785ee53a106f10ad Mon Sep 17 00:00:00 2001 From: Alvin Engler Date: Tue, 14 Jan 2025 18:26:21 -0800 Subject: [PATCH 07/21] foxflow link per @cdavernas suggestion Signed-off-by: Alvin Engler --- public/img/logos/foxflow.svg | 12 ++++++++++++ src/pages/index.astro | 8 ++++++-- 2 files changed, 18 insertions(+), 2 deletions(-) create mode 100644 public/img/logos/foxflow.svg diff --git a/public/img/logos/foxflow.svg b/public/img/logos/foxflow.svg new file mode 100644 index 0000000..85b4789 --- /dev/null +++ b/public/img/logos/foxflow.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/src/pages/index.astro b/src/pages/index.astro index 16ba9dd..b3c3b82 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -97,7 +97,7 @@ const examples = (await getCollection('example')); Open Slack
    - +
    @@ -128,6 +128,10 @@ const examples = (await getCollection('example'));

    FaasNet makes it easy to deploy functions and API to Kubernetes without repetitive, boiler-plate coding.

    Learn More
    + +

    Foxflow's AI agent development platform accelerates business process automation and software delivery through LLM-integrated declarative workflows

    + Learn More +

    Huawei FunctionGraph hosts event-driven functions in a serverless context while ensuring high availability, high scalability, and zero maintenance.

    Learn More @@ -156,4 +160,4 @@ const examples = (await getCollection('example'));
    - \ No newline at end of file + From fdad22c0e76a28de90188a7874b2857bb3337b57 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Bianchi <72747835+JBBianchi@users.noreply.github.com> Date: Thu, 16 Jan 2025 15:40:15 +0100 Subject: [PATCH 08/21] Updates key benefits (#241) - updated key benefits - added link to use cases Closes #240 Signed-off-by: Jean-Baptiste Bianchi --- src/pages/index.astro | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/pages/index.astro b/src/pages/index.astro index 55d3e1e..34e70ba 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -46,23 +46,23 @@ const examples = (await getCollection('example'));
    - -

    Serverless Workflow DSL simplifies workflow concepts, allowing users to easily create complex workflows.

    + +

    Designed with linguistic fluency, implicit default behaviors, and minimal technical jargon, making workflows accessible to developers with diverse skill levels and enhancing collaboration.

    -

    Integrate events seamlessly into workflows with support for formats like CloudEvents, enabling event-driven architectures.

    +

    Supports event-driven execution and various scheduling options, including CRON expressions and time-based triggers, to respond efficiently to dynamic conditions.

    - -

    The Serverless Workflow DSL allows developers to integrate with service-oriented architectures, defining workflows that interact with services using protocols like HTTP, GRPC, OpenAPI, and AsyncAPI.

    + +

    Seamlessly integrates with multiple protocols (HTTP, gRPC, OpenAPI, AsyncAPI), ensuring easy communication with external systems and services, along with support for custom interactions via scripts, containers, or shell commands.

    - -

    Invoke functions across platforms seamlessly within workflows, supporting FaaS and microservices architectures.

    + +

    Serverless Workflow enables developers to build workflows that can operate across diverse platforms and environments, eliminating the need for platform-specific adaptations.

    - -

    Set timeouts for workflows and tasks to manage execution duration.

    + +

    Provides extensible components and supports defining custom functions and extensions, allowing developers to tailor workflows to unique business requirements without compromising compatibility.

    -

    Define error handling strategies to manage and recover from workflow execution errors, ensuring robustness and reliability.

    +

    Offers comprehensive data transformation, validation, and fault tolerance mechanisms, ensuring workflows are robust, reliable, and capable of handling complex processes and failures gracefully.

    @@ -79,9 +79,9 @@ const examples = (await getCollection('example')); )) } - +

    + Visit our GitHub repository for more examples or complete use cases.

    +

    From 334478f1a31e37a04d93b503cc908fc4b9e03767 Mon Sep 17 00:00:00 2001 From: Ricardo Zanini <1538000+ricardozanini@users.noreply.github.com> Date: Wed, 22 Jan 2025 17:15:44 -0500 Subject: [PATCH 09/21] [blog] - Go SDK 3.0.0 announcement --- .../blog/releases/release-sdk-go-3.0.0.md | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 src/content/blog/releases/release-sdk-go-3.0.0.md diff --git a/src/content/blog/releases/release-sdk-go-3.0.0.md b/src/content/blog/releases/release-sdk-go-3.0.0.md new file mode 100644 index 0000000..5020de2 --- /dev/null +++ b/src/content/blog/releases/release-sdk-go-3.0.0.md @@ -0,0 +1,47 @@ +--- +title: "Announcing Serverless Workflow SDK Go 3.0.0" +date: "2025-01-22" +description: "Discover the new features and improvements in Serverless Workflow SDK Go 3.0.0, aligned with the Serverless Workflow specification 1.0.0." +author: "Serverless Workflow Team" +--- + +# Announcing Serverless Workflow SDK Go 3.0.0 + +We are thrilled to announce the release of **Serverless Workflow SDK Go 3.0.0**, a milestone that aligns with the latest Serverless Workflow specification (v1.0.0). + +## **What’s New in 3.0.0?** + +This release introduces a host of new features and improvements: + +1. **Support for Serverless Workflow Specification 1.0.0** + The SDK now fully supports the latest workflow specification, ensuring compatibility with modern standards and enabling developers to leverage advanced features effortlessly. + +2. **Improved DSL Parsing** + The new implementation of the DSL parser ensures more robust validation and parsing of workflow definitions, adhering strictly to the updated JSON Schema. + +3. **Reusable Components** + The introduction of reusable components such as authentication policies, error handlers, and catalogs simplifies workflow definitions and promotes consistency across workflows. + +4. **Schema Validation and Interoperability** + With Go validators integrated natively, developers can rely on robust schema validation for input, output, and context management, ensuring workflows are reliable and error-free. + +5. **Developer-Focused Improvements** + - Enhanced Go language idioms for better developer experience. + - Improved code organization for scalability and maintainability. + +## **Getting Started** + +Upgrading to the new version is straightforward: + +1. Update your project to use the new `v3` path: + ```bash + go get github.com/serverlessworkflow/sdk-go/v3 + ``` + +2. Update your code to accommodate the new DSL and schema changes. Refer to the updated [specification](https://github.com/serverlessworkflow/specification/tree/main/examples) for examples. + +3. Run your tests and validate your workflows against the new schema to ensure a smooth transition. + +## **Join the Community** + +We are proud of what we’ve accomplished with version 3.0.0, and we’re excited to see how you will use it to create innovative solutions. Share your feedback, contributions, and ideas on our [GitHub issue page](https://github.com/serverlessworkflow/sdk-go/issues). From a01d660b7ddb92ccb36a098c10ad649d2844480f Mon Sep 17 00:00:00 2001 From: Ricardo Zanini <1538000+ricardozanini@users.noreply.github.com> Date: Mon, 27 Jan 2025 09:21:04 -0500 Subject: [PATCH 10/21] Remove unnecessary title from the go sdk announcement --- src/content/blog/releases/release-sdk-go-3.0.0.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/content/blog/releases/release-sdk-go-3.0.0.md b/src/content/blog/releases/release-sdk-go-3.0.0.md index 5020de2..af266fb 100644 --- a/src/content/blog/releases/release-sdk-go-3.0.0.md +++ b/src/content/blog/releases/release-sdk-go-3.0.0.md @@ -5,8 +5,6 @@ description: "Discover the new features and improvements in Serverless Workflow author: "Serverless Workflow Team" --- -# Announcing Serverless Workflow SDK Go 3.0.0 - We are thrilled to announce the release of **Serverless Workflow SDK Go 3.0.0**, a milestone that aligns with the latest Serverless Workflow specification (v1.0.0). ## **What’s New in 3.0.0?** From 766248d4fff6b2cc7331ae283ff2dff39fc07058 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Bianchi <72747835+JBBianchi@users.noreply.github.com> Date: Tue, 28 Jan 2025 15:43:19 +0100 Subject: [PATCH 11/21] v1.0.0 announcement (#245) - Added v1 schemas - Updated examples for v1 - Added v1 announcement blog post Signed-off-by: Jean-Baptiste Bianchi --- _redirects | 6 +- public/schemas/1.0.0/workflow.json | 2694 ++++++++++++++++++++ public/schemas/1.0.0/workflow.yaml | 1758 +++++++++++++ src/consts.ts | 2 + src/content/blog/releases/release-1.0.0.md | 33 + src/content/examples/async-api.md | 4 +- src/content/examples/container.md | 4 +- src/content/examples/emit.md | 4 +- src/content/examples/for.md | 4 +- src/content/examples/fork.md | 4 +- src/content/examples/grpc.md | 4 +- src/content/examples/http.md | 4 +- src/content/examples/listen.md | 4 +- src/content/examples/open-api.md | 4 +- src/content/examples/raise.md | 4 +- src/content/examples/script.md | 2 +- src/content/examples/subflow.md | 6 +- src/content/examples/switch.md | 4 +- src/content/examples/try.md | 2 +- src/content/examples/wait.md | 4 +- src/pages/index.astro | 4 +- 21 files changed, 4521 insertions(+), 34 deletions(-) create mode 100644 public/schemas/1.0.0/workflow.json create mode 100644 public/schemas/1.0.0/workflow.yaml create mode 100644 src/content/blog/releases/release-1.0.0.md diff --git a/_redirects b/_redirects index afc9ffd..2a1e19e 100644 --- a/_redirects +++ b/_redirects @@ -1,5 +1,5 @@ # See: https://docs.netlify.com/routing/redirects/ # https://docs.netlify.com/routing/redirects/redirect-options/ -/schemas/previous/* /schemas/0.8/:splat 200 -/schemas/latest/* /schemas/0.9/:splat 200 -/schemas/snapshot/* /schemas/1.0.0-alpha5/:splat 200 +/schemas/previous/* /schemas/0.9/:splat 200 +/schemas/latest/* /schemas/1.0.0/:splat 200 +/schemas/snapshot/* /schemas/1.0.0/:splat 200 diff --git a/public/schemas/1.0.0/workflow.json b/public/schemas/1.0.0/workflow.json new file mode 100644 index 0000000..8fc3565 --- /dev/null +++ b/public/schemas/1.0.0/workflow.json @@ -0,0 +1,2694 @@ +{ + "$id": "https://serverlessworkflow.io/schemas/1.0.0/workflow.json", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "description": "Serverless Workflow DSL - Workflow Schema.", + "type": "object", + "required": [ + "document", + "do" + ], + "properties": { + "document": { + "type": "object", + "title": "Document", + "description": "Documents the workflow.", + "unevaluatedProperties": false, + "properties": { + "dsl": { + "type": "string", + "pattern": "^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$", + "title": "WorkflowDSL", + "description": "The version of the DSL used by the workflow." + }, + "namespace": { + "type": "string", + "pattern": "^[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?$", + "title": "WorkflowNamespace", + "description": "The workflow's namespace." + }, + "name": { + "type": "string", + "pattern": "^[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?$", + "title": "WorkflowName", + "description": "The workflow's name." + }, + "version": { + "type": "string", + "pattern": "^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$", + "title": "WorkflowVersion", + "description": "The workflow's semantic version." + }, + "title": { + "type": "string", + "title": "WorkflowTitle", + "description": "The workflow's title." + }, + "summary": { + "type": "string", + "title": "WorkflowSummary", + "description": "The workflow's Markdown summary." + }, + "tags": { + "type": "object", + "title": "WorkflowTags", + "description": "A key/value mapping of the workflow's tags, if any.", + "additionalProperties": true + }, + "metadata": { + "type": "object", + "title": "WorkflowMetadata", + "description": "Holds additional information about the workflow.", + "additionalProperties": true + } + }, + "required": [ + "dsl", + "namespace", + "name", + "version" + ] + }, + "input": { + "$ref": "#/$defs/input", + "title": "Input", + "description": "Configures the workflow's input." + }, + "use": { + "type": "object", + "title": "Use", + "description": "Defines the workflow's reusable components.", + "unevaluatedProperties": false, + "properties": { + "authentications": { + "type": "object", + "title": "UseAuthentications", + "description": "The workflow's reusable authentication policies.", + "additionalProperties": { + "$ref": "#/$defs/authenticationPolicy" + } + }, + "errors": { + "type": "object", + "title": "UseErrors", + "description": "The workflow's reusable errors.", + "additionalProperties": { + "$ref": "#/$defs/error" + } + }, + "extensions": { + "type": "array", + "title": "UseExtensions", + "description": "The workflow's extensions.", + "items": { + "type": "object", + "title": "ExtensionItem", + "minProperties": 1, + "maxProperties": 1, + "additionalProperties": { + "$ref": "#/$defs/extension" + } + } + }, + "functions": { + "type": "object", + "title": "UseFunctions", + "description": "The workflow's reusable functions.", + "additionalProperties": { + "$ref": "#/$defs/task" + } + }, + "retries": { + "type": "object", + "title": "UseRetries", + "description": "The workflow's reusable retry policies.", + "additionalProperties": { + "$ref": "#/$defs/retryPolicy" + } + }, + "secrets": { + "type": "array", + "title": "UseSecrets", + "description": "The workflow's reusable secrets.", + "items": { + "type": "string", + "description": "The workflow's secrets." + } + }, + "timeouts": { + "type": "object", + "title": "UseTimeouts", + "description": "The workflow's reusable timeouts.", + "additionalProperties": { + "$ref": "#/$defs/timeout" + } + }, + "catalogs": { + "type": "object", + "title": "UseCatalogs", + "description": "The workflow's reusable catalogs.", + "additionalProperties": { + "$ref": "#/$defs/catalog" + } + } + } + }, + "do": { + "$ref": "#/$defs/taskList", + "title": "Do", + "description": "Defines the task(s) the workflow must perform." + }, + "timeout": { + "title": "DoTimeout", + "oneOf": [ + { + "$ref": "#/$defs/timeout", + "title": "TimeoutDefinition", + "description": "The workflow's timeout configuration, if any." + }, + { + "type": "string", + "title": "TimeoutReference", + "description": "The name of the workflow's timeout, if any." + } + ] + }, + "output": { + "$ref": "#/$defs/output", + "title": "Output", + "description": "Configures the workflow's output." + }, + "schedule": { + "type": "object", + "title": "Schedule", + "description": "Schedules the workflow.", + "unevaluatedProperties": false, + "properties": { + "every": { + "$ref": "#/$defs/duration", + "title": "ScheduleEvery", + "description": "Specifies the duration of the interval at which the workflow should be executed." + }, + "cron": { + "type": "string", + "title": "ScheduleCron", + "description": "Specifies the schedule using a cron expression, e.g., '0 0 * * *' for daily at midnight." + }, + "after": { + "$ref": "#/$defs/duration", + "title": "ScheduleAfter", + "description": "Specifies a delay duration that the workflow must wait before starting again after it completes." + }, + "on": { + "$ref": "#/$defs/eventConsumptionStrategy", + "title": "ScheduleOn", + "description": "Specifies the events that trigger the workflow execution." + } + } + } + }, + "$defs": { + "taskList": { + "title": "TaskList", + "description": "List of named tasks to perform.", + "type": "array", + "items": { + "type": "object", + "title": "TaskItem", + "minProperties": 1, + "maxProperties": 1, + "additionalProperties": { + "$ref": "#/$defs/task" + } + } + }, + "taskBase": { + "type": "object", + "title": "TaskBase", + "description": "An object inherited by all tasks.", + "properties": { + "if": { + "type": "string", + "title": "TaskBaseIf", + "description": "A runtime expression, if any, used to determine whether or not the task should be run." + }, + "input": { + "$ref": "#/$defs/input", + "title": "TaskBaseInput", + "description": "Configure the task's input." + }, + "output": { + "$ref": "#/$defs/output", + "title": "TaskBaseOutput", + "description": "Configure the task's output." + }, + "export": { + "$ref": "#/$defs/export", + "title": "TaskBaseExport", + "description": "Export task output to context." + }, + "timeout": { + "title": "TaskTimeout", + "oneOf": [ + { + "$ref": "#/$defs/timeout", + "title": "TaskTimeoutDefinition", + "description": "The task's timeout configuration, if any." + }, + { + "type": "string", + "title": "TaskTimeoutReference", + "description": "The name of the task's timeout, if any." + } + ] + }, + "then": { + "$ref": "#/$defs/flowDirective", + "title": "TaskBaseThen", + "description": "The flow directive to be performed upon completion of the task." + }, + "metadata": { + "type": "object", + "title": "TaskMetadata", + "description": "Holds additional information about the task.", + "additionalProperties": true + } + } + }, + "task": { + "title": "Task", + "description": "A discrete unit of work that contributes to achieving the overall objectives defined by the workflow.", + "unevaluatedProperties": false, + "oneOf": [ + { + "$ref": "#/$defs/callTask" + }, + { + "$ref": "#/$defs/doTask" + }, + { + "$ref": "#/$defs/forkTask" + }, + { + "$ref": "#/$defs/emitTask" + }, + { + "$ref": "#/$defs/forTask" + }, + { + "$ref": "#/$defs/listenTask" + }, + { + "$ref": "#/$defs/raiseTask" + }, + { + "$ref": "#/$defs/runTask" + }, + { + "$ref": "#/$defs/setTask" + }, + { + "$ref": "#/$defs/switchTask" + }, + { + "$ref": "#/$defs/tryTask" + }, + { + "$ref": "#/$defs/waitTask" + } + ] + }, + "callTask": { + "title": "CallTask", + "description": "Defines the call to perform.", + "oneOf": [ + { + "title": "CallAsyncAPI", + "description": "Defines the AsyncAPI call to perform.", + "$ref": "#/$defs/taskBase", + "type": "object", + "required": [ + "call", + "with" + ], + "unevaluatedProperties": false, + "properties": { + "call": { + "type": "string", + "const": "asyncapi" + }, + "with": { + "type": "object", + "title": "AsyncApiArguments", + "description": "The Async API call arguments.", + "properties": { + "document": { + "$ref": "#/$defs/externalResource", + "title": "AsyncAPIDocument", + "description": "The document that defines the AsyncAPI operation to call." + }, + "channel": { + "type": "string", + "title": "With", + "description": "The name of the channel on which to perform the operation. Used only in case the referenced document uses AsyncAPI v2.6.0." + }, + "operation": { + "type": "string", + "title": "AsyncAPIOperation", + "description": "A reference to the AsyncAPI operation to call." + }, + "server": { + "$ref": "#/$defs/asyncApiServer", + "title": "AsyncAPIServer", + "description": "An object used to configure to the server to call the specified AsyncAPI operation on." + }, + "protocol": { + "type": "string", + "title": "AsyncApiProtocol", + "description": "The protocol to use to select the target server.", + "enum": [ + "amqp", + "amqp1", + "anypointmq", + "googlepubsub", + "http", + "ibmmq", + "jms", + "kafka", + "mercure", + "mqtt", + "mqtt5", + "nats", + "pulsar", + "redis", + "sns", + "solace", + "sqs", + "stomp", + "ws" + ] + }, + "message": { + "$ref": "#/$defs/asyncApiOutboundMessage", + "title": "AsyncApiMessage", + "description": "An object used to configure the message to publish using the target operation." + }, + "subscription": { + "$ref": "#/$defs/asyncApiSubscription", + "title": "AsyncApiSubscription", + "description": "An object used to configure the subscription to messages consumed using the target operation." + }, + "authentication": { + "$ref": "#/$defs/referenceableAuthenticationPolicy", + "title": "AsyncAPIAuthentication", + "description": "The authentication policy, if any, to use when calling the AsyncAPI operation." + } + }, + "oneOf": [ + { + "required": [ + "document", + "operation", + "message" + ] + }, + { + "required": [ + "document", + "operation", + "subscription" + ] + }, + { + "required": [ + "document", + "channel", + "message" + ] + }, + { + "required": [ + "document", + "channel", + "subscription" + ] + } + ], + "unevaluatedProperties": false + } + } + }, + { + "title": "CallGRPC", + "description": "Defines the GRPC call to perform.", + "$ref": "#/$defs/taskBase", + "type": "object", + "unevaluatedProperties": false, + "required": [ + "call", + "with" + ], + "properties": { + "call": { + "type": "string", + "const": "grpc" + }, + "with": { + "type": "object", + "title": "GRPCArguments", + "description": "The GRPC call arguments.", + "properties": { + "proto": { + "$ref": "#/$defs/externalResource", + "title": "WithGRPCProto", + "description": "The proto resource that describes the GRPC service to call." + }, + "service": { + "type": "object", + "title": "WithGRPCService", + "unevaluatedProperties": false, + "properties": { + "name": { + "type": "string", + "title": "WithGRPCServiceName", + "description": "The name of the GRPC service to call." + }, + "host": { + "type": "string", + "title": "WithGRPCServiceHost", + "description": "The hostname of the GRPC service to call.", + "pattern": "^[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?$" + }, + "port": { + "type": "integer", + "title": "WithGRPCServicePost", + "description": "The port number of the GRPC service to call.", + "minimum": 0, + "maximum": 65535 + }, + "authentication": { + "$ref": "#/$defs/referenceableAuthenticationPolicy", + "title": "WithGRPCServiceAuthentication", + "description": "The endpoint's authentication policy, if any." + } + }, + "required": [ + "name", + "host" + ] + }, + "method": { + "type": "string", + "title": "WithGRPCMethod", + "description": "The name of the method to call on the defined GRPC service." + }, + "arguments": { + "type": "object", + "title": "WithGRPCArguments", + "description": "The arguments, if any, to call the method with.", + "additionalProperties": true + } + }, + "required": [ + "proto", + "service", + "method" + ], + "unevaluatedProperties": false + } + } + }, + { + "title": "CallHTTP", + "description": "Defines the HTTP call to perform.", + "$ref": "#/$defs/taskBase", + "type": "object", + "unevaluatedProperties": false, + "required": [ + "call", + "with" + ], + "properties": { + "call": { + "type": "string", + "const": "http" + }, + "with": { + "type": "object", + "title": "HTTPArguments", + "description": "The HTTP call arguments.", + "properties": { + "method": { + "type": "string", + "title": "HTTPMethod", + "description": "The HTTP method of the HTTP request to perform." + }, + "endpoint": { + "title": "HTTPEndpoint", + "description": "The HTTP endpoint to send the request to.", + "$ref": "#/$defs/endpoint" + }, + "headers": { + "type": "object", + "title": "HTTPHeaders", + "description": "A name/value mapping of the headers, if any, of the HTTP request to perform." + }, + "body": { + "title": "HTTPBody", + "description": "The body, if any, of the HTTP request to perform." + }, + "query": { + "type": "object", + "title": "HTTPQuery", + "description": "A name/value mapping of the query parameters, if any, of the HTTP request to perform.", + "additionalProperties": true + }, + "output": { + "type": "string", + "title": "HTTPOutput", + "description": "The http call output format. Defaults to 'content'.", + "enum": [ + "raw", + "content", + "response" + ] + }, + "redirect": { + "type": "boolean", + "title": "HttpRedirect", + "description": "Specifies whether redirection status codes (`300–399`) should be treated as errors." + } + }, + "required": [ + "method", + "endpoint" + ], + "unevaluatedProperties": false + } + } + }, + { + "title": "CallOpenAPI", + "description": "Defines the OpenAPI call to perform.", + "$ref": "#/$defs/taskBase", + "type": "object", + "unevaluatedProperties": false, + "required": [ + "call", + "with" + ], + "properties": { + "call": { + "type": "string", + "const": "openapi" + }, + "with": { + "type": "object", + "title": "OpenAPIArguments", + "description": "The OpenAPI call arguments.", + "properties": { + "document": { + "$ref": "#/$defs/externalResource", + "title": "WithOpenAPIDocument", + "description": "The document that defines the OpenAPI operation to call." + }, + "operationId": { + "type": "string", + "title": "WithOpenAPIOperation", + "description": "The id of the OpenAPI operation to call." + }, + "parameters": { + "type": "object", + "title": "WithOpenAPIParameters", + "description": "A name/value mapping of the parameters of the OpenAPI operation to call.", + "additionalProperties": true + }, + "authentication": { + "$ref": "#/$defs/referenceableAuthenticationPolicy", + "title": "WithOpenAPIAuthentication", + "description": "The authentication policy, if any, to use when calling the OpenAPI operation." + }, + "output": { + "type": "string", + "enum": [ + "raw", + "content", + "response" + ], + "title": "WithOpenAPIOutput", + "description": "The http call output format. Defaults to 'content'." + }, + "redirect": { + "type": "boolean", + "title": "HttpRedirect", + "description": "Specifies whether redirection status codes (`300–399`) should be treated as errors." + } + }, + "required": [ + "document", + "operationId" + ], + "unevaluatedProperties": false + } + } + }, + { + "title": "CallFunction", + "description": "Defines the function call to perform.", + "$ref": "#/$defs/taskBase", + "type": "object", + "unevaluatedProperties": false, + "required": [ + "call" + ], + "properties": { + "call": { + "type": "string", + "not": { + "enum": [ + "asyncapi", + "grpc", + "http", + "openapi" + ] + }, + "description": "The name of the function to call." + }, + "with": { + "type": "object", + "title": "FunctionArguments", + "description": "A name/value mapping of the parameters, if any, to call the function with.", + "additionalProperties": true + } + } + } + ] + }, + "forkTask": { + "type": "object", + "$ref": "#/$defs/taskBase", + "title": "ForkTask", + "description": "Allows workflows to execute multiple tasks concurrently and optionally race them against each other, with a single possible winner, which sets the task's output.", + "unevaluatedProperties": false, + "required": [ + "fork" + ], + "properties": { + "fork": { + "type": "object", + "title": "ForkTaskConfiguration", + "description": "The configuration of the branches to perform concurrently.", + "unevaluatedProperties": false, + "required": [ + "branches" + ], + "properties": { + "branches": { + "$ref": "#/$defs/taskList", + "title": "ForkBranches" + }, + "compete": { + "type": "boolean", + "title": "ForkCompete", + "description": "Indicates whether or not the concurrent tasks are racing against each other, with a single possible winner, which sets the composite task's output.", + "default": false + } + } + } + } + }, + "doTask": { + "type": "object", + "$ref": "#/$defs/taskBase", + "title": "DoTask", + "description": "Allows to execute a list of tasks in sequence.", + "unevaluatedProperties": false, + "required": [ + "do" + ], + "properties": { + "do": { + "$ref": "#/$defs/taskList", + "title": "DoTaskConfiguration", + "description": "The configuration of the tasks to perform sequentially." + } + } + }, + "emitTask": { + "type": "object", + "$ref": "#/$defs/taskBase", + "title": "EmitTask", + "description": "Allows workflows to publish events to event brokers or messaging systems, facilitating communication and coordination between different components and services.", + "required": [ + "emit" + ], + "unevaluatedProperties": false, + "properties": { + "emit": { + "type": "object", + "title": "EmitTaskConfiguration", + "description": "The configuration of an event's emission.", + "unevaluatedProperties": false, + "properties": { + "event": { + "type": "object", + "title": "EmitEventDefinition", + "description": "The definition of the event to emit.", + "properties": { + "with": { + "$ref": "#/$defs/eventProperties", + "title": "EmitEventWith", + "description": "Defines the properties of event to emit.", + "required": [ + "source", + "type" + ] + } + }, + "additionalProperties": true + } + }, + "required": [ + "event" + ] + } + } + }, + "forTask": { + "type": "object", + "$ref": "#/$defs/taskBase", + "title": "ForTask", + "description": "Allows workflows to iterate over a collection of items, executing a defined set of subtasks for each item in the collection. This task type is instrumental in handling scenarios such as batch processing, data transformation, and repetitive operations across datasets.", + "required": [ + "for", + "do" + ], + "unevaluatedProperties": false, + "properties": { + "for": { + "type": "object", + "title": "ForTaskConfiguration", + "description": "The definition of the loop that iterates over a range of values.", + "unevaluatedProperties": false, + "properties": { + "each": { + "type": "string", + "title": "ForEach", + "description": "The name of the variable used to store the current item being enumerated.", + "default": "item" + }, + "in": { + "type": "string", + "title": "ForIn", + "description": "A runtime expression used to get the collection to enumerate." + }, + "at": { + "type": "string", + "title": "ForAt", + "description": "The name of the variable used to store the index of the current item being enumerated.", + "default": "index" + } + }, + "required": [ + "in" + ] + }, + "while": { + "type": "string", + "title": "While", + "description": "A runtime expression that represents the condition, if any, that must be met for the iteration to continue." + }, + "do": { + "$ref": "#/$defs/taskList", + "title": "ForTaskDo" + } + } + }, + "listenTask": { + "type": "object", + "$ref": "#/$defs/taskBase", + "title": "ListenTask", + "description": "Provides a mechanism for workflows to await and react to external events, enabling event-driven behavior within workflow systems.", + "required": [ + "listen" + ], + "unevaluatedProperties": false, + "properties": { + "listen": { + "type": "object", + "title": "ListenTaskConfiguration", + "description": "The configuration of the listener to use.", + "unevaluatedProperties": false, + "properties": { + "to": { + "$ref": "#/$defs/eventConsumptionStrategy", + "title": "ListenTo", + "description": "Defines the event(s) to listen to." + }, + "read": { + "type": "string", + "enum": [ + "data", + "envelope", + "raw" + ], + "default": "data", + "title": "ListenAndReadAs", + "description": "Specifies how events are read during the listen operation." + } + }, + "required": [ + "to" + ] + }, + "foreach": { + "$ref": "#/$defs/subscriptionIterator", + "title": "ListenIterator", + "description": "Configures the iterator, if any, for processing consumed event(s)." + } + } + }, + "raiseTask": { + "type": "object", + "$ref": "#/$defs/taskBase", + "title": "RaiseTask", + "description": "Intentionally triggers and propagates errors.", + "required": [ + "raise" + ], + "unevaluatedProperties": false, + "properties": { + "raise": { + "type": "object", + "title": "RaiseTaskConfiguration", + "description": "The definition of the error to raise.", + "unevaluatedProperties": false, + "properties": { + "error": { + "title": "RaiseTaskError", + "oneOf": [ + { + "$ref": "#/$defs/error", + "title": "RaiseErrorDefinition", + "description": "Defines the error to raise." + }, + { + "type": "string", + "title": "RaiseErrorReference", + "description": "The name of the error to raise" + } + ] + } + }, + "required": [ + "error" + ] + } + } + }, + "runTask": { + "type": "object", + "$ref": "#/$defs/taskBase", + "title": "RunTask", + "description": "Provides the capability to execute external containers, shell commands, scripts, or workflows.", + "required": [ + "run" + ], + "unevaluatedProperties": false, + "properties": { + "run": { + "type": "object", + "title": "RunTaskConfiguration", + "description": "The configuration of the process to execute.", + "unevaluatedProperties": false, + "properties": { + "await": { + "type": "boolean", + "default": true, + "title": "AwaitProcessCompletion", + "description": "Whether to await the process completion before continuing." + }, + "return": { + "type": "string", + "title": "ProcessReturnType", + "description": "Configures the output of the process.", + "enum": [ + "stdout", + "stderr", + "code", + "all", + "none" + ], + "default": "stdout" + } + }, + "oneOf": [ + { + "title": "RunContainer", + "description": "Enables the execution of external processes encapsulated within a containerized environment.", + "properties": { + "container": { + "type": "object", + "title": "Container", + "description": "The configuration of the container to run.", + "unevaluatedProperties": false, + "properties": { + "image": { + "type": "string", + "title": "ContainerImage", + "description": "The name of the container image to run." + }, + "name": { + "type": "string", + "title": "ContainerName", + "description": "A runtime expression, if any, used to give specific name to the container." + }, + "command": { + "type": "string", + "title": "ContainerCommand", + "description": "The command, if any, to execute on the container." + }, + "ports": { + "type": "object", + "title": "ContainerPorts", + "description": "The container's port mappings, if any." + }, + "volumes": { + "type": "object", + "title": "ContainerVolumes", + "description": "The container's volume mappings, if any." + }, + "environment": { + "type": "object", + "title": "ContainerEnvironment", + "description": "A key/value mapping of the environment variables, if any, to use when running the configured process." + }, + "lifetime": { + "$ref": "#/$defs/containerLifetime", + "title": "ContainerLifetime", + "description": "An object, if any, used to configure the container's lifetime" + } + }, + "required": [ + "image" + ] + } + }, + "required": [ + "container" + ] + }, + { + "title": "RunScript", + "description": "Enables the execution of custom scripts or code within a workflow, empowering workflows to perform specialized logic, data processing, or integration tasks by executing user-defined scripts written in various programming languages.", + "properties": { + "script": { + "type": "object", + "title": "Script", + "description": "The configuration of the script to run.", + "unevaluatedProperties": false, + "properties": { + "language": { + "type": "string", + "title": "ScriptLanguage", + "description": "The language of the script to run." + }, + "arguments": { + "type": "object", + "title": "ScriptArguments", + "description": "A key/value mapping of the arguments, if any, to use when running the configured script.", + "additionalProperties": true + }, + "environment": { + "type": "object", + "title": "ScriptEnvironment", + "description": "A key/value mapping of the environment variables, if any, to use when running the configured script process.", + "additionalProperties": true + } + }, + "oneOf": [ + { + "title": "InlineScript", + "type": "object", + "description": "The script's code.", + "properties": { + "code": { + "type": "string", + "title": "InlineScriptCode" + } + }, + "required": [ + "code" + ] + }, + { + "title": "ExternalScript", + "type": "object", + "description": "The script's resource.", + "properties": { + "source": { + "$ref": "#/$defs/externalResource", + "title": "ExternalScriptResource" + } + }, + "required": [ + "source" + ] + } + ], + "required": [ + "language" + ] + } + }, + "required": [ + "script" + ] + }, + { + "title": "RunShell", + "description": "Enables the execution of shell commands within a workflow, enabling workflows to interact with the underlying operating system and perform system-level operations, such as file manipulation, environment configuration, or system administration tasks.", + "properties": { + "shell": { + "type": "object", + "title": "Shell", + "description": "The configuration of the shell command to run.", + "unevaluatedProperties": false, + "properties": { + "command": { + "type": "string", + "title": "ShellCommand", + "description": "The shell command to run." + }, + "arguments": { + "type": "object", + "title": "ShellArguments", + "description": "A list of the arguments of the shell command to run.", + "additionalProperties": true + }, + "environment": { + "type": "object", + "title": "ShellEnvironment", + "description": "A key/value mapping of the environment variables, if any, to use when running the configured process.", + "additionalProperties": true + } + }, + "required": [ + "command" + ] + } + }, + "required": [ + "shell" + ] + }, + { + "title": "RunWorkflow", + "description": "Enables the invocation and execution of nested workflows within a parent workflow, facilitating modularization, reusability, and abstraction of complex logic or business processes by encapsulating them into standalone workflow units.", + "properties": { + "workflow": { + "type": "object", + "title": "SubflowConfiguration", + "description": "The configuration of the workflow to run.", + "unevaluatedProperties": false, + "properties": { + "namespace": { + "type": "string", + "title": "SubflowNamespace", + "description": "The namespace the workflow to run belongs to." + }, + "name": { + "type": "string", + "title": "SubflowName", + "description": "The name of the workflow to run." + }, + "version": { + "type": "string", + "default": "latest", + "title": "SubflowVersion", + "description": "The version of the workflow to run. Defaults to latest." + }, + "input": { + "type": "object", + "title": "SubflowInput", + "description": "The data, if any, to pass as input to the workflow to execute. The value should be validated against the target workflow's input schema, if specified.", + "additionalProperties": true + } + }, + "required": [ + "namespace", + "name", + "version" + ] + } + }, + "required": [ + "workflow" + ] + } + ] + } + } + }, + "setTask": { + "type": "object", + "$ref": "#/$defs/taskBase", + "title": "SetTask", + "description": "A task used to set data.", + "required": [ + "set" + ], + "unevaluatedProperties": false, + "properties": { + "set": { + "type": "object", + "title": "SetTaskConfiguration", + "description": "The data to set.", + "minProperties": 1, + "additionalProperties": true + } + } + }, + "switchTask": { + "type": "object", + "$ref": "#/$defs/taskBase", + "title": "SwitchTask", + "description": "Enables conditional branching within workflows, allowing them to dynamically select different paths based on specified conditions or criteria.", + "required": [ + "switch" + ], + "unevaluatedProperties": false, + "properties": { + "switch": { + "type": "array", + "title": "SwitchTaskConfiguration", + "description": "The definition of the switch to use.", + "minItems": 1, + "items": { + "type": "object", + "title": "SwitchItem", + "minProperties": 1, + "maxProperties": 1, + "additionalProperties": { + "type": "object", + "title": "SwitchCase", + "description": "The definition of a case within a switch task, defining a condition and corresponding tasks to execute if the condition is met.", + "unevaluatedProperties": false, + "required": [ + "then" + ], + "properties": { + "when": { + "type": "string", + "title": "SwitchCaseCondition", + "description": "A runtime expression used to determine whether or not the case matches." + }, + "then": { + "$ref": "#/$defs/flowDirective", + "title": "SwitchCaseOutcome", + "description": "The flow directive to execute when the case matches." + } + } + } + } + } + } + }, + "tryTask": { + "type": "object", + "$ref": "#/$defs/taskBase", + "title": "TryTask", + "description": "Serves as a mechanism within workflows to handle errors gracefully, potentially retrying failed tasks before proceeding with alternate ones.", + "required": [ + "try", + "catch" + ], + "unevaluatedProperties": false, + "properties": { + "try": { + "$ref": "#/$defs/taskList", + "title": "TryTaskConfiguration", + "description": "The task(s) to perform." + }, + "catch": { + "type": "object", + "title": "TryTaskCatch", + "description": "The object used to define the errors to catch.", + "unevaluatedProperties": false, + "properties": { + "errors": { + "type": "object", + "title": "CatchErrors", + "properties": { + "with": { + "$ref": "#/$defs/errorFilter" + } + }, + "description": "static error filter" + }, + "as": { + "type": "string", + "title": "CatchAs", + "description": "The name of the runtime expression variable to save the error as. Defaults to 'error'." + }, + "when": { + "type": "string", + "title": "CatchWhen", + "description": "A runtime expression used to determine whether to catch the filtered error." + }, + "exceptWhen": { + "type": "string", + "title": "CatchExceptWhen", + "description": "A runtime expression used to determine whether not to catch the filtered error." + }, + "retry": { + "oneOf": [ + { + "$ref": "#/$defs/retryPolicy", + "title": "RetryPolicyDefinition", + "description": "The retry policy to use, if any, when catching errors." + }, + { + "type": "string", + "title": "RetryPolicyReference", + "description": "The name of the retry policy to use, if any, when catching errors." + } + ] + }, + "do": { + "$ref": "#/$defs/taskList", + "title": "TryTaskCatchDo", + "description": "The definition of the task(s) to run when catching an error." + } + } + } + } + }, + "waitTask": { + "type": "object", + "$ref": "#/$defs/taskBase", + "title": "WaitTask", + "description": "Allows workflows to pause or delay their execution for a specified period of time.", + "required": [ + "wait" + ], + "unevaluatedProperties": false, + "properties": { + "wait": { + "$ref": "#/$defs/duration", + "title": "WaitTaskConfiguration", + "description": "The amount of time to wait." + } + } + }, + "flowDirective": { + "title": "FlowDirective", + "description": "Represents different transition options for a workflow.", + "anyOf": [ + { + "title": "FlowDirectiveEnum", + "type": "string", + "enum": [ + "continue", + "exit", + "end" + ], + "default": "continue" + }, + { + "type": "string" + } + ] + }, + "referenceableAuthenticationPolicy": { + "type": "object", + "title": "ReferenceableAuthenticationPolicy", + "description": "Represents a referenceable authentication policy.", + "unevaluatedProperties": false, + "oneOf": [ + { + "title": "AuthenticationPolicyReference", + "description": "The reference of the authentication policy to use.", + "properties": { + "use": { + "type": "string", + "minLength": 1, + "title": "ReferenceableAuthenticationPolicyName", + "description": "The name of the authentication policy to use." + } + }, + "required": [ + "use" + ] + }, + { + "$ref": "#/$defs/authenticationPolicy" + } + ] + }, + "secretBasedAuthenticationPolicy": { + "type": "object", + "title": "SecretBasedAuthenticationPolicy", + "description": "Represents an authentication policy based on secrets.", + "unevaluatedProperties": false, + "properties": { + "use": { + "type": "string", + "minLength": 1, + "title": "SecretBasedAuthenticationPolicyName", + "description": "The name of the authentication policy to use." + } + }, + "required": [ + "use" + ] + }, + "authenticationPolicy": { + "type": "object", + "title": "AuthenticationPolicy", + "description": "Defines an authentication policy.", + "oneOf": [ + { + "title": "BasicAuthenticationPolicy", + "description": "Use basic authentication.", + "properties": { + "basic": { + "type": "object", + "title": "BasicAuthenticationPolicyConfiguration", + "description": "The configuration of the basic authentication policy.", + "unevaluatedProperties": false, + "oneOf": [ + { + "title": "BasicAuthenticationProperties", + "description": "Inline configuration of the basic authentication policy.", + "properties": { + "username": { + "type": "string", + "description": "The username to use." + }, + "password": { + "type": "string", + "description": "The password to use." + } + }, + "required": [ + "username", + "password" + ] + }, + { + "$ref": "#/$defs/secretBasedAuthenticationPolicy", + "title": "BasicAuthenticationPolicySecret", + "description": "Secret based configuration of the basic authentication policy." + } + ] + } + }, + "required": [ + "basic" + ] + }, + { + "title": "BearerAuthenticationPolicy", + "description": "Use bearer authentication.", + "properties": { + "bearer": { + "type": "object", + "title": "BearerAuthenticationPolicyConfiguration", + "description": "The configuration of the bearer authentication policy.", + "unevaluatedProperties": false, + "oneOf": [ + { + "title": "BearerAuthenticationProperties", + "description": "Inline configuration of the bearer authentication policy.", + "properties": { + "token": { + "type": "string", + "description": "The bearer token to use." + } + }, + "required": [ + "token" + ] + }, + { + "$ref": "#/$defs/secretBasedAuthenticationPolicy", + "title": "BearerAuthenticationPolicySecret", + "description": "Secret based configuration of the bearer authentication policy." + } + ] + } + }, + "required": [ + "bearer" + ] + }, + { + "title": "DigestAuthenticationPolicy", + "description": "Use digest authentication.", + "properties": { + "digest": { + "type": "object", + "title": "DigestAuthenticationPolicyConfiguration", + "description": "The configuration of the digest authentication policy.", + "unevaluatedProperties": false, + "oneOf": [ + { + "title": "DigestAuthenticationProperties", + "description": "Inline configuration of the digest authentication policy.", + "properties": { + "username": { + "type": "string", + "description": "The username to use." + }, + "password": { + "type": "string", + "description": "The password to use." + } + }, + "required": [ + "username", + "password" + ] + }, + { + "$ref": "#/$defs/secretBasedAuthenticationPolicy", + "title": "DigestAuthenticationPolicySecret", + "description": "Secret based configuration of the digest authentication policy." + } + ] + } + }, + "required": [ + "digest" + ] + }, + { + "title": "OAuth2AuthenticationPolicy", + "description": "Use OAuth2 authentication.", + "properties": { + "oauth2": { + "type": "object", + "title": "OAuth2AuthenticationPolicyConfiguration", + "description": "The configuration of the OAuth2 authentication policy.", + "unevaluatedProperties": false, + "oneOf": [ + { + "type": "object", + "title": "OAuth2ConnectAuthenticationProperties", + "description": "The inline configuration of the OAuth2 authentication policy.", + "unevaluatedProperties": false, + "allOf": [ + { + "$ref": "#/$defs/oauth2AuthenticationProperties" + }, + { + "type": "object", + "properties": { + "endpoints": { + "type": "object", + "title": "OAuth2AuthenticationPropertiesEndpoints", + "description": "The endpoint configurations for OAuth2.", + "properties": { + "token": { + "type": "string", + "format": "uri-template", + "default": "/oauth2/token", + "title": "OAuth2TokenEndpoint", + "description": "The relative path to the token endpoint. Defaults to `/oauth2/token`." + }, + "revocation": { + "type": "string", + "format": "uri-template", + "default": "/oauth2/revoke", + "title": "OAuth2RevocationEndpoint", + "description": "The relative path to the revocation endpoint. Defaults to `/oauth2/revoke`." + }, + "introspection": { + "type": "string", + "format": "uri-template", + "default": "/oauth2/introspect", + "title": "OAuth2IntrospectionEndpoint", + "description": "The relative path to the introspection endpoint. Defaults to `/oauth2/introspect`." + } + } + } + } + } + ] + }, + { + "$ref": "#/$defs/secretBasedAuthenticationPolicy", + "title": "OAuth2AuthenticationPolicySecret", + "description": "Secret based configuration of the OAuth2 authentication policy." + } + ] + } + }, + "required": [ + "oauth2" + ] + }, + { + "title": "OpenIdConnectAuthenticationPolicy", + "description": "Use OpenIdConnect authentication.", + "properties": { + "oidc": { + "type": "object", + "title": "OpenIdConnectAuthenticationPolicyConfiguration", + "description": "The configuration of the OpenIdConnect authentication policy.", + "unevaluatedProperties": false, + "oneOf": [ + { + "$ref": "#/$defs/oauth2AuthenticationProperties", + "title": "OpenIdConnectAuthenticationProperties", + "description": "The inline configuration of the OpenIdConnect authentication policy.", + "unevaluatedProperties": false + }, + { + "$ref": "#/$defs/secretBasedAuthenticationPolicy", + "title": "OpenIdConnectAuthenticationPolicySecret", + "description": "Secret based configuration of the OpenIdConnect authentication policy." + } + ] + } + }, + "required": [ + "oidc" + ] + } + ] + }, + "oauth2AuthenticationProperties": { + "type": "object", + "title": "OAuth2AutenthicationData", + "description": "Inline configuration of the OAuth2 authentication policy.", + "properties": { + "authority": { + "$ref": "#/$defs/uriTemplate", + "title": "OAuth2AutenthicationDataAuthority", + "description": "The URI that references the OAuth2 authority to use." + }, + "grant": { + "type": "string", + "enum": [ + "authorization_code", + "client_credentials", + "password", + "refresh_token", + "urn:ietf:params:oauth:grant-type:token-exchange" + ], + "title": "OAuth2AutenthicationDataGrant", + "description": "The grant type to use." + }, + "client": { + "type": "object", + "title": "OAuth2AutenthicationDataClient", + "description": "The definition of an OAuth2 client.", + "unevaluatedProperties": false, + "properties": { + "id": { + "type": "string", + "title": "ClientId", + "description": "The client id to use." + }, + "secret": { + "type": "string", + "title": "ClientSecret", + "description": "The client secret to use, if any." + }, + "assertion": { + "type": "string", + "title": "ClientAssertion", + "description": "A JWT containing a signed assertion with your application credentials." + }, + "authentication": { + "type": "string", + "enum": [ + "client_secret_basic", + "client_secret_post", + "client_secret_jwt", + "private_key_jwt", + "none" + ], + "default": "client_secret_post", + "title": "ClientAuthentication", + "description": "The authentication method to use to authenticate the client." + } + } + }, + "request": { + "type": "object", + "title": "OAuth2TokenRequest", + "description": "The configuration of an OAuth2 token request", + "properties": { + "encoding": { + "type": "string", + "enum": [ + "application/x-www-form-urlencoded", + "application/json" + ], + "default": "application/x-www-form-urlencoded", + "title": "Oauth2TokenRequestEncoding" + } + } + }, + "issuers": { + "type": "array", + "title": "OAuth2Issuers", + "description": "A list that contains that contains valid issuers that will be used to check against the issuer of generated tokens.", + "items": { + "type": "string" + } + }, + "scopes": { + "type": "array", + "title": "OAuth2AutenthicationDataScopes", + "description": "The scopes, if any, to request the token for.", + "items": { + "type": "string" + } + }, + "audiences": { + "type": "array", + "title": "OAuth2AutenthicationDataAudiences", + "description": "The audiences, if any, to request the token for.", + "items": { + "type": "string" + } + }, + "username": { + "type": "string", + "title": "OAuth2AutenthicationDataUsername", + "description": "The username to use. Used only if the grant type is Password." + }, + "password": { + "type": "string", + "title": "OAuth2AutenthicationDataPassword", + "description": "The password to use. Used only if the grant type is Password." + }, + "subject": { + "$ref": "#/$defs/oauth2Token", + "title": "OAuth2AutenthicationDataSubject", + "description": "The security token that represents the identity of the party on behalf of whom the request is being made." + }, + "actor": { + "$ref": "#/$defs/oauth2Token", + "title": "OAuth2AutenthicationDataActor", + "description": "The security token that represents the identity of the acting party." + } + } + }, + "oauth2Token": { + "type": "object", + "title": "OAuth2TokenDefinition", + "description": "Represents an OAuth2 token.", + "unevaluatedProperties": false, + "properties": { + "token": { + "type": "string", + "title": "OAuth2Token", + "description": "The security token to use." + }, + "type": { + "type": "string", + "title": "OAuth2TokenType", + "description": "The type of the security token to use." + } + }, + "required": [ + "token", + "type" + ] + }, + "duration": { + "oneOf": [ + { + "type": "object", + "minProperties": 1, + "unevaluatedProperties": false, + "properties": { + "days": { + "type": "integer", + "title": "DurationDays", + "description": "Number of days, if any." + }, + "hours": { + "type": "integer", + "title": "DurationHours", + "description": "Number of days, if any." + }, + "minutes": { + "type": "integer", + "title": "DurationMinutes", + "description": "Number of minutes, if any." + }, + "seconds": { + "type": "integer", + "title": "DurationSeconds", + "description": "Number of seconds, if any." + }, + "milliseconds": { + "type": "integer", + "title": "DurationMilliseconds", + "description": "Number of milliseconds, if any." + } + }, + "title": "DurationInline", + "description": "The inline definition of a duration." + }, + { + "type": "string", + "pattern": "^P(?!$)(\\d+(?:\\.\\d+)?Y)?(\\d+(?:\\.\\d+)?M)?(\\d+(?:\\.\\d+)?W)?(\\d+(?:\\.\\d+)?D)?(T(?=\\d)(\\d+(?:\\.\\d+)?H)?(\\d+(?:\\.\\d+)?M)?(\\d+(?:\\.\\d+)?S)?)?$", + "title": "DurationExpression", + "description": "The ISO 8601 expression of a duration." + } + ] + }, + "error": { + "type": "object", + "title": "Error", + "description": "Represents an error.", + "unevaluatedProperties": false, + "properties": { + "type": { + "title": "ErrorType", + "description": "A URI reference that identifies the error type.", + "oneOf": [ + { + "title": "LiteralErrorType", + "$ref": "#/$defs/uriTemplate", + "description": "The literal error type." + }, + { + "title": "ExpressionErrorType", + "$ref": "#/$defs/runtimeExpression", + "description": "An expression based error type." + } + ] + }, + "status": { + "type": "integer", + "title": "ErrorStatus", + "description": "The status code generated by the origin for this occurrence of the error." + }, + "instance": { + "title": "ErrorInstance", + "description": "A JSON Pointer used to reference the component the error originates from.", + "oneOf": [ + { + "title": "LiteralErrorInstance", + "description": "The literal error instance.", + "type": "string", + "format": "json-pointer" + }, + { + "$ref": "#/$defs/runtimeExpression", + "title": "ExpressionErrorInstance", + "description": "An expression based error instance." + } + ] + }, + "title": { + "type": "string", + "title": "ErrorTitle", + "description": "A short, human-readable summary of the error." + }, + "detail": { + "type": "string", + "title": "ErrorDetails", + "description": "A human-readable explanation specific to this occurrence of the error." + } + }, + "required": [ + "type", + "status" + ] + }, + "errorFilter": { + "type": "object", + "title": "ErrorFilter", + "description": "Error filtering base on static values. For error filtering on dynamic values, use catch.when property", + "minProperties": 1, + "properties": { + "type": { + "type": "string", + "description": "if present, means this value should be used for filtering" + }, + "status": { + "type": "integer", + "description": "if present, means this value should be used for filtering" + }, + "instance": { + "type": "string", + "description": "if present, means this value should be used for filtering" + }, + "title": { + "type": "string", + "description": "if present, means this value should be used for filtering" + }, + "details": { + "type": "string", + "description": "if present, means this value should be used for filtering" + } + } + }, + "uriTemplate": { + "title": "UriTemplate", + "anyOf": [ + { + "title": "LiteralUriTemplate", + "type": "string", + "format": "uri-template", + "pattern": "^[A-Za-z][A-Za-z0-9+\\-.]*://.*" + }, + { + "title": "LiteralUri", + "type": "string", + "format": "uri", + "pattern": "^[A-Za-z][A-Za-z0-9+\\-.]*://.*" + } + ] + }, + "endpoint": { + "title": "Endpoint", + "description": "Represents an endpoint.", + "oneOf": [ + { + "$ref": "#/$defs/runtimeExpression" + }, + { + "$ref": "#/$defs/uriTemplate" + }, + { + "title": "EndpointConfiguration", + "type": "object", + "unevaluatedProperties": false, + "properties": { + "uri": { + "title": "EndpointUri", + "description": "The endpoint's URI.", + "oneOf": [ + { + "title": "LiteralEndpointURI", + "description": "The literal endpoint's URI.", + "$ref": "#/$defs/uriTemplate" + }, + { + "title": "ExpressionEndpointURI", + "$ref": "#/$defs/runtimeExpression", + "description": "An expression based endpoint's URI." + } + ] + }, + "authentication": { + "$ref": "#/$defs/referenceableAuthenticationPolicy", + "title": "EndpointAuthentication", + "description": "The authentication policy to use." + } + }, + "required": [ + "uri" + ] + } + ] + }, + "eventProperties": { + "type": "object", + "title": "EventProperties", + "description": "Describes the properties of an event.", + "properties": { + "id": { + "type": "string", + "title": "EventId", + "description": "The event's unique identifier." + }, + "source": { + "title": "EventSource", + "description": "Identifies the context in which an event happened.", + "oneOf": [ + { + "$ref": "#/$defs/uriTemplate" + }, + { + "$ref": "#/$defs/runtimeExpression" + } + ] + }, + "type": { + "type": "string", + "title": "EventType", + "description": "This attribute contains a value describing the type of event related to the originating occurrence." + }, + "time": { + "title": "EventTime", + "description": "When the event occured.", + "oneOf": [ + { + "title": "LiteralTime", + "type": "string", + "format": "date-time" + }, + { + "$ref": "#/$defs/runtimeExpression" + } + ] + }, + "subject": { + "type": "string", + "title": "EventSubject", + "description": "The subject of the event." + }, + "datacontenttype": { + "type": "string", + "title": "EventDataContentType", + "description": "Content type of data value. This attribute enables data to carry any type of content, whereby format and encoding might differ from that of the chosen event format." + }, + "dataschema": { + "title": "EventDataschema", + "description": "The schema describing the event format.", + "oneOf": [ + { + "title": "LiteralDataSchema", + "$ref": "#/$defs/uriTemplate", + "description": "The literal event data schema." + }, + { + "title": "ExpressionDataSchema", + "$ref": "#/$defs/runtimeExpression", + "description": "An expression based event data schema." + } + ] + }, + "data": { + "title": "EventData", + "description": "The event's payload data", + "anyOf": [ + { + "$ref": "#/$defs/runtimeExpression" + }, + {} + ] + } + }, + "additionalProperties": true + }, + "eventConsumptionStrategy": { + "type": "object", + "title": "EventConsumptionStrategy", + "description": "Describe the event consumption strategy to adopt.", + "unevaluatedProperties": false, + "oneOf": [ + { + "title": "AllEventConsumptionStrategy", + "properties": { + "all": { + "type": "array", + "title": "AllEventConsumptionStrategyConfiguration", + "description": "A list containing all the events that must be consumed.", + "items": { + "$ref": "#/$defs/eventFilter" + } + } + }, + "required": [ + "all" + ] + }, + { + "title": "AnyEventConsumptionStrategy", + "properties": { + "any": { + "type": "array", + "title": "AnyEventConsumptionStrategyConfiguration", + "description": "A list containing any of the events to consume.", + "items": { + "$ref": "#/$defs/eventFilter" + } + }, + "until": { + "oneOf": [ + { + "type": "string", + "title": "AnyEventUntilCondition", + "description": "A runtime expression condition evaluated after consuming an event and which determines whether or not to continue listening." + }, + { + "allOf": [ + { + "$ref": "#/$defs/eventConsumptionStrategy", + "description": "The strategy that defines the event(s) to consume to stop listening." + }, + { + "properties": { + "until": false + } + } + ], + "title": "AnyEventUntilConsumed" + } + ] + } + }, + "required": [ + "any" + ] + }, + { + "title": "OneEventConsumptionStrategy", + "properties": { + "one": { + "$ref": "#/$defs/eventFilter", + "title": "OneEventConsumptionStrategyConfiguration", + "description": "The single event to consume." + } + }, + "required": [ + "one" + ] + } + ] + }, + "eventFilter": { + "type": "object", + "title": "EventFilter", + "description": "An event filter is a mechanism used to selectively process or handle events based on predefined criteria, such as event type, source, or specific attributes.", + "unevaluatedProperties": false, + "properties": { + "with": { + "$ref": "#/$defs/eventProperties", + "minProperties": 1, + "title": "WithEvent", + "description": "An event filter is a mechanism used to selectively process or handle events based on predefined criteria, such as event type, source, or specific attributes." + }, + "correlate": { + "type": "object", + "title": "EventFilterCorrelate", + "description": "A correlation is a link between events and data, established by mapping event attributes to specific data attributes, allowing for coordinated processing or handling based on event characteristics.", + "additionalProperties": { + "type": "object", + "properties": { + "from": { + "type": "string", + "title": "CorrelateFrom", + "description": "A runtime expression used to extract the correlation value from the filtered event." + }, + "expect": { + "type": "string", + "title": "CorrelateExpect", + "description": "A constant or a runtime expression, if any, used to determine whether or not the extracted correlation value matches expectations. If not set, the first extracted value will be used as the correlation's expectation." + } + }, + "required": [ + "from" + ] + } + } + }, + "required": [ + "with" + ] + }, + "extension": { + "type": "object", + "title": "Extension", + "description": "The definition of an extension.", + "unevaluatedProperties": false, + "properties": { + "extend": { + "type": "string", + "enum": [ + "call", + "composite", + "emit", + "for", + "listen", + "raise", + "run", + "set", + "switch", + "try", + "wait", + "all" + ], + "title": "ExtensionTarget", + "description": "The type of task to extend." + }, + "when": { + "type": "string", + "title": "ExtensionCondition", + "description": "A runtime expression, if any, used to determine whether or not the extension should apply in the specified context." + }, + "before": { + "$ref": "#/$defs/taskList", + "title": "ExtensionDoBefore", + "description": "The task(s) to execute before the extended task, if any." + }, + "after": { + "$ref": "#/$defs/taskList", + "title": "ExtensionDoAfter", + "description": "The task(s) to execute after the extended task, if any." + } + }, + "required": [ + "extend" + ] + }, + "externalResource": { + "type": "object", + "title": "ExternalResource", + "description": "Represents an external resource.", + "unevaluatedProperties": false, + "properties": { + "name": { + "type": "string", + "title": "ExternalResourceName", + "description": "The name of the external resource, if any." + }, + "endpoint": { + "$ref": "#/$defs/endpoint", + "title": "ExternalResourceEndpoint", + "description": "The endpoint of the external resource." + } + }, + "required": [ + "endpoint" + ] + }, + "input": { + "type": "object", + "title": "Input", + "description": "Configures the input of a workflow or task.", + "unevaluatedProperties": false, + "properties": { + "schema": { + "$ref": "#/$defs/schema", + "title": "InputSchema", + "description": "The schema used to describe and validate the input of the workflow or task." + }, + "from": { + "title": "InputFrom", + "description": "A runtime expression, if any, used to mutate and/or filter the input of the workflow or task.", + "oneOf": [ + { + "type": "string" + }, + { + "type": "object" + } + ] + } + } + }, + "output": { + "type": "object", + "title": "Output", + "description": "Configures the output of a workflow or task.", + "unevaluatedProperties": false, + "properties": { + "schema": { + "$ref": "#/$defs/schema", + "title": "OutputSchema", + "description": "The schema used to describe and validate the output of the workflow or task." + }, + "as": { + "title": "OutputAs", + "description": "A runtime expression, if any, used to mutate and/or filter the output of the workflow or task.", + "oneOf": [ + { + "type": "string" + }, + { + "type": "object" + } + ] + } + } + }, + "export": { + "type": "object", + "title": "Export", + "description": "Set the content of the context. .", + "unevaluatedProperties": false, + "properties": { + "schema": { + "$ref": "#/$defs/schema", + "title": "ExportSchema", + "description": "The schema used to describe and validate the workflow context." + }, + "as": { + "title": "ExportAs", + "description": "A runtime expression, if any, used to export the output data to the context.", + "oneOf": [ + { + "type": "string" + }, + { + "type": "object" + } + ] + } + } + }, + "retryPolicy": { + "type": "object", + "title": "RetryPolicy", + "description": "Defines a retry policy.", + "unevaluatedProperties": false, + "properties": { + "when": { + "type": "string", + "title": "RetryWhen", + "description": "A runtime expression, if any, used to determine whether or not to retry running the task, in a given context." + }, + "exceptWhen": { + "type": "string", + "title": "RetryExcepWhen", + "description": "A runtime expression used to determine whether or not to retry running the task, in a given context." + }, + "delay": { + "$ref": "#/$defs/duration", + "title": "RetryDelay", + "description": "The duration to wait between retry attempts." + }, + "backoff": { + "type": "object", + "title": "RetryBackoff", + "description": "The retry duration backoff.", + "unevaluatedProperties": false, + "oneOf": [ + { + "title": "ConstantBackoff", + "properties": { + "constant": { + "type": "object", + "description": "The definition of the constant backoff to use, if any." + } + }, + "required": [ + "constant" + ] + }, + { + "title": "ExponentialBackOff", + "properties": { + "exponential": { + "type": "object", + "description": "The definition of the exponential backoff to use, if any." + } + }, + "required": [ + "exponential" + ] + }, + { + "title": "LinearBackoff", + "properties": { + "linear": { + "type": "object", + "description": "The definition of the linear backoff to use, if any." + } + }, + "required": [ + "linear" + ] + } + ] + }, + "limit": { + "type": "object", + "title": "RetryLimit", + "unevaluatedProperties": false, + "properties": { + "attempt": { + "type": "object", + "title": "RetryLimitAttempt", + "unevaluatedProperties": false, + "properties": { + "count": { + "type": "integer", + "title": "RetryLimitAttemptCount", + "description": "The maximum amount of retry attempts, if any." + }, + "duration": { + "$ref": "#/$defs/duration", + "title": "RetryLimitAttemptDuration", + "description": "The maximum duration for each retry attempt." + } + } + }, + "duration": { + "$ref": "#/$defs/duration", + "title": "RetryLimitDuration", + "description": "The duration limit, if any, for all retry attempts." + } + }, + "description": "The retry limit, if any." + }, + "jitter": { + "type": "object", + "title": "RetryPolicyJitter", + "description": "The parameters, if any, that control the randomness or variability of the delay between retry attempts.", + "unevaluatedProperties": false, + "properties": { + "from": { + "$ref": "#/$defs/duration", + "title": "RetryPolicyJitterFrom", + "description": "The minimum duration of the jitter range." + }, + "to": { + "$ref": "#/$defs/duration", + "title": "RetryPolicyJitterTo", + "description": "The maximum duration of the jitter range." + } + }, + "required": [ + "from", + "to" + ] + } + } + }, + "schema": { + "type": "object", + "title": "Schema", + "description": "Represents the definition of a schema.", + "unevaluatedProperties": false, + "properties": { + "format": { + "type": "string", + "default": "json", + "title": "SchemaFormat", + "description": "The schema's format. Defaults to 'json'. The (optional) version of the format can be set using `{format}:{version}`." + } + }, + "oneOf": [ + { + "title": "SchemaInline", + "properties": { + "document": { + "description": "The schema's inline definition." + } + }, + "required": [ + "document" + ] + }, + { + "title": "SchemaExternal", + "properties": { + "resource": { + "$ref": "#/$defs/externalResource", + "title": "SchemaExternalResource", + "description": "The schema's external resource." + } + }, + "required": [ + "resource" + ] + } + ] + }, + "timeout": { + "type": "object", + "title": "Timeout", + "description": "The definition of a timeout.", + "unevaluatedProperties": false, + "properties": { + "after": { + "$ref": "#/$defs/duration", + "title": "TimeoutAfter", + "description": "The duration after which to timeout." + } + }, + "required": [ + "after" + ] + }, + "catalog": { + "type": "object", + "title": "Catalog", + "description": "The definition of a resource catalog.", + "unevaluatedProperties": false, + "properties": { + "endpoint": { + "$ref": "#/$defs/endpoint", + "title": "CatalogEndpoint", + "description": "The root URL where the catalog is hosted." + } + }, + "required": [ + "endpoint" + ] + }, + "runtimeExpression": { + "type": "string", + "title": "RuntimeExpression", + "description": "A runtime expression.", + "pattern": "^\\s*\\$\\{.+\\}\\s*$" + }, + "containerLifetime": { + "type": "object", + "title": "ContainerLifetime", + "description": "The configuration of a container's lifetime", + "unevaluatedProperties": false, + "properties": { + "cleanup": { + "type": "string", + "title": "ContainerCleanupPolicy", + "description": "The container cleanup policy to use", + "enum": [ + "always", + "never", + "eventually" + ], + "default": "never" + }, + "after": { + "$ref": "#/$defs/duration", + "title": "ContainerLifetimeDuration", + "description": "The duration after which to cleanup the container, in case the cleanup policy has been set to 'eventually'" + } + }, + "required": [ + "cleanup" + ], + "if": { + "properties": { + "cleanup": { + "const": "eventually" + } + } + }, + "then": { + "required": [ + "after" + ] + }, + "else": { + "not": { + "required": [ + "after" + ] + } + } + }, + "processResult": { + "type": "object", + "title": "ProcessResult", + "description": "The object returned by a run task when its return type has been set 'all'.", + "unevaluatedProperties": false, + "properties": { + "code": { + "type": "integer", + "title": "ProcessExitCode", + "description": "The process's exit code." + }, + "stdout": { + "type": "string", + "title": "ProcessStandardOutput", + "description": "The content of the process's STDOUT." + }, + "stderr": { + "type": "string", + "title": "ProcessStandardError", + "description": "The content of the process's STDERR." + } + }, + "required": [ + "code", + "stdout", + "stderr" + ] + }, + "asyncApiServer": { + "type": "object", + "title": "AsyncApiServer", + "description": "Configures the target server of an AsyncAPI operation.", + "unevaluatedProperties": false, + "properties": { + "name": { + "type": "string", + "title": "AsyncApiServerName", + "description": "The target server's name." + }, + "variables": { + "type": "object", + "title": "AsyncApiServerVariables", + "description": "The target server's variables, if any." + } + }, + "required": [ + "name" + ] + }, + "asyncApiOutboundMessage": { + "type": "object", + "title": "AsyncApiOutboundMessage", + "description": "An object used to configure the message to publish using the target operation.", + "unevaluatedProperties": false, + "properties": { + "payload": { + "type": "object", + "title": "AsyncApiMessagePayload", + "description": "The message's payload, if any.", + "additionalProperties": true + }, + "headers": { + "type": "object", + "title": "AsyncApiMessageHeaders", + "description": "The message's headers, if any.", + "additionalProperties": true + } + } + }, + "asyncApiInboundMessage": { + "type": "object", + "title": "AsyncApiInboundMessage", + "description": "Represents a message counsumed by an AsyncAPI subscription.", + "allOf": [ + { + "$ref": "#/$defs/asyncApiOutboundMessage" + } + ], + "properties": { + "correlationId": { + "type": "string", + "title": "AsyncApiMessageCorrelationId", + "description": "The message's correlation id, if any." + } + } + }, + "asyncApiSubscription": { + "type": "object", + "title": "AsyncApiSubscription", + "description": "An object used to configure the subscription to messages consumed using the target operation.", + "unevaluatedProperties": false, + "properties": { + "filter": { + "$ref": "#/$defs/runtimeExpression", + "title": "AsyncApiSubscriptionCorrelation", + "description": "A runtime expression, if any, used to filter consumed messages." + }, + "consume": { + "$ref": "#/$defs/asyncApiMessageConsumptionPolicy", + "title": "AsyncApiMessageConsumptionPolicy", + "description": "An object used to configure the subscription's message consumption policy." + }, + "foreach": { + "$ref": "#/$defs/subscriptionIterator", + "title": "AsyncApiSubscriptionIterator", + "description": "Configures the iterator, if any, for processing consumed messages(s)." + } + }, + "required": [ + "consume" + ] + }, + "asyncApiMessageConsumptionPolicy": { + "type": "object", + "title": "AsyncApiMessageConsumptionPolicy", + "description": "An object used to configure a subscription's message consumption policy.", + "unevaluatedProperties": false, + "properties": { + "for": { + "$ref": "#/$defs/duration", + "title": "AsyncApiMessageConsumptionPolicyFor", + "description": "Specifies the time period over which messages will be consumed." + } + }, + "oneOf": [ + { + "properties": { + "amount": { + "type": "integer", + "description": "The amount of (filtered) messages to consume before disposing of the subscription." + } + }, + "title": "AsyncApiMessageConsumptionPolicyAmount", + "required": [ + "amount" + ] + }, + { + "properties": { + "while": { + "$ref": "#/$defs/runtimeExpression", + "description": "A runtime expression evaluated after each consumed (filtered) message to decide if message consumption should continue." + } + }, + "title": "AsyncApiMessageConsumptionPolicyWhile", + "required": [ + "while" + ] + }, + { + "properties": { + "until": { + "$ref": "#/$defs/runtimeExpression", + "description": "A runtime expression evaluated before each consumed (filtered) message to decide if message consumption should continue." + } + }, + "title": "AsyncApiMessageConsumptionPolicyUntil", + "required": [ + "until" + ] + } + ] + }, + "subscriptionIterator": { + "type": "object", + "title": "SubscriptionIterator", + "description": "Configures the iteration over each item (event or message) consumed by a subscription.", + "unevaluatedProperties": false, + "properties": { + "item": { + "type": "string", + "title": "SubscriptionIteratorItem", + "description": "The name of the variable used to store the current item being enumerated.", + "default": "item" + }, + "at": { + "type": "string", + "title": "SubscriptionIteratorIndex", + "description": "The name of the variable used to store the index of the current item being enumerated.", + "default": "index" + }, + "do": { + "$ref": "#/$defs/taskList", + "title": "SubscriptionIteratorTasks", + "description": "The tasks to perform for each consumed item." + }, + "output": { + "$ref": "#/$defs/output", + "title": "SubscriptionIteratorOutput", + "description": "An object, if any, used to customize the item's output and to document its schema." + }, + "export": { + "$ref": "#/$defs/export", + "title": "SubscriptionIteratorExport", + "description": "An object, if any, used to customize the content of the workflow context." + } + } + } + } +} \ No newline at end of file diff --git a/public/schemas/1.0.0/workflow.yaml b/public/schemas/1.0.0/workflow.yaml new file mode 100644 index 0000000..e1cd758 --- /dev/null +++ b/public/schemas/1.0.0/workflow.yaml @@ -0,0 +1,1758 @@ +$id: https://serverlessworkflow.io/schemas/1.0.0/workflow.yaml +$schema: https://json-schema.org/draft/2020-12/schema +description: Serverless Workflow DSL - Workflow Schema. +type: object +required: [ document, do ] +properties: + document: + type: object + title: Document + description: Documents the workflow. + unevaluatedProperties: false + properties: + dsl: + type: string + pattern: ^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$ + title: WorkflowDSL + description: The version of the DSL used by the workflow. + namespace: + type: string + pattern: ^[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?$ + title: WorkflowNamespace + description: The workflow's namespace. + name: + type: string + pattern: ^[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?$ + title: WorkflowName + description: The workflow's name. + version: + type: string + pattern: ^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$ + title: WorkflowVersion + description: The workflow's semantic version. + title: + type: string + title: WorkflowTitle + description: The workflow's title. + summary: + type: string + title: WorkflowSummary + description: The workflow's Markdown summary. + tags: + type: object + title: WorkflowTags + description: A key/value mapping of the workflow's tags, if any. + additionalProperties: true + metadata: + type: object + title: WorkflowMetadata + description: Holds additional information about the workflow. + additionalProperties: true + required: [ dsl, namespace, name, version ] + input: + $ref: '#/$defs/input' + title: Input + description: Configures the workflow's input. + use: + type: object + title: Use + description: Defines the workflow's reusable components. + unevaluatedProperties: false + properties: + authentications: + type: object + title: UseAuthentications + description: The workflow's reusable authentication policies. + additionalProperties: + $ref: '#/$defs/authenticationPolicy' + errors: + type: object + title: UseErrors + description: The workflow's reusable errors. + additionalProperties: + $ref: '#/$defs/error' + extensions: + type: array + title: UseExtensions + description: The workflow's extensions. + items: + type: object + title: ExtensionItem + minProperties: 1 + maxProperties: 1 + additionalProperties: + $ref: '#/$defs/extension' + functions: + type: object + title: UseFunctions + description: The workflow's reusable functions. + additionalProperties: + $ref: '#/$defs/task' + retries: + type: object + title: UseRetries + description: The workflow's reusable retry policies. + additionalProperties: + $ref: '#/$defs/retryPolicy' + secrets: + type: array + title: UseSecrets + description: The workflow's reusable secrets. + items: + type: string + description: The workflow's secrets. + timeouts: + type: object + title: UseTimeouts + description: The workflow's reusable timeouts. + additionalProperties: + $ref: '#/$defs/timeout' + catalogs: + type: object + title: UseCatalogs + description: The workflow's reusable catalogs. + additionalProperties: + $ref: '#/$defs/catalog' + do: + $ref: '#/$defs/taskList' + title: Do + description: Defines the task(s) the workflow must perform. + timeout: + title: DoTimeout + oneOf: + - $ref: '#/$defs/timeout' + title: TimeoutDefinition + description: The workflow's timeout configuration, if any. + - type: string + title: TimeoutReference + description: The name of the workflow's timeout, if any. + output: + $ref: '#/$defs/output' + title: Output + description: Configures the workflow's output. + schedule: + type: object + title: Schedule + description: Schedules the workflow. + unevaluatedProperties: false + properties: + every: + $ref: '#/$defs/duration' + title: ScheduleEvery + description: Specifies the duration of the interval at which the workflow should be executed. + cron: + type: string + title: ScheduleCron + description: Specifies the schedule using a cron expression, e.g., '0 0 * * *' for daily at midnight. + after: + $ref: '#/$defs/duration' + title: ScheduleAfter + description: Specifies a delay duration that the workflow must wait before starting again after it completes. + on: + $ref: '#/$defs/eventConsumptionStrategy' + title: ScheduleOn + description: Specifies the events that trigger the workflow execution. +$defs: + taskList: + title: TaskList + description: List of named tasks to perform. + type: array + items: + type: object + title: TaskItem + minProperties: 1 + maxProperties: 1 + additionalProperties: + $ref: '#/$defs/task' + taskBase: + type: object + title: TaskBase + description: An object inherited by all tasks. + properties: + if: + type: string + title: TaskBaseIf + description: A runtime expression, if any, used to determine whether or not the task should be run. + input: + $ref: '#/$defs/input' + title: TaskBaseInput + description: Configure the task's input. + output: + $ref: '#/$defs/output' + title: TaskBaseOutput + description: Configure the task's output. + export: + $ref: '#/$defs/export' + title: TaskBaseExport + description: Export task output to context. + timeout: + title: TaskTimeout + oneOf: + - $ref: '#/$defs/timeout' + title: TaskTimeoutDefinition + description: The task's timeout configuration, if any. + - type: string + title: TaskTimeoutReference + description: The name of the task's timeout, if any. + then: + $ref: '#/$defs/flowDirective' + title: TaskBaseThen + description: The flow directive to be performed upon completion of the task. + metadata: + type: object + title: TaskMetadata + description: Holds additional information about the task. + additionalProperties: true + task: + title: Task + description: A discrete unit of work that contributes to achieving the overall objectives defined by the workflow. + unevaluatedProperties: false + oneOf: + - $ref: '#/$defs/callTask' + - $ref: '#/$defs/doTask' + - $ref: '#/$defs/forkTask' + - $ref: '#/$defs/emitTask' + - $ref: '#/$defs/forTask' + - $ref: '#/$defs/listenTask' + - $ref: '#/$defs/raiseTask' + - $ref: '#/$defs/runTask' + - $ref: '#/$defs/setTask' + - $ref: '#/$defs/switchTask' + - $ref: '#/$defs/tryTask' + - $ref: '#/$defs/waitTask' + callTask: + title: CallTask + description: Defines the call to perform. + oneOf: + - title: CallAsyncAPI + description: Defines the AsyncAPI call to perform. + $ref: '#/$defs/taskBase' + type: object + required: [ call, with ] + unevaluatedProperties: false + properties: + call: + type: string + const: asyncapi + with: + type: object + title: AsyncApiArguments + description: The Async API call arguments. + properties: + document: + $ref: '#/$defs/externalResource' + title: AsyncAPIDocument + description: The document that defines the AsyncAPI operation to call. + channel: + type: string + title: With + description: The name of the channel on which to perform the operation. Used only in case the referenced document uses AsyncAPI v2.6.0. + operation: + type: string + title: AsyncAPIOperation + description: A reference to the AsyncAPI operation to call. + server: + $ref: '#/$defs/asyncApiServer' + title: AsyncAPIServer + description: An object used to configure to the server to call the specified AsyncAPI operation on. + protocol: + type: string + title: AsyncApiProtocol + description: The protocol to use to select the target server. + enum: [ amqp, amqp1, anypointmq, googlepubsub, http, ibmmq, jms, kafka, mercure, mqtt, mqtt5, nats, pulsar, redis, sns, solace, sqs, stomp, ws ] + message: + $ref: '#/$defs/asyncApiOutboundMessage' + title: AsyncApiMessage + description: An object used to configure the message to publish using the target operation. + subscription: + $ref: '#/$defs/asyncApiSubscription' + title: AsyncApiSubscription + description: An object used to configure the subscription to messages consumed using the target operation. + authentication: + $ref: '#/$defs/referenceableAuthenticationPolicy' + title: AsyncAPIAuthentication + description: The authentication policy, if any, to use when calling the AsyncAPI operation. + oneOf: + - required: [ document, operation, message ] + - required: [ document, operation, subscription ] + - required: [ document, channel, message ] + - required: [ document, channel, subscription ] + unevaluatedProperties: false + - title: CallGRPC + description: Defines the GRPC call to perform. + $ref: '#/$defs/taskBase' + type: object + unevaluatedProperties: false + required: [ call, with ] + properties: + call: + type: string + const: grpc + with: + type: object + title: GRPCArguments + description: The GRPC call arguments. + properties: + proto: + $ref: '#/$defs/externalResource' + title: WithGRPCProto + description: The proto resource that describes the GRPC service to call. + service: + type: object + title: WithGRPCService + unevaluatedProperties: false + properties: + name: + type: string + title: WithGRPCServiceName + description: The name of the GRPC service to call. + host: + type: string + title: WithGRPCServiceHost + description: The hostname of the GRPC service to call. + pattern: ^[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?$ + port: + type: integer + title: WithGRPCServicePost + description: The port number of the GRPC service to call. + minimum: 0 + maximum: 65535 + authentication: + $ref: '#/$defs/referenceableAuthenticationPolicy' + title: WithGRPCServiceAuthentication + description: The endpoint's authentication policy, if any. + required: [ name, host ] + method: + type: string + title: WithGRPCMethod + description: The name of the method to call on the defined GRPC service. + arguments: + type: object + title: WithGRPCArguments + description: The arguments, if any, to call the method with. + additionalProperties: true + required: [ proto, service, method ] + unevaluatedProperties: false + - title: CallHTTP + description: Defines the HTTP call to perform. + $ref: '#/$defs/taskBase' + type: object + unevaluatedProperties: false + required: [ call, with ] + properties: + call: + type: string + const: http + with: + type: object + title: HTTPArguments + description: The HTTP call arguments. + properties: + method: + type: string + title: HTTPMethod + description: The HTTP method of the HTTP request to perform. + endpoint: + title: HTTPEndpoint + description: The HTTP endpoint to send the request to. + $ref: '#/$defs/endpoint' + headers: + type: object + title: HTTPHeaders + description: A name/value mapping of the headers, if any, of the HTTP request to perform. + body: + title: HTTPBody + description: The body, if any, of the HTTP request to perform. + query: + type: object + title: HTTPQuery + description: A name/value mapping of the query parameters, if any, of the HTTP request to perform. + additionalProperties: true + output: + type: string + title: HTTPOutput + description: The http call output format. Defaults to 'content'. + enum: [ raw, content, response ] + redirect: + type: boolean + title: HttpRedirect + description: Specifies whether redirection status codes (`300–399`) should be treated as errors. + required: [ method, endpoint ] + unevaluatedProperties: false + - title: CallOpenAPI + description: Defines the OpenAPI call to perform. + $ref: '#/$defs/taskBase' + type: object + unevaluatedProperties: false + required: [ call, with ] + properties: + call: + type: string + const: openapi + with: + type: object + title: OpenAPIArguments + description: The OpenAPI call arguments. + properties: + document: + $ref: '#/$defs/externalResource' + title: WithOpenAPIDocument + description: The document that defines the OpenAPI operation to call. + operationId: + type: string + title: WithOpenAPIOperation + description: The id of the OpenAPI operation to call. + parameters: + type: object + title: WithOpenAPIParameters + description: A name/value mapping of the parameters of the OpenAPI operation to call. + additionalProperties: true + authentication: + $ref: '#/$defs/referenceableAuthenticationPolicy' + title: WithOpenAPIAuthentication + description: The authentication policy, if any, to use when calling the OpenAPI operation. + output: + type: string + enum: [ raw, content, response ] + title: WithOpenAPIOutput + description: The http call output format. Defaults to 'content'. + redirect: + type: boolean + title: HttpRedirect + description: Specifies whether redirection status codes (`300–399`) should be treated as errors. + required: [ document, operationId ] + unevaluatedProperties: false + - title: CallFunction + description: Defines the function call to perform. + $ref: '#/$defs/taskBase' + type: object + unevaluatedProperties: false + required: [ call ] + properties: + call: + type: string + not: + enum: ["asyncapi", "grpc", "http", "openapi"] + description: The name of the function to call. + with: + type: object + title: FunctionArguments + description: A name/value mapping of the parameters, if any, to call the function with. + additionalProperties: true + forkTask: + type: object + $ref: '#/$defs/taskBase' + title: ForkTask + description: Allows workflows to execute multiple tasks concurrently and optionally race them against each other, with a single possible winner, which sets the task's output. + unevaluatedProperties: false + required: [ fork ] + properties: + fork: + type: object + title: ForkTaskConfiguration + description: The configuration of the branches to perform concurrently. + unevaluatedProperties: false + required: [ branches ] + properties: + branches: + $ref: '#/$defs/taskList' + title: ForkBranches + compete: + type: boolean + title: ForkCompete + description: Indicates whether or not the concurrent tasks are racing against each other, with a single possible winner, which sets the composite task's output. + default: false + doTask: + type: object + $ref: '#/$defs/taskBase' + title: DoTask + description: Allows to execute a list of tasks in sequence. + unevaluatedProperties: false + required: [ do ] + properties: + do: + $ref: '#/$defs/taskList' + title: DoTaskConfiguration + description: The configuration of the tasks to perform sequentially. + emitTask: + type: object + $ref: '#/$defs/taskBase' + title: EmitTask + description: Allows workflows to publish events to event brokers or messaging systems, facilitating communication and coordination between different components and services. + required: [ emit ] + unevaluatedProperties: false + properties: + emit: + type: object + title: EmitTaskConfiguration + description: The configuration of an event's emission. + unevaluatedProperties: false + properties: + event: + type: object + title: EmitEventDefinition + description: The definition of the event to emit. + properties: + with: + $ref: '#/$defs/eventProperties' + title: EmitEventWith + description: Defines the properties of event to emit. + required: [ source, type ] + additionalProperties: true + required: [ event ] + forTask: + type: object + $ref: '#/$defs/taskBase' + title: ForTask + description: Allows workflows to iterate over a collection of items, executing a defined set of subtasks for each item in the collection. This task type is instrumental in handling scenarios such as batch processing, data transformation, and repetitive operations across datasets. + required: [ for, do ] + unevaluatedProperties: false + properties: + for: + type: object + title: ForTaskConfiguration + description: The definition of the loop that iterates over a range of values. + unevaluatedProperties: false + properties: + each: + type: string + title: ForEach + description: The name of the variable used to store the current item being enumerated. + default: item + in: + type: string + title: ForIn + description: A runtime expression used to get the collection to enumerate. + at: + type: string + title: ForAt + description: The name of the variable used to store the index of the current item being enumerated. + default: index + required: [ in ] + while: + type: string + title: While + description: A runtime expression that represents the condition, if any, that must be met for the iteration to continue. + do: + $ref: '#/$defs/taskList' + title: ForTaskDo + listenTask: + type: object + $ref: '#/$defs/taskBase' + title: ListenTask + description: Provides a mechanism for workflows to await and react to external events, enabling event-driven behavior within workflow systems. + required: [ listen ] + unevaluatedProperties: false + properties: + listen: + type: object + title: ListenTaskConfiguration + description: The configuration of the listener to use. + unevaluatedProperties: false + properties: + to: + $ref: '#/$defs/eventConsumptionStrategy' + title: ListenTo + description: Defines the event(s) to listen to. + read: + type: string + enum: [ data, envelope, raw ] + default: data + title: ListenAndReadAs + description: Specifies how events are read during the listen operation. + required: [ to ] + foreach: + $ref: '#/$defs/subscriptionIterator' + title: ListenIterator + description: Configures the iterator, if any, for processing consumed event(s). + raiseTask: + type: object + $ref: '#/$defs/taskBase' + title: RaiseTask + description: Intentionally triggers and propagates errors. + required: [ raise ] + unevaluatedProperties: false + properties: + raise: + type: object + title: RaiseTaskConfiguration + description: The definition of the error to raise. + unevaluatedProperties: false + properties: + error: + title: RaiseTaskError + oneOf: + - $ref: '#/$defs/error' + title: RaiseErrorDefinition + description: Defines the error to raise. + - type: string + title: RaiseErrorReference + description: The name of the error to raise + required: [ error ] + runTask: + type: object + $ref: '#/$defs/taskBase' + title: RunTask + description: Provides the capability to execute external containers, shell commands, scripts, or workflows. + required: [ run ] + unevaluatedProperties: false + properties: + run: + type: object + title: RunTaskConfiguration + description: The configuration of the process to execute. + unevaluatedProperties: false + properties: + await: + type: boolean + default: true + title: AwaitProcessCompletion + description: Whether to await the process completion before continuing. + return: + type: string + title: ProcessReturnType + description: Configures the output of the process. + enum: [ stdout, stderr, code, all, none ] + default: stdout + oneOf: + - title: RunContainer + description: Enables the execution of external processes encapsulated within a containerized environment. + properties: + container: + type: object + title: Container + description: The configuration of the container to run. + unevaluatedProperties: false + properties: + image: + type: string + title: ContainerImage + description: The name of the container image to run. + name: + type: string + title: ContainerName + description: A runtime expression, if any, used to give specific name to the container. + command: + type: string + title: ContainerCommand + description: The command, if any, to execute on the container. + ports: + type: object + title: ContainerPorts + description: The container's port mappings, if any. + volumes: + type: object + title: ContainerVolumes + description: The container's volume mappings, if any. + environment: + type: object + title: ContainerEnvironment + description: A key/value mapping of the environment variables, if any, to use when running the configured process. + lifetime: + $ref: '#/$defs/containerLifetime' + title: ContainerLifetime + description: An object, if any, used to configure the container's lifetime + required: [ image ] + required: [ container ] + - title: RunScript + description: Enables the execution of custom scripts or code within a workflow, empowering workflows to perform specialized logic, data processing, or integration tasks by executing user-defined scripts written in various programming languages. + properties: + script: + type: object + title: Script + description: The configuration of the script to run. + unevaluatedProperties: false + properties: + language: + type: string + title: ScriptLanguage + description: The language of the script to run. + arguments: + type: object + title: ScriptArguments + description: A key/value mapping of the arguments, if any, to use when running the configured script. + additionalProperties: true + environment: + type: object + title: ScriptEnvironment + description: A key/value mapping of the environment variables, if any, to use when running the configured script process. + additionalProperties: true + oneOf: + - title: InlineScript + type: object + description: The script's code. + properties: + code: + type: string + title: InlineScriptCode + required: [ code ] + - title: ExternalScript + type: object + description: The script's resource. + properties: + source: + $ref: '#/$defs/externalResource' + title: ExternalScriptResource + required: [ source ] + required: [ language ] + required: [ script ] + - title: RunShell + description: Enables the execution of shell commands within a workflow, enabling workflows to interact with the underlying operating system and perform system-level operations, such as file manipulation, environment configuration, or system administration tasks. + properties: + shell: + type: object + title: Shell + description: The configuration of the shell command to run. + unevaluatedProperties: false + properties: + command: + type: string + title: ShellCommand + description: The shell command to run. + arguments: + type: object + title: ShellArguments + description: A list of the arguments of the shell command to run. + additionalProperties: true + environment: + type: object + title: ShellEnvironment + description: A key/value mapping of the environment variables, if any, to use when running the configured process. + additionalProperties: true + required: [ command ] + required: [ shell ] + - title: RunWorkflow + description: Enables the invocation and execution of nested workflows within a parent workflow, facilitating modularization, reusability, and abstraction of complex logic or business processes by encapsulating them into standalone workflow units. + properties: + workflow: + type: object + title: SubflowConfiguration + description: The configuration of the workflow to run. + unevaluatedProperties: false + properties: + namespace: + type: string + title: SubflowNamespace + description: The namespace the workflow to run belongs to. + name: + type: string + title: SubflowName + description: The name of the workflow to run. + version: + type: string + default: latest + title: SubflowVersion + description: The version of the workflow to run. Defaults to latest. + input: + type: object + title: SubflowInput + description: The data, if any, to pass as input to the workflow to execute. The value should be validated against the target workflow's input schema, if specified. + additionalProperties: true + required: [ namespace, name, version ] + required: [ workflow ] + setTask: + type: object + $ref: '#/$defs/taskBase' + title: SetTask + description: A task used to set data. + required: [ set ] + unevaluatedProperties: false + properties: + set: + type: object + title: SetTaskConfiguration + description: The data to set. + minProperties: 1 + additionalProperties: true + switchTask: + type: object + $ref: '#/$defs/taskBase' + title: SwitchTask + description: Enables conditional branching within workflows, allowing them to dynamically select different paths based on specified conditions or criteria. + required: [ switch ] + unevaluatedProperties: false + properties: + switch: + type: array + title: SwitchTaskConfiguration + description: The definition of the switch to use. + minItems: 1 + items: + type: object + title: SwitchItem + minProperties: 1 + maxProperties: 1 + additionalProperties: + type: object + title: SwitchCase + description: The definition of a case within a switch task, defining a condition and corresponding tasks to execute if the condition is met. + unevaluatedProperties: false + required: [ then ] + properties: + when: + type: string + title: SwitchCaseCondition + description: A runtime expression used to determine whether or not the case matches. + then: + $ref: '#/$defs/flowDirective' + title: SwitchCaseOutcome + description: The flow directive to execute when the case matches. + tryTask: + type: object + $ref: '#/$defs/taskBase' + title: TryTask + description: Serves as a mechanism within workflows to handle errors gracefully, potentially retrying failed tasks before proceeding with alternate ones. + required: [ try, catch ] + unevaluatedProperties: false + properties: + try: + $ref: '#/$defs/taskList' + title: TryTaskConfiguration + description: The task(s) to perform. + catch: + type: object + title: TryTaskCatch + description: The object used to define the errors to catch. + unevaluatedProperties: false + properties: + errors: + type: object + title: CatchErrors + properties: + with: + $ref: '#/$defs/errorFilter' + description: static error filter + as: + type: string + title: CatchAs + description: The name of the runtime expression variable to save the error as. Defaults to 'error'. + when: + type: string + title: CatchWhen + description: A runtime expression used to determine whether to catch the filtered error. + exceptWhen: + type: string + title: CatchExceptWhen + description: A runtime expression used to determine whether not to catch the filtered error. + retry: + oneOf: + - $ref: '#/$defs/retryPolicy' + title: RetryPolicyDefinition + description: The retry policy to use, if any, when catching errors. + - type: string + title: RetryPolicyReference + description: The name of the retry policy to use, if any, when catching errors. + do: + $ref: '#/$defs/taskList' + title: TryTaskCatchDo + description: The definition of the task(s) to run when catching an error. + waitTask: + type: object + $ref: '#/$defs/taskBase' + title: WaitTask + description: Allows workflows to pause or delay their execution for a specified period of time. + required: [ wait ] + unevaluatedProperties: false + properties: + wait: + $ref: '#/$defs/duration' + title: WaitTaskConfiguration + description: The amount of time to wait. + flowDirective: + title: FlowDirective + description: Represents different transition options for a workflow. + anyOf: + - title: FlowDirectiveEnum + type: string + enum: [ continue, exit, end ] + default: continue + - type: string + referenceableAuthenticationPolicy: + type: object + title: ReferenceableAuthenticationPolicy + description: Represents a referenceable authentication policy. + unevaluatedProperties: false + oneOf: + - title: AuthenticationPolicyReference + description: The reference of the authentication policy to use. + properties: + use: + type: string + minLength: 1 + title: ReferenceableAuthenticationPolicyName + description: The name of the authentication policy to use. + required: [use] + - $ref: '#/$defs/authenticationPolicy' + secretBasedAuthenticationPolicy: + type: object + title: SecretBasedAuthenticationPolicy + description: Represents an authentication policy based on secrets. + unevaluatedProperties: false + properties: + use: + type: string + minLength: 1 + title: SecretBasedAuthenticationPolicyName + description: The name of the authentication policy to use. + required: [use] + authenticationPolicy: + type: object + title: AuthenticationPolicy + description: Defines an authentication policy. + oneOf: + - title: BasicAuthenticationPolicy + description: Use basic authentication. + properties: + basic: + type: object + title: BasicAuthenticationPolicyConfiguration + description: The configuration of the basic authentication policy. + unevaluatedProperties: false + oneOf: + - title: BasicAuthenticationProperties + description: Inline configuration of the basic authentication policy. + properties: + username: + type: string + description: The username to use. + password: + type: string + description: The password to use. + required: [ username, password ] + - $ref: '#/$defs/secretBasedAuthenticationPolicy' + title: BasicAuthenticationPolicySecret + description: Secret based configuration of the basic authentication policy. + required: [ basic ] + - title: BearerAuthenticationPolicy + description: Use bearer authentication. + properties: + bearer: + type: object + title: BearerAuthenticationPolicyConfiguration + description: The configuration of the bearer authentication policy. + unevaluatedProperties: false + oneOf: + - title: BearerAuthenticationProperties + description: Inline configuration of the bearer authentication policy. + properties: + token: + type: string + description: The bearer token to use. + required: [ token ] + - $ref: '#/$defs/secretBasedAuthenticationPolicy' + title: BearerAuthenticationPolicySecret + description: Secret based configuration of the bearer authentication policy. + required: [ bearer ] + - title: DigestAuthenticationPolicy + description: Use digest authentication. + properties: + digest: + type: object + title: DigestAuthenticationPolicyConfiguration + description: The configuration of the digest authentication policy. + unevaluatedProperties: false + oneOf: + - title: DigestAuthenticationProperties + description: Inline configuration of the digest authentication policy. + properties: + username: + type: string + description: The username to use. + password: + type: string + description: The password to use. + required: [ username, password ] + - $ref: '#/$defs/secretBasedAuthenticationPolicy' + title: DigestAuthenticationPolicySecret + description: Secret based configuration of the digest authentication policy. + required: [ digest ] + - title: OAuth2AuthenticationPolicy + description: Use OAuth2 authentication. + properties: + oauth2: + type: object + title: OAuth2AuthenticationPolicyConfiguration + description: The configuration of the OAuth2 authentication policy. + unevaluatedProperties: false + oneOf: + - type: object + title: OAuth2ConnectAuthenticationProperties + description: The inline configuration of the OAuth2 authentication policy. + unevaluatedProperties: false + allOf: + - $ref: '#/$defs/oauth2AuthenticationProperties' + - type: object + properties: + endpoints: + type: object + title: OAuth2AuthenticationPropertiesEndpoints + description: The endpoint configurations for OAuth2. + properties: + token: + type: string + format: uri-template + default: /oauth2/token + title: OAuth2TokenEndpoint + description: The relative path to the token endpoint. Defaults to `/oauth2/token`. + revocation: + type: string + format: uri-template + default: /oauth2/revoke + title: OAuth2RevocationEndpoint + description: The relative path to the revocation endpoint. Defaults to `/oauth2/revoke`. + introspection: + type: string + format: uri-template + default: /oauth2/introspect + title: OAuth2IntrospectionEndpoint + description: The relative path to the introspection endpoint. Defaults to `/oauth2/introspect`. + - $ref: '#/$defs/secretBasedAuthenticationPolicy' + title: OAuth2AuthenticationPolicySecret + description: Secret based configuration of the OAuth2 authentication policy. + required: [ oauth2 ] + - title: OpenIdConnectAuthenticationPolicy + description: Use OpenIdConnect authentication. + properties: + oidc: + type: object + title: OpenIdConnectAuthenticationPolicyConfiguration + description: The configuration of the OpenIdConnect authentication policy. + unevaluatedProperties: false + oneOf: + - $ref: '#/$defs/oauth2AuthenticationProperties' + title: OpenIdConnectAuthenticationProperties + description: The inline configuration of the OpenIdConnect authentication policy. + unevaluatedProperties: false + - $ref: '#/$defs/secretBasedAuthenticationPolicy' + title: OpenIdConnectAuthenticationPolicySecret + description: Secret based configuration of the OpenIdConnect authentication policy. + required: [ oidc ] + oauth2AuthenticationProperties: + type: object + title: OAuth2AutenthicationData + description: Inline configuration of the OAuth2 authentication policy. + properties: + authority: + $ref: '#/$defs/uriTemplate' + title: OAuth2AutenthicationDataAuthority + description: The URI that references the OAuth2 authority to use. + grant: + type: string + enum: [ authorization_code, client_credentials, password, refresh_token, 'urn:ietf:params:oauth:grant-type:token-exchange'] + title: OAuth2AutenthicationDataGrant + description: The grant type to use. + client: + type: object + title: OAuth2AutenthicationDataClient + description: The definition of an OAuth2 client. + unevaluatedProperties: false + properties: + id: + type: string + title: ClientId + description: The client id to use. + secret: + type: string + title: ClientSecret + description: The client secret to use, if any. + assertion: + type: string + title: ClientAssertion + description: A JWT containing a signed assertion with your application credentials. + authentication: + type: string + enum: [ client_secret_basic, client_secret_post, client_secret_jwt, private_key_jwt, none ] + default: client_secret_post + title: ClientAuthentication + description: The authentication method to use to authenticate the client. + request: + type: object + title: OAuth2TokenRequest + description: The configuration of an OAuth2 token request + properties: + encoding: + type: string + enum: [ 'application/x-www-form-urlencoded', 'application/json' ] + default: 'application/x-www-form-urlencoded' + title: Oauth2TokenRequestEncoding + issuers: + type: array + title: OAuth2Issuers + description: A list that contains that contains valid issuers that will be used to check against the issuer of generated tokens. + items: + type: string + scopes: + type: array + title: OAuth2AutenthicationDataScopes + description: The scopes, if any, to request the token for. + items: + type: string + audiences: + type: array + title: OAuth2AutenthicationDataAudiences + description: The audiences, if any, to request the token for. + items: + type: string + username: + type: string + title: OAuth2AutenthicationDataUsername + description: The username to use. Used only if the grant type is Password. + password: + type: string + title: OAuth2AutenthicationDataPassword + description: The password to use. Used only if the grant type is Password. + subject: + $ref: '#/$defs/oauth2Token' + title: OAuth2AutenthicationDataSubject + description: The security token that represents the identity of the party on behalf of whom the request is being made. + actor: + $ref: '#/$defs/oauth2Token' + title: OAuth2AutenthicationDataActor + description: The security token that represents the identity of the acting party. + oauth2Token: + type: object + title: OAuth2TokenDefinition + description: Represents an OAuth2 token. + unevaluatedProperties: false + properties: + token: + type: string + title: OAuth2Token + description: The security token to use. + type: + type: string + title: OAuth2TokenType + description: The type of the security token to use. + required: [ token, type ] + duration: + oneOf: + - type: object + minProperties: 1 + unevaluatedProperties: false + properties: + days: + type: integer + title: DurationDays + description: Number of days, if any. + hours: + type: integer + title: DurationHours + description: Number of days, if any. + minutes: + type: integer + title: DurationMinutes + description: Number of minutes, if any. + seconds: + type: integer + title: DurationSeconds + description: Number of seconds, if any. + milliseconds: + type: integer + title: DurationMilliseconds + description: Number of milliseconds, if any. + title: DurationInline + description: The inline definition of a duration. + - type: string + pattern: '^P(?!$)(\d+(?:\.\d+)?Y)?(\d+(?:\.\d+)?M)?(\d+(?:\.\d+)?W)?(\d+(?:\.\d+)?D)?(T(?=\d)(\d+(?:\.\d+)?H)?(\d+(?:\.\d+)?M)?(\d+(?:\.\d+)?S)?)?$' + title: DurationExpression + description: The ISO 8601 expression of a duration. + error: + type: object + title: Error + description: Represents an error. + unevaluatedProperties: false + properties: + type: + title: ErrorType + description: A URI reference that identifies the error type. + oneOf: + - title: LiteralErrorType + $ref: '#/$defs/uriTemplate' + description: The literal error type. + - title: ExpressionErrorType + $ref: '#/$defs/runtimeExpression' + description: An expression based error type. + status: + type: integer + title: ErrorStatus + description: The status code generated by the origin for this occurrence of the error. + instance: + title: ErrorInstance + description: A JSON Pointer used to reference the component the error originates from. + oneOf: + - title: LiteralErrorInstance + description: The literal error instance. + type: string + format: json-pointer + - $ref: '#/$defs/runtimeExpression' + title: ExpressionErrorInstance + description: An expression based error instance. + title: + type: string + title: ErrorTitle + description: A short, human-readable summary of the error. + detail: + type: string + title: ErrorDetails + description: A human-readable explanation specific to this occurrence of the error. + required: [ type, status ] + errorFilter: + type: object + title: ErrorFilter + description: Error filtering base on static values. For error filtering on dynamic values, use catch.when property + minProperties: 1 + properties: + type: + type: string + description: if present, means this value should be used for filtering + status: + type: integer + description: if present, means this value should be used for filtering + instance: + type: string + description: if present, means this value should be used for filtering + title: + type: string + description: if present, means this value should be used for filtering + details: + type: string + description: if present, means this value should be used for filtering + uriTemplate: + title: UriTemplate + anyOf: + - title: LiteralUriTemplate + type: string + format: uri-template + pattern: "^[A-Za-z][A-Za-z0-9+\\-.]*://.*" + - title: LiteralUri + type: string + format: uri + pattern: "^[A-Za-z][A-Za-z0-9+\\-.]*://.*" + endpoint: + title: Endpoint + description: Represents an endpoint. + oneOf: + - $ref: '#/$defs/runtimeExpression' + - $ref: '#/$defs/uriTemplate' + - title: EndpointConfiguration + type: object + unevaluatedProperties: false + properties: + uri: + title: EndpointUri + description: The endpoint's URI. + oneOf: + - title: LiteralEndpointURI + description: The literal endpoint's URI. + $ref: '#/$defs/uriTemplate' + - title: ExpressionEndpointURI + $ref: '#/$defs/runtimeExpression' + description: An expression based endpoint's URI. + authentication: + $ref: '#/$defs/referenceableAuthenticationPolicy' + title: EndpointAuthentication + description: The authentication policy to use. + required: [ uri ] + eventProperties: + type: object + title: EventProperties + description: Describes the properties of an event. + properties: + id: + type: string + title: EventId + description: The event's unique identifier. + source: + title: EventSource + description: Identifies the context in which an event happened. + oneOf: + - $ref: '#/$defs/uriTemplate' + - $ref: '#/$defs/runtimeExpression' + type: + type: string + title: EventType + description: This attribute contains a value describing the type of event related to the originating occurrence. + time: + title: EventTime + description: When the event occured. + oneOf: + - title: LiteralTime + type: string + format: date-time + - $ref: '#/$defs/runtimeExpression' + subject: + type: string + title: EventSubject + description: The subject of the event. + datacontenttype: + type: string + title: EventDataContentType + description: Content type of data value. This attribute enables data to carry any type of content, whereby format and encoding might differ from that of the chosen event format. + dataschema: + title: EventDataschema + description: The schema describing the event format. + oneOf: + - title: LiteralDataSchema + $ref: '#/$defs/uriTemplate' + description: The literal event data schema. + - title: ExpressionDataSchema + $ref: '#/$defs/runtimeExpression' + description: An expression based event data schema. + data: + title: EventData + description: The event's payload data + anyOf: + - $ref: '#/$defs/runtimeExpression' + - {} + additionalProperties: true + eventConsumptionStrategy: + type: object + title: EventConsumptionStrategy + description: Describe the event consumption strategy to adopt. + unevaluatedProperties: false + oneOf: + - title: AllEventConsumptionStrategy + properties: + all: + type: array + title: AllEventConsumptionStrategyConfiguration + description: A list containing all the events that must be consumed. + items: + $ref: '#/$defs/eventFilter' + required: [ all ] + - title: AnyEventConsumptionStrategy + properties: + any: + type: array + title: AnyEventConsumptionStrategyConfiguration + description: A list containing any of the events to consume. + items: + $ref: '#/$defs/eventFilter' + until: + oneOf: + - type: string + title: AnyEventUntilCondition + description: A runtime expression condition evaluated after consuming an event and which determines whether or not to continue listening. + - allOf: + - $ref: '#/$defs/eventConsumptionStrategy' + description: The strategy that defines the event(s) to consume to stop listening. + - properties: + until: false + title: AnyEventUntilConsumed + required: [ any ] + - title: OneEventConsumptionStrategy + properties: + one: + $ref: '#/$defs/eventFilter' + title: OneEventConsumptionStrategyConfiguration + description: The single event to consume. + required: [ one ] + eventFilter: + type: object + title: EventFilter + description: An event filter is a mechanism used to selectively process or handle events based on predefined criteria, such as event type, source, or specific attributes. + unevaluatedProperties: false + properties: + with: + $ref: '#/$defs/eventProperties' + minProperties: 1 + title: WithEvent + description: An event filter is a mechanism used to selectively process or handle events based on predefined criteria, such as event type, source, or specific attributes. + correlate: + type: object + title: EventFilterCorrelate + description: A correlation is a link between events and data, established by mapping event attributes to specific data attributes, allowing for coordinated processing or handling based on event characteristics. + additionalProperties: + type: object + properties: + from: + type: string + title: CorrelateFrom + description: A runtime expression used to extract the correlation value from the filtered event. + expect: + type: string + title: CorrelateExpect + description: A constant or a runtime expression, if any, used to determine whether or not the extracted correlation value matches expectations. If not set, the first extracted value will be used as the correlation's expectation. + required: [ from ] + required: [ with ] + extension: + type: object + title: Extension + description: The definition of an extension. + unevaluatedProperties: false + properties: + extend: + type: string + enum: [ call, composite, emit, for, listen, raise, run, set, switch, try, wait, all ] + title: ExtensionTarget + description: The type of task to extend. + when: + type: string + title: ExtensionCondition + description: A runtime expression, if any, used to determine whether or not the extension should apply in the specified context. + before: + $ref: '#/$defs/taskList' + title: ExtensionDoBefore + description: The task(s) to execute before the extended task, if any. + after: + $ref: '#/$defs/taskList' + title: ExtensionDoAfter + description: The task(s) to execute after the extended task, if any. + required: [ extend ] + externalResource: + type: object + title: ExternalResource + description: Represents an external resource. + unevaluatedProperties: false + properties: + name: + type: string + title: ExternalResourceName + description: The name of the external resource, if any. + endpoint: + $ref: '#/$defs/endpoint' + title: ExternalResourceEndpoint + description: The endpoint of the external resource. + required: [ endpoint ] + input: + type: object + title: Input + description: Configures the input of a workflow or task. + unevaluatedProperties: false + properties: + schema: + $ref: '#/$defs/schema' + title: InputSchema + description: The schema used to describe and validate the input of the workflow or task. + from: + title: InputFrom + description: A runtime expression, if any, used to mutate and/or filter the input of the workflow or task. + oneOf: + - type: string + - type: object + output: + type: object + title: Output + description: Configures the output of a workflow or task. + unevaluatedProperties: false + properties: + schema: + $ref: '#/$defs/schema' + title: OutputSchema + description: The schema used to describe and validate the output of the workflow or task. + as: + title: OutputAs + description: A runtime expression, if any, used to mutate and/or filter the output of the workflow or task. + oneOf: + - type: string + - type: object + export: + type: object + title: Export + description: Set the content of the context. . + unevaluatedProperties: false + properties: + schema: + $ref: '#/$defs/schema' + title: ExportSchema + description: The schema used to describe and validate the workflow context. + as: + title: ExportAs + description: A runtime expression, if any, used to export the output data to the context. + oneOf: + - type: string + - type: object + retryPolicy: + type: object + title: RetryPolicy + description: Defines a retry policy. + unevaluatedProperties: false + properties: + when: + type: string + title: RetryWhen + description: A runtime expression, if any, used to determine whether or not to retry running the task, in a given context. + exceptWhen: + type: string + title: RetryExcepWhen + description: A runtime expression used to determine whether or not to retry running the task, in a given context. + delay: + $ref: '#/$defs/duration' + title: RetryDelay + description: The duration to wait between retry attempts. + backoff: + type: object + title: RetryBackoff + description: The retry duration backoff. + unevaluatedProperties: false + oneOf: + - title: ConstantBackoff + properties: + constant: + type: object + description: The definition of the constant backoff to use, if any. + required: [ constant ] + - title: ExponentialBackOff + properties: + exponential: + type: object + description: The definition of the exponential backoff to use, if any. + required: [ exponential ] + - title: LinearBackoff + properties: + linear: + type: object + description: The definition of the linear backoff to use, if any. + required: [ linear ] + limit: + type: object + title: RetryLimit + unevaluatedProperties: false + properties: + attempt: + type: object + title: RetryLimitAttempt + unevaluatedProperties: false + properties: + count: + type: integer + title: RetryLimitAttemptCount + description: The maximum amount of retry attempts, if any. + duration: + $ref: '#/$defs/duration' + title: RetryLimitAttemptDuration + description: The maximum duration for each retry attempt. + duration: + $ref: '#/$defs/duration' + title: RetryLimitDuration + description: The duration limit, if any, for all retry attempts. + description: The retry limit, if any. + jitter: + type: object + title: RetryPolicyJitter + description: The parameters, if any, that control the randomness or variability of the delay between retry attempts. + unevaluatedProperties: false + properties: + from: + $ref: '#/$defs/duration' + title: RetryPolicyJitterFrom + description: The minimum duration of the jitter range. + to: + $ref: '#/$defs/duration' + title: RetryPolicyJitterTo + description: The maximum duration of the jitter range. + required: [ from, to ] + schema: + type: object + title: Schema + description: Represents the definition of a schema. + unevaluatedProperties: false + properties: + format: + type: string + default: json + title: SchemaFormat + description: The schema's format. Defaults to 'json'. The (optional) version of the format can be set using `{format}:{version}`. + oneOf: + - title: SchemaInline + properties: + document: + description: The schema's inline definition. + required: [ document ] + - title: SchemaExternal + properties: + resource: + $ref: '#/$defs/externalResource' + title: SchemaExternalResource + description: The schema's external resource. + required: [ resource ] + timeout: + type: object + title: Timeout + description: The definition of a timeout. + unevaluatedProperties: false + properties: + after: + $ref: '#/$defs/duration' + title: TimeoutAfter + description: The duration after which to timeout. + required: [ after ] + catalog: + type: object + title: Catalog + description: The definition of a resource catalog. + unevaluatedProperties: false + properties: + endpoint: + $ref: '#/$defs/endpoint' + title: CatalogEndpoint + description: The root URL where the catalog is hosted. + required: [ endpoint ] + runtimeExpression: + type: string + title: RuntimeExpression + description: A runtime expression. + pattern: "^\\s*\\$\\{.+\\}\\s*$" + containerLifetime: + type: object + title: ContainerLifetime + description: The configuration of a container's lifetime + unevaluatedProperties: false + properties: + cleanup: + type: string + title: ContainerCleanupPolicy + description: The container cleanup policy to use + enum: [ always, never, eventually ] + default: never + after: + $ref: '#/$defs/duration' + title: ContainerLifetimeDuration + description: The duration after which to cleanup the container, in case the cleanup policy has been set to 'eventually' + required: [ cleanup ] + if: + properties: + cleanup: + const: eventually + then: + required: [ after ] + else: + not: + required: [ after ] + processResult: + type: object + title: ProcessResult + description: The object returned by a run task when its return type has been set 'all'. + unevaluatedProperties: false + properties: + code: + type: integer + title: ProcessExitCode + description: The process's exit code. + stdout: + type: string + title: ProcessStandardOutput + description: The content of the process's STDOUT. + stderr: + type: string + title: ProcessStandardError + description: The content of the process's STDERR. + required: [ code, stdout, stderr ] + asyncApiServer: + type: object + title: AsyncApiServer + description: Configures the target server of an AsyncAPI operation. + unevaluatedProperties: false + properties: + name: + type: string + title: AsyncApiServerName + description: The target server's name. + variables: + type: object + title: AsyncApiServerVariables + description: The target server's variables, if any. + required: [ name ] + asyncApiOutboundMessage: + type: object + title: AsyncApiOutboundMessage + description: An object used to configure the message to publish using the target operation. + unevaluatedProperties: false + properties: + payload: + type: object + title: AsyncApiMessagePayload + description: The message's payload, if any. + additionalProperties: true + headers: + type: object + title: AsyncApiMessageHeaders + description: The message's headers, if any. + additionalProperties: true + asyncApiInboundMessage: + type: object + title: AsyncApiInboundMessage + description: Represents a message counsumed by an AsyncAPI subscription. + allOf: + - $ref: '#/$defs/asyncApiOutboundMessage' + properties: + correlationId: + type: string + title: AsyncApiMessageCorrelationId + description: The message's correlation id, if any. + asyncApiSubscription: + type: object + title: AsyncApiSubscription + description: An object used to configure the subscription to messages consumed using the target operation. + unevaluatedProperties: false + properties: + filter: + $ref: '#/$defs/runtimeExpression' + title: AsyncApiSubscriptionCorrelation + description: A runtime expression, if any, used to filter consumed messages. + consume: + $ref: '#/$defs/asyncApiMessageConsumptionPolicy' + title: AsyncApiMessageConsumptionPolicy + description: An object used to configure the subscription's message consumption policy. + foreach: + $ref: '#/$defs/subscriptionIterator' + title: AsyncApiSubscriptionIterator + description: Configures the iterator, if any, for processing consumed messages(s). + required: [ consume ] + asyncApiMessageConsumptionPolicy: + type: object + title: AsyncApiMessageConsumptionPolicy + description: An object used to configure a subscription's message consumption policy. + unevaluatedProperties: false + properties: + for: + $ref: '#/$defs/duration' + title: AsyncApiMessageConsumptionPolicyFor + description: Specifies the time period over which messages will be consumed. + oneOf: + - properties: + amount: + type: integer + description: The amount of (filtered) messages to consume before disposing of the subscription. + title: AsyncApiMessageConsumptionPolicyAmount + required: [ amount ] + - properties: + while: + $ref: '#/$defs/runtimeExpression' + description: A runtime expression evaluated after each consumed (filtered) message to decide if message consumption should continue. + title: AsyncApiMessageConsumptionPolicyWhile + required: [ while ] + - properties: + until: + $ref: '#/$defs/runtimeExpression' + description: A runtime expression evaluated before each consumed (filtered) message to decide if message consumption should continue. + title: AsyncApiMessageConsumptionPolicyUntil + required: [ until ] + subscriptionIterator: + type: object + title: SubscriptionIterator + description: Configures the iteration over each item (event or message) consumed by a subscription. + unevaluatedProperties: false + properties: + item: + type: string + title: SubscriptionIteratorItem + description: The name of the variable used to store the current item being enumerated. + default: item + at: + type: string + title: SubscriptionIteratorIndex + description: The name of the variable used to store the index of the current item being enumerated. + default: index + do: + $ref: '#/$defs/taskList' + title: SubscriptionIteratorTasks + description: The tasks to perform for each consumed item. + output: + $ref: '#/$defs/output' + title: SubscriptionIteratorOutput + description: An object, if any, used to customize the item's output and to document its schema. + export: + $ref: '#/$defs/export' + title: SubscriptionIteratorExport + description: An object, if any, used to customize the content of the workflow context. \ No newline at end of file diff --git a/src/consts.ts b/src/consts.ts index 2dd5f37..4cb63f8 100644 --- a/src/consts.ts +++ b/src/consts.ts @@ -1,6 +1,8 @@ export const DEFAULT_TITLE = 'Serverless Workflow'; export const DEFAULT_DESC = `Serverless Workflow presents a vendor-neutral, open-source, and entirely community-driven ecosystem tailored for defining and executing DSL-based workflows in the realm of Serverless technology.`; +export const CURRENT_VERSION = '1.0.0'; + export const GITHUB_ORG = 'https://github.com/serverlessworkflow/'; export const GITHUB_LINK = GITHUB_ORG + 'specification/'; export const SLACK_LINK = 'https://slack.cncf.io/'; diff --git a/src/content/blog/releases/release-1.0.0.md b/src/content/blog/releases/release-1.0.0.md new file mode 100644 index 0000000..fc62f86 --- /dev/null +++ b/src/content/blog/releases/release-1.0.0.md @@ -0,0 +1,33 @@ +--- +title: Serverless Workflow 1.0.0 Release +author: Jean-Baptiste Bianchi +date: 2025-01-27 +description: > + Serverless Workflow v1.0.0 is out ! +--- + +🎉 Celebrating the **1.0.0** Release of the Serverless Workflow Specification - Five Years in the Making ! 🎉 + +It’s been half a decade since the first release of the **Serverless Workflow Specification**, and we’re proud to share our biggest milestone yet: **Version 1.0.0**. This marks a new era of event-driven, function-centric, and service-oriented workflow design—backed by a vibrant community and robust ecosystem. + +## ⭐ Key Enhancements and Features ⭐ +- ✅ **Refined Grammar & Semantics** – Cleaner, more readable DSL for effortless workflow design. +- ✅ **Unified Task Concept** – Merge states and actions into tasks, simplifying definitions and removing nesting limits. +- ✅ **Easy Function Invocation** – Seamlessly call HTTP, gRPC, OpenAPI, or AsyncAPI services. +- ✅ **Event Driven** – Ingest events for real-time triggers and correlations. +- ✅ **Streaming Support** – Leverage AsyncAPI and CloudEvent subscriptions for continuous data flow. +- ✅ **Fault Tolerance & Timeouts** – Built-in error handling, retries, and timeout management for greater reliability. +- ✅ **Scheduling & Concurrency** – CRON-based triggers and parallel event handling let you run workflows exactly when—and how—you need. +- ✅ **Extensibility** – Extend or override the DSL without writing extra code, ensuring runtime-agnostic portability. +- ✅ **Code Reusability & Maintainability** – Scale effortlessly with cleaner, modular definitions. +- ✅ **Behavior Driven Design** – Gherkin-based features ensure consistent, standardized testing and implementations. + +## 💡 Why this Matters 💡 +**Serverless Workflow 1.0.0** makes building reliable, event-driven, and function-centric systems easier than ever—whether you’re running on public cloud, private cloud, or hybrid environments. The result? Faster development, resilient architectures, and streamlined operations at scale. + +## 📢 Get Involved 📢 +A heartfelt thank you to the entire community—contributors, maintainers, and adopters—who have shaped and refined this specification over the last five years. We couldn’t have done it without you! + +- ➜ **Check out the Official Docs**: https://github.com/serverlessworkflow/specification/blob/main/README.md +- ➜ **Join the Conversation**: https://cloud-native.slack.com/?redir=%2Fmessages%2Fserverless-workflow +- ➜ **Contribute**: Your ideas, feedback, and experiences are what keep the Serverless Workflow Specification thriving. \ No newline at end of file diff --git a/src/content/examples/async-api.md b/src/content/examples/async-api.md index ef9ed9f..3799558 100644 --- a/src/content/examples/async-api.md +++ b/src/content/examples/async-api.md @@ -2,8 +2,8 @@ title: Async API --- document: - dsl: '1.0.0-alpha5' - namespace: examples + dsl: '1.0.0' + namespace: default name: call-asyncapi version: '1.0.0' do: diff --git a/src/content/examples/container.md b/src/content/examples/container.md index 4cf380a..41c4f3c 100644 --- a/src/content/examples/container.md +++ b/src/content/examples/container.md @@ -2,8 +2,8 @@ title: Container --- document: - dsl: '1.0.0-alpha5' - namespace: examples + dsl: '1.0.0' + namespace: default name: run-container version: '1.0.0' do: diff --git a/src/content/examples/emit.md b/src/content/examples/emit.md index 11e57f4..8f09378 100644 --- a/src/content/examples/emit.md +++ b/src/content/examples/emit.md @@ -2,8 +2,8 @@ title: Emit Event --- document: - dsl: '1.0.0-alpha5' - namespace: test + dsl: '1.0.0' + namespace: default name: emit version: '0.1.0' do: diff --git a/src/content/examples/for.md b/src/content/examples/for.md index bab77cb..d306a79 100644 --- a/src/content/examples/for.md +++ b/src/content/examples/for.md @@ -2,8 +2,8 @@ title: For --- document: - dsl: '1.0.0-alpha5' - namespace: test + dsl: '1.0.0' + namespace: default name: for-example version: '0.1.0' do: diff --git a/src/content/examples/fork.md b/src/content/examples/fork.md index 81765c5..7354dc9 100644 --- a/src/content/examples/fork.md +++ b/src/content/examples/fork.md @@ -2,8 +2,8 @@ title: Fork --- document: - dsl: '1.0.0-alpha5' - namespace: test + dsl: '1.0.0' + namespace: default name: fork-example version: '0.1.0' do: diff --git a/src/content/examples/grpc.md b/src/content/examples/grpc.md index c85f049..f7c06f7 100644 --- a/src/content/examples/grpc.md +++ b/src/content/examples/grpc.md @@ -2,8 +2,8 @@ title: gRPC --- document: - dsl: '1.0.0-alpha5' - namespace: examples + dsl: '1.0.0' + namespace: default name: call-grpc version: '1.0.0' do: diff --git a/src/content/examples/http.md b/src/content/examples/http.md index 3b11b5a..c47ec6f 100644 --- a/src/content/examples/http.md +++ b/src/content/examples/http.md @@ -2,8 +2,8 @@ title: HTTP --- document: - dsl: '1.0.0-alpha5' - namespace: examples + dsl: '1.0.0' + namespace: default name: call-http version: '1.0.0' do: diff --git a/src/content/examples/listen.md b/src/content/examples/listen.md index 6d27936..1dcb604 100644 --- a/src/content/examples/listen.md +++ b/src/content/examples/listen.md @@ -2,8 +2,8 @@ title: Listen Event --- document: - dsl: '1.0.0-alpha5' - namespace: test + dsl: '1.0.0' + namespace: default name: listen-to-all version: '0.1.0' do: diff --git a/src/content/examples/open-api.md b/src/content/examples/open-api.md index e3064fb..b5dd344 100644 --- a/src/content/examples/open-api.md +++ b/src/content/examples/open-api.md @@ -2,8 +2,8 @@ title: Open API --- document: - dsl: '1.0.0-alpha5' - namespace: examples + dsl: '1.0.0' + namespace: default name: call-openapi version: '1.0.0' do: diff --git a/src/content/examples/raise.md b/src/content/examples/raise.md index 93ee2b0..12940b0 100644 --- a/src/content/examples/raise.md +++ b/src/content/examples/raise.md @@ -2,8 +2,8 @@ title: Raise Error --- document: - dsl: '1.0.0-alpha5' - namespace: test + dsl: '1.0.0' + namespace: default name: raise-not-implemented version: '0.1.0' do: diff --git a/src/content/examples/script.md b/src/content/examples/script.md index 4d1e7ad..45d1393 100644 --- a/src/content/examples/script.md +++ b/src/content/examples/script.md @@ -2,7 +2,7 @@ title: Script --- document: - dsl: '1.0.0-alpha5' + dsl: '1.0.0' namespace: samples name: run-script-with-arguments version: 0.1.0 diff --git a/src/content/examples/subflow.md b/src/content/examples/subflow.md index b8bcfac..9a9e8fb 100644 --- a/src/content/examples/subflow.md +++ b/src/content/examples/subflow.md @@ -2,15 +2,15 @@ title: Subflow --- document: - dsl: '1.0.0-alpha5' - namespace: test + dsl: '1.0.0' + namespace: default name: run-subflow version: '0.1.0' do: - registerCustomer: run: workflow: - namespace: test + namespace: default name: register-customer version: '0.1.0' input: diff --git a/src/content/examples/switch.md b/src/content/examples/switch.md index 8b731da..071251a 100644 --- a/src/content/examples/switch.md +++ b/src/content/examples/switch.md @@ -2,8 +2,8 @@ title: Switch --- document: - dsl: '1.0.0-alpha5' - namespace: test + dsl: '1.0.0' + namespace: default name: switch-example version: '0.1.0' do: diff --git a/src/content/examples/try.md b/src/content/examples/try.md index 737b9fa..74ca7a8 100644 --- a/src/content/examples/try.md +++ b/src/content/examples/try.md @@ -2,7 +2,7 @@ title: Try-Catch --- document: - dsl: '1.0.0-alpha5' + dsl: '1.0.0' namespace: default name: try-catch version: '0.1.0' diff --git a/src/content/examples/wait.md b/src/content/examples/wait.md index f5eb5b9..2324633 100644 --- a/src/content/examples/wait.md +++ b/src/content/examples/wait.md @@ -2,8 +2,8 @@ title: Wait --- document: - dsl: '1.0.0-alpha5' - namespace: test + dsl: '1.0.0' + namespace: default name: wait-duration-inline version: '0.1.0' do: diff --git a/src/pages/index.astro b/src/pages/index.astro index 34e70ba..7742837 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -1,5 +1,5 @@ --- -import { GITHUB_LINK, GITHUB_ORG } from '../consts'; +import { CURRENT_VERSION, GITHUB_LINK, GITHUB_ORG } from '../consts'; import Layout from '../layouts/Layout.astro'; import Card from '../components/Card.astro'; import Section from '../components/Section.astro'; @@ -21,7 +21,7 @@ const examples = (await getCollection('example'));

    Serverless Workflow

    Serverless Workflow presents a vendor-neutral, open-source, and entirely community-driven ecosystem tailored for defining and executing DSL-based workflows in the realm of Serverless technology.

    -

    The current version is 1.0.0-alpha5, get the JSON Schema here: YAML or JSON

    +

    The current version is {CURRENT_VERSION}, get the JSON Schema here: YAML or JSON

    Learn More